Skip to content

Commit 0468d61

Browse files
committed
Move proxy target authorization handling to middleware instead of internals
- Add support and test for WebSockect authorization handling - Cleanup
1 parent 1361789 commit 0468d61

File tree

2 files changed

+72
-10
lines changed

2 files changed

+72
-10
lines changed

middleware/proxy.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,13 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
375375
// that Balancer may have replaced with c.SetRequest.
376376
req = c.Request()
377377

378+
// Handle authorization from target URL (for both HTTP and WebSocket)
379+
if tgt.URL.User != nil {
380+
username := tgt.URL.User.Username()
381+
password, _ := tgt.URL.User.Password()
382+
req.SetBasicAuth(username, password)
383+
}
384+
378385
// Proxy
379386
switch {
380387
case c.IsWebSocket():
@@ -431,15 +438,5 @@ func proxyHTTP(tgt *ProxyTarget, c echo.Context, config ProxyConfig) http.Handle
431438
proxy.Transport = config.Transport
432439
proxy.ModifyResponse = config.ModifyResponse
433440

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-
444441
return proxy
445442
}

middleware/proxy_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,3 +1093,68 @@ func TestProxyWithAuthorizationHeader(t *testing.T) {
10931093
assert.Equal(t, "target 2", rec.Body.String())
10941094
assert.Equal(t, "", receivedAuthHeader)
10951095
}
1096+
1097+
func TestProxyWithConfigWebSocketAuthorizationHeader(t *testing.T) {
1098+
// Capture the authorization header received by the WebSocket server
1099+
var receivedAuthHeader string
1100+
var authHeaderMutex sync.Mutex
1101+
1102+
// Create a WebSocket server that captures the Authorization header
1103+
wsServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1104+
authHeaderMutex.Lock()
1105+
receivedAuthHeader = r.Header.Get("Authorization")
1106+
authHeaderMutex.Unlock()
1107+
1108+
wsHandler := func(conn *websocket.Conn) {
1109+
defer conn.Close()
1110+
for {
1111+
var msg string
1112+
err := websocket.Message.Receive(conn, &msg)
1113+
if err != nil {
1114+
return
1115+
}
1116+
// Echo message back to the client
1117+
websocket.Message.Send(conn, msg)
1118+
}
1119+
}
1120+
websocket.Server{Handler: wsHandler}.ServeHTTP(w, r)
1121+
}))
1122+
defer wsServer.Close()
1123+
1124+
// Create proxy server with target URL containing user:pass credentials
1125+
targetURL, _ := url.Parse(wsServer.URL)
1126+
targetURL.User = url.UserPassword("wsuser", "wspass")
1127+
1128+
e := echo.New()
1129+
balancer := NewRandomBalancer([]*ProxyTarget{{URL: targetURL}})
1130+
e.Use(ProxyWithConfig(ProxyConfig{Balancer: balancer}))
1131+
1132+
proxyServer := httptest.NewServer(e)
1133+
defer proxyServer.Close()
1134+
1135+
// Connect to the proxy WebSocket
1136+
proxyURL, _ := url.Parse(proxyServer.URL)
1137+
proxyURL.Scheme = "ws"
1138+
proxyURL.Path = "/"
1139+
1140+
wsConn, err := websocket.Dial(proxyURL.String(), "", "http://localhost/")
1141+
assert.NoError(t, err)
1142+
defer wsConn.Close()
1143+
1144+
// Send message to verify WebSocket connection works
1145+
sendMsg := "Hello, WebSocket with Auth!"
1146+
err = websocket.Message.Send(wsConn, sendMsg)
1147+
assert.NoError(t, err)
1148+
1149+
// Read response
1150+
var recvMsg string
1151+
err = websocket.Message.Receive(wsConn, &recvMsg)
1152+
assert.NoError(t, err)
1153+
assert.Equal(t, sendMsg, recvMsg)
1154+
1155+
// Verify authorization header was forwarded
1156+
authHeaderMutex.Lock()
1157+
expectedAuth := "Basic d3N1c2VyOndzcGFzcw==" // base64 of "wsuser:wspass"
1158+
assert.Equal(t, expectedAuth, receivedAuthHeader)
1159+
authHeaderMutex.Unlock()
1160+
}

0 commit comments

Comments
 (0)