controller_media_runner_callback

Client-side receiver for results produced by the external media runner site. This controller belongs to mod_base, so each client site has a callback endpoint without installing the runner site itself.

Endpoint

The media_runner_callback dispatch accepts POST /media-runner/callback?id=<job-id> with Content-Type: application/json and Authorization: Bearer <secret>. The body must be a JSON object containing the runner's result envelope. Its size is bounded by z_media_runner_protocol:callback_limit/0 before JSON decoding.

Place in the processing flow

  1. A client calls z_exec:run/4 with its site context. When remote processing is configured, z_media_runner registers the waiting process, creates a job ID and random callback secret, and builds an absolute URL using the client's media_runner_callback dispatch rule.
  2. The client submits the job to the runner using OAuth2. The job includes that callback URL and secret. The runner queues the command, executes it in the sandbox, and POSTs its JSON result here with ?id=<job-id> and the secret in the Authorization: Bearer <secret> header.
  3. This controller authenticates the callback and forwards the decoded result to z_media_runner. The waiting client process then uses z_media_runner_protocol:unpack/2 to validate the result and restore output files to the paths declared by the original caller. This controller does not execute commands or write the returned media files.

Callback authentication

The dispatch rule is anonymous deliberately: this endpoint authenticates with the per-job callback secret, not the OAuth2 token used to submit jobs to the runner, nor a browser session. z_media_runner keeps only the secret's hash and associates it with the waiting process. Both the job ID and secret must match.

The request query is already parsed before is_authorized/1. Reading the job ID there lets us reject unauthorized requests before allocating the bounded result body. Responses have cache prevention headers; media payloads and callback secrets are not logged.

Delivery and lifetime

HTTP 204 acknowledges delivery to the waiting process, including a result that reports a processing failure. It does not mean that output validation succeeded. Malformed JSON or a non-map result returns 400; missing or malformed credentials return 401. Unknown jobs and non-matching secrets return 410. The runner treats 410 as final and stops retrying that callback.

While the job is registered, duplicate authenticated callbacks are acknowledged without notifying the waiting process again. The registration is removed when the call finishes, times out, or its process dies. Late callbacks then return 410. Registrations are in memory on the submitting Zotonic node; cluster routing must send callbacks back to that node, and a node restart loses pending registrations.

See the media runner documentation for deployment and client configuration.

Edit on GitHub