Skip to content

Commit 1361789

Browse files
committed
Add authorization header handling in proxy middleware
- Implemented logic to pass the Authorization header to the target if the proxy URL includes user credentials. - Added unit tests to verify behavior for both scenarios: with and without user credentials in the proxy URL.
1 parent 98ca08e commit 1361789

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

middleware/proxy.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,5 +430,16 @@ func proxyHTTP(tgt *ProxyTarget, c echo.Context, config ProxyConfig) http.Handle
430430
}
431431
proxy.Transport = config.Transport
432432
proxy.ModifyResponse = config.ModifyResponse
433+
434+
// Handle authorization from target URL
435+
if tgt.URL.User != nil {
436+
originalDirector := proxy.Director
437+
proxy.Director = func(req *http.Request) {
438+
originalDirector(req)
439+
password, _ := tgt.URL.User.Password()
440+
req.SetBasicAuth(tgt.URL.User.Username(), password)
441+
}
442+
}
443+
433444
return proxy
434445
}

middleware/proxy_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,3 +1040,56 @@ func TestProxyWithConfigWebSocketTLS2NonTLS(t *testing.T) {
10401040
assert.NoError(t, err)
10411041
assert.Equal(t, sendMsg, recvMsg)
10421042
}
1043+
1044+
func TestProxyWithAuthorizationHeader(t *testing.T) {
1045+
// Scenario:
1046+
// A proxy target has user:pass in the url.
1047+
// The proxy should pass the Authorization header to the target.
1048+
1049+
var receivedAuthHeader string
1050+
// Arrange
1051+
t1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1052+
receivedAuthHeader = r.Header.Get("Authorization")
1053+
fmt.Fprint(w, "target 1")
1054+
}))
1055+
defer t1.Close()
1056+
url1, _ := url.Parse(t1.URL)
1057+
url1.User = url.UserPassword("user1", "pass1")
1058+
1059+
e := echo.New()
1060+
tp := &testProvider{}
1061+
tp.target = &ProxyTarget{Name: "target 1", URL: url1}
1062+
e.Use(Proxy(tp))
1063+
rec := httptest.NewRecorder()
1064+
req := httptest.NewRequest(http.MethodGet, "/", nil)
1065+
e.ServeHTTP(rec, req)
1066+
1067+
// Assert
1068+
assert.Equal(t, "target 1", rec.Body.String())
1069+
assert.Equal(t, "Basic dXNlcjE6cGFzczE=", receivedAuthHeader)
1070+
1071+
// Scenario:
1072+
// A proxy target does not have user:pass in the url.
1073+
// The proxy should not pass the Authorization header to the target.
1074+
1075+
receivedAuthHeader = ""
1076+
// Arrange
1077+
t2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1078+
receivedAuthHeader = r.Header.Get("Authorization")
1079+
fmt.Fprint(w, "target 2")
1080+
}))
1081+
defer t2.Close()
1082+
url2, _ := url.Parse(t2.URL)
1083+
1084+
e = echo.New()
1085+
tp = &testProvider{}
1086+
tp.target = &ProxyTarget{Name: "target 2", URL: url2}
1087+
e.Use(Proxy(tp))
1088+
rec = httptest.NewRecorder()
1089+
req = httptest.NewRequest(http.MethodGet, "/", nil)
1090+
e.ServeHTTP(rec, req)
1091+
1092+
// Assert
1093+
assert.Equal(t, "target 2", rec.Body.String())
1094+
assert.Equal(t, "", receivedAuthHeader)
1095+
}

0 commit comments

Comments
 (0)