reverseproxy: Use correct cases for websocket related headers (#6621)

Co-authored-by: Francis Lavoie <lavofr@gmail.com>
This commit is contained in:
WeidiDeng 2024-10-11 17:02:23 +08:00 committed by GitHub
parent ef4e0224a8
commit 48ce47f1d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 26 additions and 0 deletions

View File

@ -569,6 +569,30 @@ func (h *Handler) proxyLoopIteration(r *http.Request, origReq *http.Request, w h
return false, proxyErr return false, proxyErr
} }
// Mapping of the canonical form of the headers, to the RFC 6455 form,
// i.e. `WebSocket` with uppercase 'S'.
var websocketHeaderMapping = map[string]string{
"Sec-Websocket-Accept": "Sec-WebSocket-Accept",
"Sec-Websocket-Extensions": "Sec-WebSocket-Extensions",
"Sec-Websocket-Key": "Sec-WebSocket-Key",
"Sec-Websocket-Protocol": "Sec-WebSocket-Protocol",
"Sec-Websocket-Version": "Sec-WebSocket-Version",
}
// normalizeWebsocketHeaders ensures we use the standard casing as per
// RFC 6455, i.e. `WebSocket` with uppercase 'S'. Most servers don't
// care about this difference (read headers case insensitively), but
// some do, so this maximizes compatibility with upstreams.
// See https://github.com/caddyserver/caddy/pull/6621
func normalizeWebsocketHeaders(header http.Header) {
for k, rk := range websocketHeaderMapping {
if v, ok := header[k]; ok {
delete(header, k)
header[rk] = v
}
}
}
// prepareRequest clones req so that it can be safely modified without // prepareRequest clones req so that it can be safely modified without
// changing the original request or introducing data races. It then // changing the original request or introducing data races. It then
// modifies it so that it is ready to be proxied, except for directing // modifies it so that it is ready to be proxied, except for directing
@ -655,6 +679,7 @@ func (h Handler) prepareRequest(req *http.Request, repl *caddy.Replacer) (*http.
if reqUpType != "" { if reqUpType != "" {
req.Header.Set("Connection", "Upgrade") req.Header.Set("Connection", "Upgrade")
req.Header.Set("Upgrade", reqUpType) req.Header.Set("Upgrade", reqUpType)
normalizeWebsocketHeaders(req.Header)
} }
// Set up the PROXY protocol info // Set up the PROXY protocol info

View File

@ -66,6 +66,7 @@ func (h *Handler) handleUpgradeResponse(logger *zap.Logger, wg *sync.WaitGroup,
// write header first, response headers should not be counted in size // write header first, response headers should not be counted in size
// like the rest of handler chain. // like the rest of handler chain.
copyHeader(rw.Header(), res.Header) copyHeader(rw.Header(), res.Header)
normalizeWebsocketHeaders(rw.Header())
rw.WriteHeader(res.StatusCode) rw.WriteHeader(res.StatusCode)
logger.Debug("upgrading connection") logger.Debug("upgrading connection")