Should redirects work for http/2 streams?

I’m debugging an issue with a stream that fails to playback on a playbin3 pipeline (tested on 1.24 & 1.26):

gst-launch-1.0 souphttpsrc location=https://frontend.streamonkey.net/radio886-onair/stream/mp3 ! fakesink
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
Got context from element 'souphttpsrc0': gst.soup.session=context, session=(GstSoupSession)NULL;
ERROR: from element /GstPipeline:pipeline0/GstSoupHTTPSrc:souphttpsrc0: Internal data stream error.
Additional debug info:
../libs/gst/base/gstbasesrc.c(3177): gst_base_src_loop (): /GstPipeline:pipeline0/GstSoupHTTPSrc:souphttpsrc0:
streaming stopped, reason error (-5)
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...

Enabling some more debugging, it seems we get no data:

0:00:00.297647697 209048 0x58547dae3b60 TRACE              souputils gstsouputils.c:66:gst_soup_util_log_printer_cb:<GstSoupSession@0x58547db5d880> HTTP_SESSION(M): > GET /radio886-onair/stream/mp3 HTTP/2
0:00:00.297676896 209048 0x58547dae3b60 TRACE              souputils gstsouputils.c:66:gst_soup_util_log_printer_cb:<GstSoupSession@0x58547db5d880> HTTP_SESSION(M): > Soup-Debug-Timestamp: 1754060987
0:00:00.297683719 209048 0x58547dae3b60 TRACE              souputils gstsouputils.c:66:gst_soup_util_log_printer_cb:<GstSoupSession@0x58547db5d880> HTTP_SESSION(M): > Soup-Debug: SoupSession 1 (0x7a44cc001770), SoupMessage 1 (0x7a44c8005100), GSocket 1 (0x7a44cc019ee0)
0:00:00.297691492 209048 0x58547dae3b60 TRACE              souputils gstsouputils.c:66:gst_soup_util_log_printer_cb:<GstSoupSession@0x58547db5d880> HTTP_SESSION(H): > User-Agent: GStreamer souphttpsrc 1.24.2 libsoup/3.4.4
0:00:00.297697132 209048 0x58547dae3b60 TRACE              souputils gstsouputils.c:66:gst_soup_util_log_printer_cb:<GstSoupSession@0x58547db5d880> HTTP_SESSION(H): > Accept-Encoding: identity
0:00:00.297702653 209048 0x58547dae3b60 TRACE              souputils gstsouputils.c:66:gst_soup_util_log_printer_cb:<GstSoupSession@0x58547db5d880> HTTP_SESSION(H): > icy-metadata: 1
0:00:00.297708011 209048 0x58547dae3b60 TRACE              souputils gstsouputils.c:66:gst_soup_util_log_printer_cb:<GstSoupSession@0x58547db5d880> HTTP_SESSION(M):   
0:00:00.320053508 209048 0x58547dae3b60 TRACE              souputils gstsouputils.c:66:gst_soup_util_log_printer_cb:<GstSoupSession@0x58547db5d880> HTTP_SESSION(M): < HTTP/2 0 (null)
0:00:00.320073667 209048 0x58547dae3b60 TRACE              souputils gstsouputils.c:66:gst_soup_util_log_printer_cb:<GstSoupSession@0x58547db5d880> HTTP_SESSION(M): < Soup-Debug-Timestamp: 1754060987
0:00:00.320079927 209048 0x58547dae3b60 TRACE              souputils gstsouputils.c:66:gst_soup_util_log_printer_cb:<GstSoupSession@0x58547db5d880> HTTP_SESSION(M): < Soup-Debug: SoupMessage 1 (0x7a44c8005100)
0:00:00.320085683 209048 0x58547dae3b60 TRACE              souputils gstsouputils.c:66:gst_soup_util_log_printer_cb:<GstSoupSession@0x58547db5d880> HTTP_SESSION(M):

Looking at the request with curl, it turns out to be a redirect:

$ curl -I https://frontend.streamonkey.net/radio886-onair/stream/mp3
HTTP/2 302 
access-control-allow-origin: *
cache-control: no-cache
content-type: text/html; charset=utf-8
location: https://edge18.streamonkey.net/radio886-onair/stream/mp3
server: streaMonkey streaming Server Loadbalancer Native
date: Fri, 01 Aug 2025 15:07:10 GMT

Using the URL in the location header directly in the pipeline works! So it’s not that http/2 itself is unsupported.

Interestingly, when I replace the https with http, the pipeline does succeed in following the redirect.

$ curl -I http://frontend.streamonkey.net/radio886-onair/stream/mp3
HTTP/1.1 302 Found
Access-Control-Allow-Origin: *
Cache-Control: no-cache
Connection: close
Content-Type: text/html; charset=utf-8
Location: http://edge10.streamonkey.net/radio886-onair/stream/mp3
Server: streaMonkey streaming Server Loadbalancer Native
Date: Fri, 01 Aug 2025 15:06:58 GMT
  • http/1.1 without redirect: works :white_check_mark:
  • http/1.1 with redirect: works :white_check_mark:
  • http/2 without redirect: works :white_check_mark:
  • http/2 with redirect: does not work :cross_mark:

(tested on gstreamer 1.24 + libsoup 3.4.4, and gstreamer 1.26 + libsoup 3.6.5)

Is following redirects on http/2 not implemented? Is it off by default somehow, and can it be configured?

Based on the logs this looks like a problem in libsoup. Can you check if this still happens with the latest version and if so report it in gitlab?

I already tested with 3.6.5, which is the latest version as far as I can tell.

I’ve opened an issue :crossed_fingers:

1 Like

Is switching gstreamer to libcurl instead of libsoup something that’s been considered? The latter doesn’t feel very actively maintained…

Anyway, I had a go at debugging and fixing the issue with help of Claude AI, we found the issue in libsoup and sent it upstream.

You can try the existing curlhttpsrc element I guess?

If you need it auto-plugged by decodebin you should set the ranks accordingly: export GST_PLUGIN_FEATURE_RANK=souphttpsrc:0,curlhttpsrc:max

:exploding_head:

Based on the docs I figured I’d have to build a completely custom pipeline. I did not know I could just replace the http source in decodebin like that! What an easy fix :face_with_peeking_eye:!

I can confirm the curlhttpsrc has no issues with these redirects, thanks!

It’s `souphttpsrc` + libsoup, not a http/2 standard problem.

Because the connection shuts and reopens properly, http/1.1 redirects are effective. When using http/2, the 302 occurs on a multiplexed stream, and with some versions of libsoup, the redirect is simply not followed correctly, resulting in `souphttpsrc` having no data and displaying the base src error.

In GStreamer, it is not deactivated. With http/2 + 302 in this stack, it’s simply erratic.

Change to `curlhttpsrc` or fix the redirect yourself and supply the final URL if this is for real-world usage. avoids the headache.