mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2025-03-21 21:47:11 +02:00
Ensure upstreams are sorted by longest first
This commit is contained in:
parent
8a06779d41
commit
075cb9c3a0
pkg/upstream
@ -6,6 +6,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
@ -26,7 +27,7 @@ func NewProxy(upstreams options.Upstreams, sigData *options.SignatureData, write
|
||||
serveMux: mux.NewRouter(),
|
||||
}
|
||||
|
||||
for _, upstream := range upstreams {
|
||||
for _, upstream := range sortByPathLongest(upstreams) {
|
||||
if upstream.Static {
|
||||
if err := m.registerStaticResponseHandler(upstream, writer); err != nil {
|
||||
return nil, fmt.Errorf("could not register static upstream %q: %v", upstream.ID, err)
|
||||
@ -145,3 +146,33 @@ func registerTrailingSlashHandler(serveMux *mux.Router) {
|
||||
http.Redirect(rw, req, req.URL.String()+"/", http.StatusMovedPermanently)
|
||||
}))
|
||||
}
|
||||
|
||||
// sortByPathLongest ensures that the upstreams are sorted by longest path.
|
||||
// If rewrites are involved, a rewrite takes precedence over a non-rewrite.
|
||||
// When two upstreams define rewrites, whichever has the longest path will take
|
||||
// precedence (note this is the input to the rewrite logic).
|
||||
// This does not account for when a rewrite would actually make the path shorter.
|
||||
// This should maintain the sorting behaviour of the standard go serve mux.
|
||||
func sortByPathLongest(in options.Upstreams) options.Upstreams {
|
||||
sort.Slice(in, func(i, j int) bool {
|
||||
iRW := in[i].RewriteTarget
|
||||
jRW := in[j].RewriteTarget
|
||||
|
||||
switch {
|
||||
case iRW != "" && jRW != "":
|
||||
// If both have a rewrite target, whichever has the longest pattern
|
||||
// should go first
|
||||
return len(in[i].Path) > len(in[j].Path)
|
||||
case iRW != "" && jRW == "":
|
||||
// Only one has rewrite, it goes first
|
||||
return true
|
||||
case iRW == "" && jRW != "":
|
||||
// Only one has rewrite, it goes first
|
||||
return false
|
||||
default:
|
||||
// Default to longest Path wins
|
||||
return len(in[i].Path) > len(in[j].Path)
|
||||
}
|
||||
})
|
||||
return in
|
||||
}
|
||||
|
@ -18,249 +18,369 @@ import (
|
||||
var _ = Describe("Proxy Suite", func() {
|
||||
var upstreamServer http.Handler
|
||||
|
||||
BeforeEach(func() {
|
||||
sigData := &options.SignatureData{Hash: crypto.SHA256, Key: "secret"}
|
||||
Context("multiUpstreamProxy", func() {
|
||||
BeforeEach(func() {
|
||||
sigData := &options.SignatureData{Hash: crypto.SHA256, Key: "secret"}
|
||||
|
||||
writer := &pagewriter.WriterFuncs{
|
||||
ProxyErrorFunc: func(rw http.ResponseWriter, _ *http.Request, _ error) {
|
||||
rw.WriteHeader(502)
|
||||
rw.Write([]byte("Proxy Error"))
|
||||
},
|
||||
}
|
||||
|
||||
ok := http.StatusOK
|
||||
accepted := http.StatusAccepted
|
||||
|
||||
upstreams := options.Upstreams{
|
||||
{
|
||||
ID: "http-backend",
|
||||
Path: "/http/",
|
||||
URI: serverAddr,
|
||||
},
|
||||
{
|
||||
ID: "file-backend",
|
||||
Path: "/files/",
|
||||
URI: fmt.Sprintf("file:///%s", filesDir),
|
||||
},
|
||||
{
|
||||
ID: "static-backend",
|
||||
Path: "/static/",
|
||||
Static: true,
|
||||
StaticCode: &ok,
|
||||
},
|
||||
{
|
||||
ID: "static-backend-no-trailing-slash",
|
||||
Path: "/static",
|
||||
Static: true,
|
||||
StaticCode: &accepted,
|
||||
},
|
||||
{
|
||||
ID: "bad-http-backend",
|
||||
Path: "/bad-http/",
|
||||
URI: "http://::1",
|
||||
},
|
||||
{
|
||||
ID: "single-path-backend",
|
||||
Path: "/single-path",
|
||||
Static: true,
|
||||
StaticCode: &ok,
|
||||
},
|
||||
{
|
||||
ID: "backend-with-rewrite-prefix",
|
||||
Path: "^/rewrite-prefix/(.*)",
|
||||
RewriteTarget: "/different/backend/path/$1",
|
||||
URI: serverAddr,
|
||||
},
|
||||
}
|
||||
|
||||
var err error
|
||||
upstreamServer, err = NewProxy(upstreams, sigData, writer)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
type proxyTableInput struct {
|
||||
target string
|
||||
response testHTTPResponse
|
||||
upstream string
|
||||
}
|
||||
|
||||
DescribeTable("Proxy ServeHTTP",
|
||||
func(in *proxyTableInput) {
|
||||
req := middlewareapi.AddRequestScope(
|
||||
httptest.NewRequest("", in.target, nil),
|
||||
&middlewareapi.RequestScope{},
|
||||
)
|
||||
rw := httptest.NewRecorder()
|
||||
// Don't mock the remote Address
|
||||
req.RemoteAddr = ""
|
||||
|
||||
upstreamServer.ServeHTTP(rw, req)
|
||||
|
||||
scope := middlewareapi.GetRequestScope(req)
|
||||
Expect(scope.Upstream).To(Equal(in.upstream))
|
||||
|
||||
Expect(rw.Code).To(Equal(in.response.code))
|
||||
|
||||
// Delete extra headers that aren't relevant to tests
|
||||
testSanitizeResponseHeader(rw.Header())
|
||||
Expect(rw.Header()).To(Equal(in.response.header))
|
||||
|
||||
body := rw.Body.Bytes()
|
||||
// If the raw body is set, check that, else check the Request object
|
||||
if in.response.raw != "" {
|
||||
Expect(string(body)).To(Equal(in.response.raw))
|
||||
return
|
||||
writer := &pagewriter.WriterFuncs{
|
||||
ProxyErrorFunc: func(rw http.ResponseWriter, _ *http.Request, _ error) {
|
||||
rw.WriteHeader(502)
|
||||
rw.Write([]byte("Proxy Error"))
|
||||
},
|
||||
}
|
||||
|
||||
// Compare the reflected request to the upstream
|
||||
request := testHTTPRequest{}
|
||||
Expect(json.Unmarshal(body, &request)).To(Succeed())
|
||||
testSanitizeRequestHeader(request.Header)
|
||||
Expect(request).To(Equal(in.response.request))
|
||||
},
|
||||
Entry("with a request to the HTTP service", &proxyTableInput{
|
||||
target: "http://example.localhost/http/1234",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{
|
||||
contentType: {applicationJSON},
|
||||
ok := http.StatusOK
|
||||
accepted := http.StatusAccepted
|
||||
|
||||
upstreams := options.Upstreams{
|
||||
{
|
||||
ID: "http-backend",
|
||||
Path: "/http/",
|
||||
URI: serverAddr,
|
||||
},
|
||||
request: testHTTPRequest{
|
||||
Method: "GET",
|
||||
URL: "http://example.localhost/http/1234",
|
||||
Header: map[string][]string{
|
||||
"Gap-Auth": {""},
|
||||
"Gap-Signature": {"sha256 ofB1u6+FhEUbFLc3/uGbJVkl7GaN4egFqVvyO3+2I1w="},
|
||||
{
|
||||
ID: "file-backend",
|
||||
Path: "/files/",
|
||||
URI: fmt.Sprintf("file:///%s", filesDir),
|
||||
},
|
||||
{
|
||||
ID: "static-backend",
|
||||
Path: "/static/",
|
||||
Static: true,
|
||||
StaticCode: &ok,
|
||||
},
|
||||
{
|
||||
ID: "static-backend-no-trailing-slash",
|
||||
Path: "/static",
|
||||
Static: true,
|
||||
StaticCode: &accepted,
|
||||
},
|
||||
{
|
||||
ID: "static-backend-long",
|
||||
Path: "/static/long",
|
||||
Static: true,
|
||||
StaticCode: &accepted,
|
||||
},
|
||||
{
|
||||
ID: "bad-http-backend",
|
||||
Path: "/bad-http/",
|
||||
URI: "http://::1",
|
||||
},
|
||||
{
|
||||
ID: "single-path-backend",
|
||||
Path: "/single-path",
|
||||
Static: true,
|
||||
StaticCode: &ok,
|
||||
},
|
||||
{
|
||||
ID: "backend-with-rewrite-prefix",
|
||||
Path: "^/rewrite-prefix/(.*)",
|
||||
RewriteTarget: "/different/backend/path/$1",
|
||||
URI: serverAddr,
|
||||
},
|
||||
{
|
||||
ID: "double-match-plain",
|
||||
Path: "/double-match/",
|
||||
URI: serverAddr,
|
||||
},
|
||||
{
|
||||
ID: "double-match-rewrite",
|
||||
Path: "^/double-match/(.*)",
|
||||
RewriteTarget: "/double-match/rewrite/$1",
|
||||
URI: serverAddr,
|
||||
},
|
||||
}
|
||||
|
||||
var err error
|
||||
upstreamServer, err = NewProxy(upstreams, sigData, writer)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
type proxyTableInput struct {
|
||||
target string
|
||||
response testHTTPResponse
|
||||
upstream string
|
||||
}
|
||||
|
||||
DescribeTable("Proxy ServeHTTP",
|
||||
func(in *proxyTableInput) {
|
||||
req := middlewareapi.AddRequestScope(
|
||||
httptest.NewRequest("", in.target, nil),
|
||||
&middlewareapi.RequestScope{},
|
||||
)
|
||||
rw := httptest.NewRecorder()
|
||||
// Don't mock the remote Address
|
||||
req.RemoteAddr = ""
|
||||
|
||||
upstreamServer.ServeHTTP(rw, req)
|
||||
|
||||
scope := middlewareapi.GetRequestScope(req)
|
||||
Expect(scope.Upstream).To(Equal(in.upstream))
|
||||
|
||||
Expect(rw.Code).To(Equal(in.response.code))
|
||||
|
||||
// Delete extra headers that aren't relevant to tests
|
||||
testSanitizeResponseHeader(rw.Header())
|
||||
Expect(rw.Header()).To(Equal(in.response.header))
|
||||
|
||||
body := rw.Body.Bytes()
|
||||
// If the raw body is set, check that, else check the Request object
|
||||
if in.response.raw != "" {
|
||||
Expect(string(body)).To(Equal(in.response.raw))
|
||||
return
|
||||
}
|
||||
|
||||
// Compare the reflected request to the upstream
|
||||
request := testHTTPRequest{}
|
||||
Expect(json.Unmarshal(body, &request)).To(Succeed())
|
||||
testSanitizeRequestHeader(request.Header)
|
||||
Expect(request).To(Equal(in.response.request))
|
||||
},
|
||||
Entry("with a request to the HTTP service", &proxyTableInput{
|
||||
target: "http://example.localhost/http/1234",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{
|
||||
contentType: {applicationJSON},
|
||||
},
|
||||
Body: []byte{},
|
||||
Host: "example.localhost",
|
||||
RequestURI: "http://example.localhost/http/1234",
|
||||
},
|
||||
},
|
||||
upstream: "http-backend",
|
||||
}),
|
||||
Entry("with a request to the File backend", &proxyTableInput{
|
||||
target: "http://example.localhost/files/foo",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{
|
||||
contentType: {textPlainUTF8},
|
||||
},
|
||||
raw: "foo",
|
||||
},
|
||||
upstream: "file-backend",
|
||||
}),
|
||||
Entry("with a request to the Static backend", &proxyTableInput{
|
||||
target: "http://example.localhost/static/bar",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{},
|
||||
raw: "Authenticated",
|
||||
},
|
||||
upstream: "static-backend",
|
||||
}),
|
||||
Entry("with a request to the bad HTTP backend", &proxyTableInput{
|
||||
target: "http://example.localhost/bad-http/bad",
|
||||
response: testHTTPResponse{
|
||||
code: 502,
|
||||
header: map[string][]string{},
|
||||
// This tests the error handler
|
||||
raw: "Proxy Error",
|
||||
},
|
||||
upstream: "bad-http-backend",
|
||||
}),
|
||||
Entry("with a request to the to an unregistered path", &proxyTableInput{
|
||||
target: "http://example.localhost/unregistered",
|
||||
response: testHTTPResponse{
|
||||
code: 404,
|
||||
header: map[string][]string{
|
||||
"X-Content-Type-Options": {"nosniff"},
|
||||
contentType: {textPlainUTF8},
|
||||
},
|
||||
raw: "404 page not found\n",
|
||||
},
|
||||
}),
|
||||
Entry("with a request to the to backend registered to a single path", &proxyTableInput{
|
||||
target: "http://example.localhost/single-path",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{},
|
||||
raw: "Authenticated",
|
||||
},
|
||||
upstream: "single-path-backend",
|
||||
}),
|
||||
Entry("with a request to the to a subpath of a backend registered to a single path", &proxyTableInput{
|
||||
target: "http://example.localhost/single-path/unregistered",
|
||||
response: testHTTPResponse{
|
||||
code: 404,
|
||||
header: map[string][]string{
|
||||
"X-Content-Type-Options": {"nosniff"},
|
||||
contentType: {textPlainUTF8},
|
||||
},
|
||||
raw: "404 page not found\n",
|
||||
},
|
||||
}),
|
||||
Entry("with a request to the rewrite prefix server", &proxyTableInput{
|
||||
target: "http://example.localhost/rewrite-prefix/1234",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{
|
||||
contentType: {applicationJSON},
|
||||
},
|
||||
request: testHTTPRequest{
|
||||
Method: "GET",
|
||||
URL: "http://example.localhost/different/backend/path/1234",
|
||||
Header: map[string][]string{
|
||||
"Gap-Auth": {""},
|
||||
"Gap-Signature": {"sha256 jeAeM7wHSj2ab/l9YPvtTJ9l/8q1tpY2V/iwXF48bgw="},
|
||||
request: testHTTPRequest{
|
||||
Method: "GET",
|
||||
URL: "http://example.localhost/http/1234",
|
||||
Header: map[string][]string{
|
||||
"Gap-Auth": {""},
|
||||
"Gap-Signature": {"sha256 ofB1u6+FhEUbFLc3/uGbJVkl7GaN4egFqVvyO3+2I1w="},
|
||||
},
|
||||
Body: []byte{},
|
||||
Host: "example.localhost",
|
||||
RequestURI: "http://example.localhost/http/1234",
|
||||
},
|
||||
Body: []byte{},
|
||||
Host: "example.localhost",
|
||||
RequestURI: "http://example.localhost/different/backend/path/1234",
|
||||
},
|
||||
},
|
||||
upstream: "backend-with-rewrite-prefix",
|
||||
}),
|
||||
Entry("with a request to a subpath of the rewrite prefix server", &proxyTableInput{
|
||||
target: "http://example.localhost/rewrite-prefix/1234/abc",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{
|
||||
contentType: {applicationJSON},
|
||||
},
|
||||
request: testHTTPRequest{
|
||||
Method: "GET",
|
||||
URL: "http://example.localhost/different/backend/path/1234/abc",
|
||||
Header: map[string][]string{
|
||||
"Gap-Auth": {""},
|
||||
"Gap-Signature": {"sha256 rAkAc9gp7EndoOppJuvbuPnYuBcqrTkBnQx6iPS8xTA="},
|
||||
upstream: "http-backend",
|
||||
}),
|
||||
Entry("with a request to the File backend", &proxyTableInput{
|
||||
target: "http://example.localhost/files/foo",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{
|
||||
contentType: {textPlainUTF8},
|
||||
},
|
||||
Body: []byte{},
|
||||
Host: "example.localhost",
|
||||
RequestURI: "http://example.localhost/different/backend/path/1234/abc",
|
||||
raw: "foo",
|
||||
},
|
||||
},
|
||||
upstream: "backend-with-rewrite-prefix",
|
||||
}),
|
||||
Entry("with a request to a path, missing the trailing slash", &proxyTableInput{
|
||||
target: "http://example.localhost/http",
|
||||
response: testHTTPResponse{
|
||||
code: 301,
|
||||
header: map[string][]string{
|
||||
contentType: {textHTMLUTF8},
|
||||
"Location": {"http://example.localhost/http/"},
|
||||
upstream: "file-backend",
|
||||
}),
|
||||
Entry("with a request to the Static backend", &proxyTableInput{
|
||||
target: "http://example.localhost/static/bar",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{},
|
||||
raw: "Authenticated",
|
||||
},
|
||||
raw: "<a href=\"http://example.localhost/http/\">Moved Permanently</a>.\n\n",
|
||||
upstream: "static-backend",
|
||||
}),
|
||||
Entry("with a request to the bad HTTP backend", &proxyTableInput{
|
||||
target: "http://example.localhost/bad-http/bad",
|
||||
response: testHTTPResponse{
|
||||
code: 502,
|
||||
header: map[string][]string{},
|
||||
// This tests the error handler
|
||||
raw: "Proxy Error",
|
||||
},
|
||||
upstream: "bad-http-backend",
|
||||
}),
|
||||
Entry("with a request to the to an unregistered path", &proxyTableInput{
|
||||
target: "http://example.localhost/unregistered",
|
||||
response: testHTTPResponse{
|
||||
code: 404,
|
||||
header: map[string][]string{
|
||||
"X-Content-Type-Options": {"nosniff"},
|
||||
contentType: {textPlainUTF8},
|
||||
},
|
||||
raw: "404 page not found\n",
|
||||
},
|
||||
}),
|
||||
Entry("with a request to the to backend registered to a single path", &proxyTableInput{
|
||||
target: "http://example.localhost/single-path",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{},
|
||||
raw: "Authenticated",
|
||||
},
|
||||
upstream: "single-path-backend",
|
||||
}),
|
||||
Entry("with a request to the to a subpath of a backend registered to a single path", &proxyTableInput{
|
||||
target: "http://example.localhost/single-path/unregistered",
|
||||
response: testHTTPResponse{
|
||||
code: 404,
|
||||
header: map[string][]string{
|
||||
"X-Content-Type-Options": {"nosniff"},
|
||||
contentType: {textPlainUTF8},
|
||||
},
|
||||
raw: "404 page not found\n",
|
||||
},
|
||||
}),
|
||||
Entry("with a request to the rewrite prefix server", &proxyTableInput{
|
||||
target: "http://example.localhost/rewrite-prefix/1234",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{
|
||||
contentType: {applicationJSON},
|
||||
},
|
||||
request: testHTTPRequest{
|
||||
Method: "GET",
|
||||
URL: "http://example.localhost/different/backend/path/1234",
|
||||
Header: map[string][]string{
|
||||
"Gap-Auth": {""},
|
||||
"Gap-Signature": {"sha256 jeAeM7wHSj2ab/l9YPvtTJ9l/8q1tpY2V/iwXF48bgw="},
|
||||
},
|
||||
Body: []byte{},
|
||||
Host: "example.localhost",
|
||||
RequestURI: "http://example.localhost/different/backend/path/1234",
|
||||
},
|
||||
},
|
||||
upstream: "backend-with-rewrite-prefix",
|
||||
}),
|
||||
Entry("with a request to a subpath of the rewrite prefix server", &proxyTableInput{
|
||||
target: "http://example.localhost/rewrite-prefix/1234/abc",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{
|
||||
contentType: {applicationJSON},
|
||||
},
|
||||
request: testHTTPRequest{
|
||||
Method: "GET",
|
||||
URL: "http://example.localhost/different/backend/path/1234/abc",
|
||||
Header: map[string][]string{
|
||||
"Gap-Auth": {""},
|
||||
"Gap-Signature": {"sha256 rAkAc9gp7EndoOppJuvbuPnYuBcqrTkBnQx6iPS8xTA="},
|
||||
},
|
||||
Body: []byte{},
|
||||
Host: "example.localhost",
|
||||
RequestURI: "http://example.localhost/different/backend/path/1234/abc",
|
||||
},
|
||||
},
|
||||
upstream: "backend-with-rewrite-prefix",
|
||||
}),
|
||||
Entry("with a request to a path, missing the trailing slash", &proxyTableInput{
|
||||
target: "http://example.localhost/http",
|
||||
response: testHTTPResponse{
|
||||
code: 301,
|
||||
header: map[string][]string{
|
||||
contentType: {textHTMLUTF8},
|
||||
"Location": {"http://example.localhost/http/"},
|
||||
},
|
||||
raw: "<a href=\"http://example.localhost/http/\">Moved Permanently</a>.\n\n",
|
||||
},
|
||||
}),
|
||||
Entry("with a request to a path, missing the trailing slash, but registered separately", &proxyTableInput{
|
||||
target: "http://example.localhost/static",
|
||||
response: testHTTPResponse{
|
||||
code: 202,
|
||||
header: map[string][]string{},
|
||||
raw: "Authenticated",
|
||||
},
|
||||
upstream: "static-backend-no-trailing-slash",
|
||||
}),
|
||||
Entry("should match longest path first", &proxyTableInput{
|
||||
target: "http://example.localhost/static/long",
|
||||
response: testHTTPResponse{
|
||||
code: 202,
|
||||
header: map[string][]string{},
|
||||
raw: "Authenticated",
|
||||
},
|
||||
upstream: "static-backend-long",
|
||||
}),
|
||||
Entry("should match rewrite path first", &proxyTableInput{
|
||||
target: "http://example.localhost/double-match/foo",
|
||||
response: testHTTPResponse{
|
||||
code: 200,
|
||||
header: map[string][]string{
|
||||
contentType: {applicationJSON},
|
||||
},
|
||||
request: testHTTPRequest{
|
||||
Method: "GET",
|
||||
URL: "http://example.localhost/double-match/rewrite/foo",
|
||||
Header: map[string][]string{
|
||||
"Gap-Auth": {""},
|
||||
"Gap-Signature": {"sha256 eYyUNdsrTmnvFpavpP8AdHGUGzqJ39QEjqn0/3fQPHA="},
|
||||
},
|
||||
Body: []byte{},
|
||||
Host: "example.localhost",
|
||||
RequestURI: "http://example.localhost/double-match/rewrite/foo",
|
||||
},
|
||||
},
|
||||
upstream: "double-match-rewrite",
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
Context("sortByPathLongest", func() {
|
||||
type sortByPathLongestTableInput struct {
|
||||
input options.Upstreams
|
||||
expectedOutput options.Upstreams
|
||||
}
|
||||
|
||||
var httpPath = options.Upstream{
|
||||
Path: "/http/",
|
||||
}
|
||||
|
||||
var httpSubPath = options.Upstream{
|
||||
Path: "/http/subpath/",
|
||||
}
|
||||
|
||||
var longerPath = options.Upstream{
|
||||
Path: "/longer-than-http",
|
||||
}
|
||||
|
||||
var shortPathWithRewrite = options.Upstream{
|
||||
Path: "^/h/(.*)",
|
||||
RewriteTarget: "/$1",
|
||||
}
|
||||
|
||||
var shortSubPathWithRewrite = options.Upstream{
|
||||
Path: "^/h/bar/(.*)",
|
||||
RewriteTarget: "/$1",
|
||||
}
|
||||
|
||||
DescribeTable("short sort into the correct order",
|
||||
func(in sortByPathLongestTableInput) {
|
||||
Expect(sortByPathLongest(in.input)).To(Equal(in.expectedOutput))
|
||||
},
|
||||
}),
|
||||
Entry("with a request to a path, missing the trailing slash, but registered separately", &proxyTableInput{
|
||||
target: "http://example.localhost/static",
|
||||
response: testHTTPResponse{
|
||||
code: 202,
|
||||
header: map[string][]string{},
|
||||
raw: "Authenticated",
|
||||
},
|
||||
upstream: "static-backend-no-trailing-slash",
|
||||
}),
|
||||
)
|
||||
Entry("with a mix of paths registered", sortByPathLongestTableInput{
|
||||
input: options.Upstreams{httpPath, httpSubPath, shortSubPathWithRewrite, longerPath, shortPathWithRewrite},
|
||||
expectedOutput: options.Upstreams{shortSubPathWithRewrite, shortPathWithRewrite, longerPath, httpSubPath, httpPath},
|
||||
}),
|
||||
Entry("when a subpath is registered (in order)", sortByPathLongestTableInput{
|
||||
input: options.Upstreams{httpSubPath, httpPath},
|
||||
expectedOutput: options.Upstreams{httpSubPath, httpPath},
|
||||
}),
|
||||
Entry("when a subpath is registered (out of order)", sortByPathLongestTableInput{
|
||||
input: options.Upstreams{httpPath, httpSubPath},
|
||||
expectedOutput: options.Upstreams{httpSubPath, httpPath},
|
||||
}),
|
||||
Entry("when longer paths are registered (in order)", sortByPathLongestTableInput{
|
||||
input: options.Upstreams{longerPath, httpPath},
|
||||
expectedOutput: options.Upstreams{longerPath, httpPath},
|
||||
}),
|
||||
Entry("when longer paths are registered (out of order)", sortByPathLongestTableInput{
|
||||
input: options.Upstreams{httpPath, longerPath},
|
||||
expectedOutput: options.Upstreams{longerPath, httpPath},
|
||||
}),
|
||||
Entry("when a rewrite target is registered (in order)", sortByPathLongestTableInput{
|
||||
input: options.Upstreams{shortPathWithRewrite, longerPath},
|
||||
expectedOutput: options.Upstreams{shortPathWithRewrite, longerPath},
|
||||
}),
|
||||
Entry("when a rewrite target is registered (out of order)", sortByPathLongestTableInput{
|
||||
input: options.Upstreams{longerPath, shortPathWithRewrite},
|
||||
expectedOutput: options.Upstreams{shortPathWithRewrite, longerPath},
|
||||
}),
|
||||
Entry("with multiple rewrite targets registered (in order)", sortByPathLongestTableInput{
|
||||
input: options.Upstreams{shortSubPathWithRewrite, shortPathWithRewrite},
|
||||
expectedOutput: options.Upstreams{shortSubPathWithRewrite, shortPathWithRewrite},
|
||||
}),
|
||||
Entry("with multiple rewrite targets registered (out of order)", sortByPathLongestTableInput{
|
||||
input: options.Upstreams{shortPathWithRewrite, shortSubPathWithRewrite},
|
||||
expectedOutput: options.Upstreams{shortSubPathWithRewrite, shortPathWithRewrite},
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user