Skip to content

fix: handle HEAD requests on /stream/track/:id endpoint#252

Open
Sigmabrogz wants to merge 2 commits into
simojenki:masterfrom
Sigmabrogz:fix/handle-head-request-stream
Open

fix: handle HEAD requests on /stream/track/:id endpoint#252
Sigmabrogz wants to merge 2 commits into
simojenki:masterfrom
Sigmabrogz:fix/handle-head-request-stream

Conversation

@Sigmabrogz

Copy link
Copy Markdown

Summary

Fixes #229

Sonos devices make HEAD requests to streaming endpoints to check track availability and content length without downloading the full audio data. This is standard HTTP behavior for streaming services.

Problem

The /stream/track/:id endpoint only handled GET requests, causing HEAD requests to return 401 errors. This was logged in the issue as:

"HEAD /stream/track/...... HTTP/1.1" 401 - "-" "Linux UPnP/1.0 Sonos/85.0-65270 (ZPS19)"

Solution

  • Extracted the stream handler into a named function streamTrackHandler
  • Registered both GET and HEAD routes to use the same handler
  • The existing handler already checks req.method == "GET" to conditionally stream data vs. just headers
  • HEAD requests now properly return status and headers without the audio body

Testing

  • Build passes: npm run build
  • Tests pass (9 pre-existing failures unrelated to this change) ✅
  • No lint script in project

Checklist

Generated with Claude Code

Fixes simojenki#229

Sonos devices make HEAD requests to /stream endpoints to check
availability and content length without downloading the full track.
Previously, only GET requests were handled, causing 401 errors for
HEAD requests.

Changes:
- Extract stream handler into named function streamTrackHandler
- Register both GET and HEAD routes to use the same handler
- Handler already checks req.method == "GET" to conditionally stream
  data, so HEAD requests properly return headers without body

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@Sigmabrogz

Copy link
Copy Markdown
Author

Hi, the PR is ready for review. Thanks!

@simojenki

Copy link
Copy Markdown
Owner

PR needs test cases so that;

  • the feature doesn't get inadvertently removed with a future change
  • it's easy to see that the following from the sonos docs is satisified
    In addition to returning the requested music, your service must return an accurate Content-Length HTTP header in the response. Sonos requires this to support seeking to any point in the file for formats where the time position doesn't map linearly to byte positions. In some situations, Sonos players may send a HEAD request to get the Content-Length header. Make sure that your service can accept and respond to this request or listeners won’t be able to seek in these situations. here

Also, I'm not convinced that loading the entire stream from downstream/navidrome to only return the content-length is the best way to go about it. Its possible that bonob should simply proxy the request to the *sonic implementation, however I've not tested how that would work against ND or gonic etc, so for now maybe this is good enough.

@Sigmabrogz

Copy link
Copy Markdown
Author

Hi @simojenki, thanks for the review! Proxying the HEAD request downstream makes sense as a longer-term solution if we want to perfectly mirror the sonic implementations, but considering the current scope, I'll go ahead and add the unit tests for this endpoint behavior to ensure it satisfies Sonos' requirements and doesn't regress. I'll push those shortly!

@simojenki

Copy link
Copy Markdown
Owner

Is that you Claude?

Signed-off-by: Sigmabrogz <sigmabrogz@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Handle HEAD request on /stream

2 participants