From 4fa87deff6a1962000aa1fcf6d07985a76792669 Mon Sep 17 00:00:00 2001 From: shiweikang Date: Sat, 11 Apr 2026 12:41:49 +0800 Subject: [PATCH] Proxy: Fix HLS proxy response header loss and m3u8 URL query parameter corruption 1. Move WriteHeader() after setting response headers. In Go's http.ResponseWriter, headers set after WriteHeader() are silently ignored, which caused all backend response headers (Content-Type, Cache-Control, etc.) to be lost during HLS proxying. 2. Fix double ampersand (&&) in m3u8 ts URL rewriting. When the original ts URL already contains query parameters, the proxy generated malformed URLs like ".ts?spbhid=xxx&&token=abc" instead of ".ts?spbhid=xxx&token=abc". --- internal/proxy/http.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/internal/proxy/http.go b/internal/proxy/http.go index 2bf052460..54049f6cf 100644 --- a/internal/proxy/http.go +++ b/internal/proxy/http.go @@ -347,13 +347,14 @@ func (v *httpFlvTsConnection) serveByBackend(ctx context.Context, w http.Respons return errors.Errorf("proxy stream to %v failed, status=%v", backendURL, resp.Status) } - // Copy all headers from backend to client. - w.WriteHeader(resp.StatusCode) + // Copy all headers from backend to client before WriteHeader, + // because headers set after WriteHeader are silently ignored. for k, v := range resp.Header { for _, vv := range v { w.Header().Add(k, vv) } } + w.WriteHeader(resp.StatusCode) logger.Debug(ctx, "HTTP start streaming") @@ -476,13 +477,14 @@ func (v *hlsPlayStream) serveByBackend(ctx context.Context, w http.ResponseWrite return errors.Errorf("proxy stream to %v failed, status=%v", backendURL, resp.Status) } - // Copy all headers from backend to client. - w.WriteHeader(resp.StatusCode) + // Copy all headers from backend to client before WriteHeader, + // because headers set after WriteHeader are silently ignored. for k, v := range resp.Header { for _, vv := range v { w.Header().Add(k, vv) } } + w.WriteHeader(resp.StatusCode) // For TS file, directly copy it. if !strings.HasSuffix(r.URL.Path, ".m3u8") { @@ -502,7 +504,7 @@ func (v *hlsPlayStream) serveByBackend(ctx context.Context, w http.ResponseWrite m3u8 := string(b) if strings.Contains(m3u8, ".ts?") { - m3u8 = strings.ReplaceAll(m3u8, ".ts?", fmt.Sprintf(".ts?spbhid=%v&&", v.SRSProxyBackendHLSID)) + m3u8 = strings.ReplaceAll(m3u8, ".ts?", fmt.Sprintf(".ts?spbhid=%v&", v.SRSProxyBackendHLSID)) } else { m3u8 = strings.ReplaceAll(m3u8, ".ts", fmt.Sprintf(".ts?spbhid=%v", v.SRSProxyBackendHLSID)) }