Add a transparent stream proxy for creamfresh radio
A plain <audio src="https://user:pass@host/..."> doesn't get its embedded Basic Auth credentials honoured consistently across browsers (the user hit a native auth prompt on play) -- this instead holds the credentials server-side and relays the request. Forwards the client's own Icy-MetaData header and the upstream's icy-* response headers unchanged, so the existing icy.py-based metadata SSE keeps working when pointed at this URL instead of the direct one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Drq8o4HfFmwkXz2AgvaQ4p
This commit is contained in:
parent
0fd5461daa
commit
9228906db8
2 changed files with 42 additions and 0 deletions
|
|
@ -19,4 +19,5 @@ urlpatterns = [
|
|||
path('radio/focus/record/', views.record_focus_session, name='record_focus_session'),
|
||||
path('radio/focus/stats/', views.focus_stats, name='focus_stats'),
|
||||
path('radio/stream-player/', views.stream_player, name='stream_player'),
|
||||
path('radio/creamfresh-stream/', views.creamfresh_stream, name='creamfresh_stream'),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -581,6 +581,47 @@ def import_m3u(request):
|
|||
# Minimal HTTP stream player (standalone tab for mixed-content streams)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# creamfresh radio proxy
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Held server-side only -- never exposed to the browser this way. The
|
||||
# upstream is protected by HTTP Basic Auth; a plain <audio src="user:pass@..">
|
||||
# doesn't get credentials honoured consistently across browsers, so this
|
||||
# transparently relays the request instead (including the client's own
|
||||
# Icy-MetaData header, so the existing icy.py-based metadata SSE keeps
|
||||
# working unmodified when pointed at this URL instead of the direct one).
|
||||
CREAMFRESH_STREAM_URL = 'https://radio.creamfresh.xyz/stream.mp3'
|
||||
CREAMFRESH_AUTH = ('player', 'MJMr58p83zAU5zZaDGU0_BIn')
|
||||
|
||||
|
||||
def creamfresh_stream(request):
|
||||
headers = {}
|
||||
if request.META.get('HTTP_ICY_METADATA'):
|
||||
headers['Icy-MetaData'] = request.META['HTTP_ICY_METADATA']
|
||||
try:
|
||||
upstream = requests.get(
|
||||
CREAMFRESH_STREAM_URL,
|
||||
auth=CREAMFRESH_AUTH,
|
||||
headers=headers,
|
||||
stream=True,
|
||||
timeout=15,
|
||||
)
|
||||
except requests.RequestException:
|
||||
return HttpResponse(status=502)
|
||||
|
||||
response = StreamingHttpResponse(
|
||||
upstream.iter_content(chunk_size=4096),
|
||||
content_type=upstream.headers.get('Content-Type', 'audio/mpeg'),
|
||||
status=upstream.status_code,
|
||||
)
|
||||
for h in ('icy-metaint', 'icy-name', 'icy-genre', 'icy-br', 'icy-description', 'icy-url'):
|
||||
if h in upstream.headers:
|
||||
response[h] = upstream.headers[h]
|
||||
response['Cache-Control'] = 'no-cache'
|
||||
return response
|
||||
|
||||
|
||||
def stream_player(request):
|
||||
url = request.GET.get('url', '').strip()
|
||||
name = request.GET.get('name', '').strip()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue