From 7dd00d24243428cef1f68bba6760dc8ff4fb1eba Mon Sep 17 00:00:00 2001 From: Peter Olds Date: Thu, 23 Jan 2025 08:34:26 -0800 Subject: [PATCH] feat: add a `add_prefix` middleware (#51) This will allow you to translate: `foo.mydomain.com` => `192.168.1.99:8000/foo` (for example) --- .../net/http/middleware/modify_request.go | 14 +++++- .../http/middleware/modify_request_test.go | 47 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/internal/net/http/middleware/modify_request.go b/internal/net/http/middleware/modify_request.go index 0860dc8e..ee665bec 100644 --- a/internal/net/http/middleware/modify_request.go +++ b/internal/net/http/middleware/modify_request.go @@ -2,6 +2,7 @@ package middleware import ( "net/http" + "path/filepath" "strings" ) @@ -10,11 +11,12 @@ type ( ModifyRequestOpts Tracer } - // order: set_headers -> add_headers -> hide_headers + // order: add_prefix -> set_headers -> add_headers -> hide_headers ModifyRequestOpts struct { SetHeaders map[string]string AddHeaders map[string]string HideHeaders []string + AddPrefix string needVarSubstitution bool } @@ -30,6 +32,8 @@ func (mr *ModifyRequestOpts) finalize() { // before implements RequestModifier. func (mr *modifyRequest) before(w http.ResponseWriter, r *http.Request) (proceed bool) { mr.AddTraceRequest("before modify request", r) + + mr.addPrefix(r, nil, r.URL.Path) mr.modifyHeaders(r, nil, r.Header) mr.AddTraceRequest("after modify request", r) return true @@ -77,3 +81,11 @@ func (mr *ModifyRequestOpts) modifyHeaders(req *http.Request, resp *http.Respons delete(headers, k) } } + +func (mr *modifyRequest) addPrefix(r *http.Request, _ *http.Response, path string) { + if len(mr.AddPrefix) == 0 { + return + } + + r.URL.Path = filepath.Join(mr.AddPrefix, path) +} diff --git a/internal/net/http/middleware/modify_request_test.go b/internal/net/http/middleware/modify_request_test.go index 0496a209..dc8cba7f 100644 --- a/internal/net/http/middleware/modify_request_test.go +++ b/internal/net/http/middleware/modify_request_test.go @@ -95,4 +95,51 @@ func TestModifyRequest(t *testing.T) { ExpectEqual(t, result.RequestHeaders.Get("X-Test-Arg-Arg_1"), "b") }) + + t.Run("add_prefix", func(t *testing.T) { + tests := []struct { + name string + path string + expectedPath string + upstreamURL string + addPrefix string + }{ + { + name: "no prefix", + path: "/foo", + expectedPath: "/foo", + upstreamURL: "http://test.example.com", + }, + { + name: "slash only", + path: "/", + expectedPath: "/", + upstreamURL: "http://test.example.com", + addPrefix: "/", // should not change anything + }, + { + name: "some prefix", + path: "/test", + expectedPath: "/foo/test", + upstreamURL: "http://test.example.com", + addPrefix: "/foo", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + reqURL := types.MustParseURL("https://my.app" + tt.path) + upstreamURL := types.MustParseURL(tt.upstreamURL) + + opts["add_prefix"] = tt.addPrefix + result, err := newMiddlewareTest(ModifyRequest, &testArgs{ + middlewareOpt: opts, + reqURL: reqURL, + upstreamURL: upstreamURL, + }) + ExpectNoError(t, err) + ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Path"), tt.expectedPath) + }) + } + }) }