Skip to content

fix(api): stop leaking the probe's skip_play_count into the stream url - #1027

Open
rickyrombo wants to merge 1 commit into
mainfrom
mjp-stream-url-skip-play-count
Open

fix(api): stop leaking the probe's skip_play_count into the stream url#1027
rickyrombo wants to merge 1 commit into
mainfrom
mjp-stream-url-skip-play-count

Conversation

@rickyrombo

Copy link
Copy Markdown
Contributor

The bug

tryFindWorkingUrl probes each candidate host with a two-byte range request, setting skip_play_count=true so the probe isn't counted as a listen. But it sets that on the candidate itself:

for _, u := range urls {
    q := u.Query()
    q.Set("skip_play_count", "true")
    u.RawQuery = q.Encode()      // ← mutates the candidate
    ...
    if resp.StatusCode == ... {
        return u                 // ← returned with the flag still on
    }
}
return mainURL                   // ← urls[0], mutated by its own probe

The node serving /tracks/cidstream/:cid returns immediately from logTrackListen when it sees that flag, so plays resolved through /v1/tracks/:id/stream are never recorded.

Confirmed against production — the live Location header today:

https://val001.open-audio-validator.com/tracks/cidstream/baeaaa...?signature=...&skip_play_count=true

The fallback path has it too: mainURL is urls[0], already mutated on the first iteration, so even "no working host" returns a suppressed URL.

This has been there since the endpoint was added (#57). In practice most playback resolves the track object's stream MediaLink directly rather than calling this endpoint, which is why aggregate play counts look healthy — but any caller that does use /stream loses the play.

The fix

Probe on a copy; return the candidate untouched. redirectToStream still honours an explicit skip_play_count passed by the caller, so opting out remains possible.

/v1/tracks/:id/download shares this helper and is fixed by the same change, though downloads don't hit the cidstream path so no play was at stake there.

Tests

Three, using an httptest server that records what the probe actually sent:

  • primary path — returned URL has no skip_play_count, keeps its signature, and the probe did send the flag (so probing still can't inflate counts)
  • fallback path — the no-working-host return is clean
  • mirror path — a mirror selected after a dead primary is clean

Confirmed failing against the previous behaviour:

--- FAIL: TestReturnedUrlHasNoProbeArtifacts
    returned url carries skip_play_count="true"; the serving node will not record the play
--- FAIL: TestFallbackUrlHasNoProbeArtifacts
--- FAIL: TestMirrorUrlHasNoProbeArtifacts

tryFindWorkingUrl probes each candidate host with a two-byte range request and
sets skip_play_count=true so the probe is not counted as a listen. It set that
on the candidate itself and then returned the same URL, so the flag rode along
into what the caller hands the client.

The node serving /tracks/cidstream/:cid returns early from logTrackListen when
it sees skip_play_count, so every play resolved through /v1/tracks/:id/stream
went unrecorded. Verified against production: the Location header from
/v1/tracks/{id}/stream carries skip_play_count=true today. The fallback path is
affected too, since the returned mainURL is urls[0] and was mutated by its own
probe attempt.

Probe on a copy and return the candidate untouched. redirectToStream still
honours an explicit skip_play_count from the caller.

Tests assert the returned URL is clean on the primary, fallback, and mirror
paths, and that the probe itself still sets the flag -- confirmed failing
against the previous behaviour.
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.

1 participant