@@ -16,94 +16,94 @@ import (
18var _ = Describe("Proxy Suite", func() {
18var _ = Describe("Proxy Suite", func() {
19− var upstreamServer http.Handler
19+ type proxyTableInput struct {
21+ response testHTTPResponse
23+ upstreams options.UpstreamConfig
21 Context("multiUpstreamProxy", func() {
26 Context("multiUpstreamProxy", func() {
22− BeforeEach(func() {
27+ DescribeTable("Proxy ServeHTTP",
28+ func(in *proxyTableInput) {
23− sigData := &options.SignatureData{Hash: crypto.SHA256, Key: "secret"}
29+ sigData := &options.SignatureData{Hash: crypto.SHA256, Key: "secret"}
25− writer := &pagewriter.WriterFuncs{
26− ProxyErrorFunc: func(rw http.ResponseWriter, _ *http.Request, _ error) {
28− rw.Write([]byte("Proxy Error"))
32− ok := http.StatusOK
31+ writer := &pagewriter.WriterFuncs{
33− accepted := http.StatusAccepted
32+ ProxyErrorFunc: func(rw http.ResponseWriter, _ *http.Request, _ error) {
34+ rw.Write([]byte("Proxy Error"))
35− upstreams := options.Upstreams{
38+ ok := http.StatusOK
36− {
39+ accepted := http.StatusAccepted
44− URI: fmt.Sprintf("file:///%s", filesDir),
47− ID: "static-backend",
53− ID: "static-backend-no-trailing-slash",
56− StaticCode: &accepted,
59− ID: "static-backend-long",
60− Path: "/static/long",
62− StaticCode: &accepted,
65− ID: "bad-http-backend",
70− ID: "single-path-backend",
71− Path: "/single-path",
76− ID: "backend-with-rewrite-prefix",
77− Path: "^/rewrite-prefix/(.*)",
78− RewriteTarget: "/different/backend/path/$1",
82− ID: "double-match-plain",
83− Path: "/double-match/",
87− ID: "double-match-rewrite",
88− Path: "^/double-match/(.*)",
89− RewriteTarget: "/double-match/rewrite/$1",
94− var err error
41+ // Allows for specifying settings and even individual upstreams for specific tests and uses the default upstreams/configs otherwise
95− upstreamServer, err = NewProxy(upstreams, sigData, writer)
42+ upstreams := in.upstreams
96− Expect(err).ToNot(HaveOccurred())
43+ if len(in.upstreams.Upstreams) == 0 {
44+ upstreams.Upstreams = []options.Upstream{
53+ URI: fmt.Sprintf("file:///%s", filesDir),
56+ ID: "static-backend",
62+ ID: "static-backend-no-trailing-slash",
65+ StaticCode: &accepted,
68+ ID: "static-backend-long",
69+ Path: "/static/long",
71+ StaticCode: &accepted,
74+ ID: "bad-http-backend",
79+ ID: "single-path-backend",
80+ Path: "/single-path",
85+ ID: "backend-with-rewrite-prefix",
86+ Path: "^/rewrite-prefix/(.*)",
87+ RewriteTarget: "/different/backend/path/$1",
91+ ID: "double-match-plain",
92+ Path: "/double-match/",
96+ ID: "double-match-rewrite",
97+ Path: "^/double-match/(.*)",
98+ RewriteTarget: "/double-match/rewrite/$1",
99− type proxyTableInput struct {
104+ upstreamServer, err := NewProxy(upstreams, sigData, writer)
100− target string
105+ Expect(err).ToNot(HaveOccurred())
101− response testHTTPResponse
105− DescribeTable("Proxy ServeHTTP",
106− func(in *proxyTableInput) {
107 req := middlewareapi.AddRequestScope(
107 req := middlewareapi.AddRequestScope(
108 httptest.NewRequest("", in.target, nil),
108 httptest.NewRequest("", in.target, nil),
109 &middlewareapi.RequestScope{},
109 &middlewareapi.RequestScope{},
@@ -131,10 +131,12 @@ var _ = Describe("Proxy Suite", func() {
133 // Compare the reflected request to the upstream
133 // Compare the reflected request to the upstream
134− request := testHTTPRequest{}
135+ request := testHTTPRequest{}
135− Expect(json.Unmarshal(body, &request)).To(Succeed())
136+ Expect(json.Unmarshal(body, &request)).To(Succeed())
136− testSanitizeRequestHeader(request.Header)
137+ testSanitizeRequestHeader(request.Header)
137− Expect(request).To(Equal(in.response.request))
138+ Expect(request).To(Equal(in.response.request))
139 Entry("with a request to the HTTP service", &proxyTableInput{
141 Entry("with a request to the HTTP service", &proxyTableInput{
140 target: "http://example.localhost/http/1234",
142 target: "http://example.localhost/http/1234",
@@ -310,33 +312,58 @@ var _ = Describe("Proxy Suite", func() {
311 upstream: "double-match-rewrite",
313 upstream: "double-match-rewrite",
315+ Entry("containing an escaped '/' without ProxyRawPath", &proxyTableInput{
316+ target: "http://example.localhost/%2F/test1/%2F/test2",
317+ response: testHTTPResponse{
319+ header: map[string][]string{
321+ "http://example.localhost/test1/test2",
327+ Entry("containing an escaped '/' with ProxyRawPath", &proxyTableInput{
328+ upstreams: options.UpstreamConfig{ProxyRawPath: true},
329+ target: "http://example.localhost/%2F/test1/%2F/test2",
330+ response: testHTTPResponse{
332+ header: map[string][]string{
333+ "X-Content-Type-Options": {"nosniff"},
334+ contentType: {textPlainUTF8},
336+ raw: "404 page not found\n",
316 Context("sortByPathLongest", func() {
343 Context("sortByPathLongest", func() {
317 type sortByPathLongestTableInput struct {
344 type sortByPathLongestTableInput struct {
318− input options.Upstreams
345+ input []options.Upstream
319− expectedOutput options.Upstreams
346+ expectedOutput []options.Upstream
322− var httpPath = options.Upstream{
349+ httpPath := options.Upstream{
323 Path: "/http/",
350 Path: "/http/",
326− var httpSubPath = options.Upstream{
353+ httpSubPath := options.Upstream{
327 Path: "/http/subpath/",
354 Path: "/http/subpath/",
330− var longerPath = options.Upstream{
357+ longerPath := options.Upstream{
331 Path: "/longer-than-http",
358 Path: "/longer-than-http",
334− var shortPathWithRewrite = options.Upstream{
361+ shortPathWithRewrite := options.Upstream{
335 Path: "^/h/(.*)",
362 Path: "^/h/(.*)",
336 RewriteTarget: "/$1",
363 RewriteTarget: "/$1",
339− var shortSubPathWithRewrite = options.Upstream{
366+ shortSubPathWithRewrite := options.Upstream{
340 Path: "^/h/bar/(.*)",
367 Path: "^/h/bar/(.*)",
341 RewriteTarget: "/$1",
368 RewriteTarget: "/$1",
@@ -346,40 +373,40 @@ var _ = Describe("Proxy Suite", func() {
346 Expect(sortByPathLongest(in.input)).To(Equal(in.expectedOutput))
373 Expect(sortByPathLongest(in.input)).To(Equal(in.expectedOutput))
348 Entry("with a mix of paths registered", sortByPathLongestTableInput{
375 Entry("with a mix of paths registered", sortByPathLongestTableInput{
349− input: options.Upstreams{httpPath, httpSubPath, shortSubPathWithRewrite, longerPath, shortPathWithRewrite},
376+ input: []options.Upstream{httpPath, httpSubPath, shortSubPathWithRewrite, longerPath, shortPathWithRewrite},
350− expectedOutput: options.Upstreams{shortSubPathWithRewrite, shortPathWithRewrite, longerPath, httpSubPath, httpPath},
377+ expectedOutput: []options.Upstream{shortSubPathWithRewrite, shortPathWithRewrite, longerPath, httpSubPath, httpPath},
352 Entry("when a subpath is registered (in order)", sortByPathLongestTableInput{
379 Entry("when a subpath is registered (in order)", sortByPathLongestTableInput{
353− input: options.Upstreams{httpSubPath, httpPath},
380+ input: []options.Upstream{httpSubPath, httpPath},
354− expectedOutput: options.Upstreams{httpSubPath, httpPath},
381+ expectedOutput: []options.Upstream{httpSubPath, httpPath},
356 Entry("when a subpath is registered (out of order)", sortByPathLongestTableInput{
383 Entry("when a subpath is registered (out of order)", sortByPathLongestTableInput{
357− input: options.Upstreams{httpPath, httpSubPath},
384+ input: []options.Upstream{httpPath, httpSubPath},
358− expectedOutput: options.Upstreams{httpSubPath, httpPath},
385+ expectedOutput: []options.Upstream{httpSubPath, httpPath},
360 Entry("when longer paths are registered (in order)", sortByPathLongestTableInput{
387 Entry("when longer paths are registered (in order)", sortByPathLongestTableInput{
361− input: options.Upstreams{longerPath, httpPath},
388+ input: []options.Upstream{longerPath, httpPath},
362− expectedOutput: options.Upstreams{longerPath, httpPath},
389+ expectedOutput: []options.Upstream{longerPath, httpPath},
364 Entry("when longer paths are registered (out of order)", sortByPathLongestTableInput{
391 Entry("when longer paths are registered (out of order)", sortByPathLongestTableInput{
365− input: options.Upstreams{httpPath, longerPath},
392+ input: []options.Upstream{httpPath, longerPath},
366− expectedOutput: options.Upstreams{longerPath, httpPath},
393+ expectedOutput: []options.Upstream{longerPath, httpPath},
368 Entry("when a rewrite target is registered (in order)", sortByPathLongestTableInput{
395 Entry("when a rewrite target is registered (in order)", sortByPathLongestTableInput{
369− input: options.Upstreams{shortPathWithRewrite, longerPath},
396+ input: []options.Upstream{shortPathWithRewrite, longerPath},
370− expectedOutput: options.Upstreams{shortPathWithRewrite, longerPath},
397+ expectedOutput: []options.Upstream{shortPathWithRewrite, longerPath},
372 Entry("when a rewrite target is registered (out of order)", sortByPathLongestTableInput{
399 Entry("when a rewrite target is registered (out of order)", sortByPathLongestTableInput{
373− input: options.Upstreams{longerPath, shortPathWithRewrite},
400+ input: []options.Upstream{longerPath, shortPathWithRewrite},
374− expectedOutput: options.Upstreams{shortPathWithRewrite, longerPath},
401+ expectedOutput: []options.Upstream{shortPathWithRewrite, longerPath},
376 Entry("with multiple rewrite targets registered (in order)", sortByPathLongestTableInput{
403 Entry("with multiple rewrite targets registered (in order)", sortByPathLongestTableInput{
377− input: options.Upstreams{shortSubPathWithRewrite, shortPathWithRewrite},
404+ input: []options.Upstream{shortSubPathWithRewrite, shortPathWithRewrite},
378− expectedOutput: options.Upstreams{shortSubPathWithRewrite, shortPathWithRewrite},
405+ expectedOutput: []options.Upstream{shortSubPathWithRewrite, shortPathWithRewrite},
380 Entry("with multiple rewrite targets registered (out of order)", sortByPathLongestTableInput{
407 Entry("with multiple rewrite targets registered (out of order)", sortByPathLongestTableInput{
381− input: options.Upstreams{shortPathWithRewrite, shortSubPathWithRewrite},
408+ input: []options.Upstream{shortPathWithRewrite, shortSubPathWithRewrite},
382− expectedOutput: options.Upstreams{shortSubPathWithRewrite, shortPathWithRewrite},
409+ expectedOutput: []options.Upstream{shortSubPathWithRewrite, shortPathWithRewrite},