The info endpoint's action (API doc §2, §4): stat, probe, JSON.
It shares the whole check chain with the render endpoint and diverges only
here — same signature gate, same source resolution, same blind 404. What it
does instead of rendering is one ffprobe run through
AudioProxy.Ffprobe, filtered to §4's object.
The order is stat then probe, and the stat earns its place twice over: it
is what answers 404 before a subprocess exists, and its ETag material is half
of this response's validator.
AP_MAX_SRC_BYTES does not apply here
The render path refuses an oversized source with 413, and this endpoint deliberately does not — which is a departure from the proposal's "413 as usual", made once it was clear what the limit buys on this path. Nothing. A probe reads container headers and stops; against an HTTP source ffmpeg ranges for them, so a four-gigabyte master costs the same probe a four-megabyte one does. The limit exists to stop a render from decoding something huge.
Refusing anyway would also be self-defeating in the one case that matters:
the client most in need of /info is the one holding a long source it means
to ask for a trimmed preview of, and answering "too large to describe" leaves
it guessing at the very numbers the endpoint exists to supply.
The ETag is not a cache key
On the render path the ETag is the cache key — a pure function of the URL,
because the URL fully describes immutable variant bytes. Nothing like that is
true here. /info describes the source, the source is mutable, and the same
URL answers differently after a re-upload. So the validator is
lowercase-hex(SHA-256(canonical-source ‖ "\n" ‖ stat-etag))which changes exactly when the object does. Two consequences follow, and both are the opposite of the render path's:
- The 304 comes after the stat, not before it, because the stat is what the validator is made of. A revalidation still skips the probe, which is the expensive half.
Cache-Controlis notimmutable. §4 asks for aggressive caching and@cache_controlgives an hour of it, butimmutableon a URL whose answer can change would tell caches never to revalidate a document that has no other way of being corrected. An hour plus a cheap 304 is aggressive; never asking again is wrong.
A backend that offers no ETag material (stat.etag is nil) gets no
validator and a short, plainly-stated max-age instead — a response that
cannot be revalidated must not be held for an hour.
HEAD
Same discipline as AudioProxy.Plugs.RenderAction: every check the chain can
run — here the stat, and nothing else — then a bodiless 200 with no
subprocess. The divergence that buys is the same one, and is deliberate: a
HEAD on an unprobeable source answers 200 where the GET answers 415, because
diagnosing 415 is the probe. There is no Content-Length either, for the
same reason.
Failures
AudioProxy.Ffprobe classifies, this maps: a source ffprobe cannot parse — or
that carries no audio stream at all — is 415, a probe that outran
AP_PROBE_TIMEOUT is 504, and anything else is 500. A missing source
rediscovered by the probe (deleted between the stat and the spawn) is the
same blind 404 the stat would have given.
One 415 is not the probe's verdict but the audio-only policy's: a source
carrying a genuine video stream is refused as :video_source, the same
answer the render endpoint gives it, so the policy has no endpoint-shaped
exception. It costs nothing extra — the probe has already run, and this is one
pass over the streams it returned. Cover art is not video; see
AudioProxy.Ffprobe.has_video?/1.
Summary
Types
@type opts() :: keyword()
Plug options.
:executable— the binary to probe with, passed through toAudioProxy.Ffprobe. Unset meansffprobefromPATH; tests mount a chain of their own with a stand-in.