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".
This commit is contained in:
shiweikang 2026-04-11 12:41:49 +08:00 committed by Jacob Su
parent 913b773282
commit 4fa87deff6

View File

@ -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))
}