1
0
Fork 0

Add HTTPUrlRewrite Filter in Gateway API

This commit is contained in:
Manuel Zapf 2024-06-13 17:06:04 +02:00 committed by GitHub
parent 3ca667a3d4
commit a696f7c654
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 754 additions and 110 deletions

View file

@ -18,8 +18,9 @@ const (
)
type redirect struct {
name string
next http.Handler
name string
next http.Handler
scheme *string
hostname *string
port *string

View file

@ -2,7 +2,6 @@ package redirect
import (
"context"
"crypto/tls"
"net/http"
"net/http/httptest"
"testing"
@ -15,15 +14,12 @@ import (
func TestRequestRedirectHandler(t *testing.T) {
testCases := []struct {
desc string
config dynamic.RequestRedirect
method string
url string
headers map[string]string
secured bool
expectedURL string
expectedStatus int
errorExpected bool
desc string
config dynamic.RequestRedirect
url string
wantURL string
wantStatus int
wantErr bool
}{
{
desc: "wrong status code",
@ -31,44 +27,44 @@ func TestRequestRedirectHandler(t *testing.T) {
Path: ptr.To("/baz"),
StatusCode: http.StatusOK,
},
url: "http://foo.com:80/foo/bar",
errorExpected: true,
url: "http://foo.com:80/foo/bar",
wantErr: true,
},
{
desc: "replace path",
config: dynamic.RequestRedirect{
Path: ptr.To("/baz"),
},
url: "http://foo.com:80/foo/bar",
expectedURL: "http://foo.com:80/baz",
expectedStatus: http.StatusFound,
url: "http://foo.com:80/foo/bar",
wantURL: "http://foo.com:80/baz",
wantStatus: http.StatusFound,
},
{
desc: "replace path without trailing slash",
config: dynamic.RequestRedirect{
Path: ptr.To("/baz"),
},
url: "http://foo.com:80/foo/bar/",
expectedURL: "http://foo.com:80/baz",
expectedStatus: http.StatusFound,
url: "http://foo.com:80/foo/bar/",
wantURL: "http://foo.com:80/baz",
wantStatus: http.StatusFound,
},
{
desc: "replace path with trailing slash",
config: dynamic.RequestRedirect{
Path: ptr.To("/baz/"),
},
url: "http://foo.com:80/foo/bar",
expectedURL: "http://foo.com:80/baz/",
expectedStatus: http.StatusFound,
url: "http://foo.com:80/foo/bar",
wantURL: "http://foo.com:80/baz/",
wantStatus: http.StatusFound,
},
{
desc: "only hostname",
config: dynamic.RequestRedirect{
Hostname: ptr.To("bar.com"),
},
url: "http://foo.com:8080/foo/",
expectedURL: "http://bar.com:8080/foo/",
expectedStatus: http.StatusFound,
url: "http://foo.com:8080/foo/",
wantURL: "http://bar.com:8080/foo/",
wantStatus: http.StatusFound,
},
{
desc: "replace prefix path",
@ -76,9 +72,9 @@ func TestRequestRedirectHandler(t *testing.T) {
Path: ptr.To("/baz"),
PathPrefix: ptr.To("/foo"),
},
url: "http://foo.com:80/foo/bar",
expectedURL: "http://foo.com:80/baz/bar",
expectedStatus: http.StatusFound,
url: "http://foo.com:80/foo/bar",
wantURL: "http://foo.com:80/baz/bar",
wantStatus: http.StatusFound,
},
{
desc: "replace prefix path with trailing slash",
@ -86,9 +82,9 @@ func TestRequestRedirectHandler(t *testing.T) {
Path: ptr.To("/baz"),
PathPrefix: ptr.To("/foo"),
},
url: "http://foo.com:80/foo/bar/",
expectedURL: "http://foo.com:80/baz/bar/",
expectedStatus: http.StatusFound,
url: "http://foo.com:80/foo/bar/",
wantURL: "http://foo.com:80/baz/bar/",
wantStatus: http.StatusFound,
},
{
desc: "replace prefix path without slash prefix",
@ -96,9 +92,9 @@ func TestRequestRedirectHandler(t *testing.T) {
Path: ptr.To("baz"),
PathPrefix: ptr.To("/foo"),
},
url: "http://foo.com:80/foo/bar",
expectedURL: "http://foo.com:80/baz/bar",
expectedStatus: http.StatusFound,
url: "http://foo.com:80/foo/bar",
wantURL: "http://foo.com:80/baz/bar",
wantStatus: http.StatusFound,
},
{
desc: "replace prefix path without slash prefix",
@ -106,9 +102,9 @@ func TestRequestRedirectHandler(t *testing.T) {
Path: ptr.To("/baz"),
PathPrefix: ptr.To("/foo/"),
},
url: "http://foo.com:80/foo/bar",
expectedURL: "http://foo.com:80/baz/bar",
expectedStatus: http.StatusFound,
url: "http://foo.com:80/foo/bar",
wantURL: "http://foo.com:80/baz/bar",
wantStatus: http.StatusFound,
},
{
desc: "simple redirection",
@ -117,9 +113,9 @@ func TestRequestRedirectHandler(t *testing.T) {
Hostname: ptr.To("foobar.com"),
Port: ptr.To("443"),
},
url: "http://foo.com:80",
expectedURL: "https://foobar.com:443",
expectedStatus: http.StatusFound,
url: "http://foo.com:80",
wantURL: "https://foobar.com:443",
wantStatus: http.StatusFound,
},
{
desc: "HTTP to HTTPS permanent",
@ -127,9 +123,9 @@ func TestRequestRedirectHandler(t *testing.T) {
Scheme: ptr.To("https"),
StatusCode: http.StatusMovedPermanently,
},
url: "http://foo",
expectedURL: "https://foo",
expectedStatus: http.StatusMovedPermanently,
url: "http://foo",
wantURL: "https://foo",
wantStatus: http.StatusMovedPermanently,
},
{
desc: "HTTPS to HTTP permanent",
@ -137,10 +133,9 @@ func TestRequestRedirectHandler(t *testing.T) {
Scheme: ptr.To("http"),
StatusCode: http.StatusMovedPermanently,
},
secured: true,
url: "https://foo",
expectedURL: "http://foo",
expectedStatus: http.StatusMovedPermanently,
url: "https://foo",
wantURL: "http://foo",
wantStatus: http.StatusMovedPermanently,
},
{
desc: "HTTP to HTTPS",
@ -148,9 +143,9 @@ func TestRequestRedirectHandler(t *testing.T) {
Scheme: ptr.To("https"),
Port: ptr.To("443"),
},
url: "http://foo:80",
expectedURL: "https://foo:443",
expectedStatus: http.StatusFound,
url: "http://foo:80",
wantURL: "https://foo:443",
wantStatus: http.StatusFound,
},
{
desc: "HTTP to HTTPS, with X-Forwarded-Proto",
@ -158,12 +153,9 @@ func TestRequestRedirectHandler(t *testing.T) {
Scheme: ptr.To("https"),
Port: ptr.To("443"),
},
url: "http://foo:80",
headers: map[string]string{
"X-Forwarded-Proto": "https",
},
expectedURL: "https://foo:443",
expectedStatus: http.StatusFound,
url: "http://foo:80",
wantURL: "https://foo:443",
wantStatus: http.StatusFound,
},
{
desc: "HTTPS to HTTP",
@ -171,10 +163,9 @@ func TestRequestRedirectHandler(t *testing.T) {
Scheme: ptr.To("http"),
Port: ptr.To("80"),
},
secured: true,
url: "https://foo:443",
expectedURL: "http://foo:80",
expectedStatus: http.StatusFound,
url: "https://foo:443",
wantURL: "http://foo:80",
wantStatus: http.StatusFound,
},
{
desc: "HTTP to HTTP",
@ -182,9 +173,9 @@ func TestRequestRedirectHandler(t *testing.T) {
Scheme: ptr.To("http"),
Port: ptr.To("88"),
},
url: "http://foo:80",
expectedURL: "http://foo:88",
expectedStatus: http.StatusFound,
url: "http://foo:80",
wantURL: "http://foo:88",
wantStatus: http.StatusFound,
},
}
@ -193,45 +184,32 @@ func TestRequestRedirectHandler(t *testing.T) {
t.Parallel()
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
handler, err := NewRequestRedirect(context.Background(), next, test.config, "traefikTest")
if test.errorExpected {
handler, err := NewRequestRedirect(context.Background(), next, test.config, "traefikTest")
if test.wantErr {
require.Error(t, err)
require.Nil(t, handler)
} else {
return
}
require.NoError(t, err)
require.NotNil(t, handler)
recorder := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, test.url, nil)
handler.ServeHTTP(recorder, req)
assert.Equal(t, test.wantStatus, recorder.Code)
switch test.wantStatus {
case http.StatusMovedPermanently, http.StatusFound:
location, err := recorder.Result().Location()
require.NoError(t, err)
require.NotNil(t, handler)
recorder := httptest.NewRecorder()
method := http.MethodGet
if test.method != "" {
method = test.method
}
req := httptest.NewRequest(method, test.url, nil)
if test.secured {
req.TLS = &tls.ConnectionState{}
}
for k, v := range test.headers {
req.Header.Set(k, v)
}
req.Header.Set("X-Foo", "bar")
handler.ServeHTTP(recorder, req)
assert.Equal(t, test.expectedStatus, recorder.Code)
switch test.expectedStatus {
case http.StatusMovedPermanently, http.StatusFound:
location, err := recorder.Result().Location()
require.NoError(t, err)
assert.Equal(t, test.expectedURL, location.String())
default:
location, err := recorder.Result().Location()
require.Errorf(t, err, "Location %v", location)
}
assert.Equal(t, test.wantURL, location.String())
default:
location, err := recorder.Result().Location()
require.Errorf(t, err, "Location %v", location)
}
})
}