AudioProxy.Plugs.InfoAction (audio_proxy v0.7.0)

Copy Markdown View Source

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-Control is not immutable. §4 asks for aggressive caching and @cache_control gives an hour of it, but immutable on 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 for the question and AudioProxy.VideoPolicy for the verdict on it.

Summary

Types

Plug options.

Types

opts()

@type opts() :: keyword()

Plug options.

  • :executable — the binary to probe with, passed through to AudioProxy.Ffprobe. Unset means ffprobe from PATH; tests mount a chain of their own with a stand-in.