@@ -569,6 +569,30 @@ func (h *Handler) proxyLoopIteration(r *http.Request, origReq *http.Request, w h
569
569
return false , proxyErr
570
570
}
571
571
572
+ // Mapping of the canonical form of the headers, to the RFC 6455 form,
573
+ // i.e. `WebSocket` with uppercase 'S'.
574
+ var websocketHeaderMapping = map [string ]string {
575
+ "Sec-Websocket-Accept" : "Sec-WebSocket-Accept" ,
576
+ "Sec-Websocket-Extensions" : "Sec-WebSocket-Extensions" ,
577
+ "Sec-Websocket-Key" : "Sec-WebSocket-Key" ,
578
+ "Sec-Websocket-Protocol" : "Sec-WebSocket-Protocol" ,
579
+ "Sec-Websocket-Version" : "Sec-WebSocket-Version" ,
580
+ }
581
+
582
+ // normalizeWebsocketHeaders ensures we use the standard casing as per
583
+ // RFC 6455, i.e. `WebSocket` with uppercase 'S'. Most servers don't
584
+ // care about this difference (read headers case insensitively), but
585
+ // some do, so this maximizes compatibility with upstreams.
586
+ // See https://github.com/caddyserver/caddy/pull/6621
587
+ func normalizeWebsocketHeaders (header http.Header ) {
588
+ for k , rk := range websocketHeaderMapping {
589
+ if v , ok := header [k ]; ok {
590
+ delete (header , k )
591
+ header [rk ] = v
592
+ }
593
+ }
594
+ }
595
+
572
596
// prepareRequest clones req so that it can be safely modified without
573
597
// changing the original request or introducing data races. It then
574
598
// 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.
655
679
if reqUpType != "" {
656
680
req .Header .Set ("Connection" , "Upgrade" )
657
681
req .Header .Set ("Upgrade" , reqUpType )
682
+ normalizeWebsocketHeaders (req .Header )
658
683
}
659
684
660
685
// Set up the PROXY protocol info
0 commit comments