Skip to content
ANY /{namespace}/{id}{rest}

Resolves the id to its worker (placing it if needed) and streams the request there. The response is the worker's, streamed back unchanged except for the headers listed below. See Routing for how a worker is chosen.

Authentication

Per the namespace's data-plane rule. Open when the server has no namespaces rules. A request carrying valid instance attestation skips the rule.

Path parameters

NameTypeDescription
namespacestringA namespace a worker registered, without the leading /.
idstringInstance id: 1–256 characters of [A-Za-z0-9._~-].
reststringOptional. Path after the id, forwarded verbatim.

The query string is forwarded verbatim.

Request headers

HeaderHandling
Authorization (or the configured cookie/header)Checked against the data-plane rule, then forwarded.
HostHostname-aware mode: selects the hostname. Never forwarded; the worker sees its own host.
Pinboard-*Read for instance attestation, then stripped. Never forwarded.
X-Forwarded-ForReplaced with the peer address Pinboard observed.
Hop-by-hop (Connection, Keep-Alive, TE, Trailer, Transfer-Encoding, Upgrade, Proxy-*, and any named in Connection)Stripped.
Everything elseForwarded.

Pinboard adds:

HeaderValue
Pinboard-AttestationHS256 JWS for the target worker; see Authentication.
Pinboard-EpochPlacement epoch, decimal string.

Request body

Any. Streamed to the worker without buffering or a size cap. Never replayed.

Example

curl -N https://pinboard.example.com/threads/t_8f2a/stream \
  -H "Authorization: Bearer $USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":"attach"}'

Response

The worker's status, headers and body, streamed. Pinboard:

  • strips hop-by-hop headers and every Pinboard-* header;
  • strips Pinned-Refusal (an internal signal; see below);
  • sets X-Accel-Buffering: no;
  • when the request had an Origin and the response has no Access-Control-Allow-Origin, sets Access-Control-Allow-Origin: {Origin} and appends Vary: origin. This applies to Pinboard's own error responses and to worker responses alike.

Redirects from the worker are passed to the client, never followed.

WebSockets

Send the upgrade to the same path. Resolution, auth and attestation are identical. On success the client gets the worker's 101 with Pinboard-* and Pinned-Refusal headers removed, and Pinboard pipes the two sockets. TCP keepalive (30 s) is the tunnel's dead-peer detection.

When the upgrade fails before the tunnel opens, the client gets a bare status line and closes:

HTTP/1.1 503 Service Unavailable
retry-after: 1
connection: close
  • No body and no error string; only the status and, for 503, Retry-After.
  • A 500 destroys the socket without a status line.
  • A worker that answers the upgrade with a non-101 status has its status line relayed.
  • A WebSocket upgrade to /healthz, /readyz or /registry/* is treated as an instance request (namespace /registry, /healthz, …).

In-band refusal

A worker that cannot take a new activation answers 503 with Pinned-Refusal: lease-unhealthy. Pinboard does not relay it:

  1. Releases the placement and counts a nack against the worker.
  2. If the request has no body (or is an upgrade), re-resolves once, excluding that worker, and forwards there.
  3. Otherwise, or when the retry also refuses or no other worker exists: 503 {"error":"worker refused activation, retry"}.

Errors

StatusBodyWhen
400id must be non-empty / id must be at most 256 characters / id must contain only [A-Za-z0-9._~-] (text)Invalid id
400{"error":"missing Host header"}Hostname-aware, no Host
401{"error":"invalid credential"}A provider rejected the credential
401{"error":"authentication required"}Rule requires a credential
403{"error":"namespace not allowed"}No data-plane rule matches
403{"error":"insufficient scope"}Missing a required scope
403attestation errorsSee Call from an instance
404{"error":"unknown namespace"}No id segment in the path, or no worker registered the namespace
502bad gateway (text)Worker unreachable or failed before headers
502emptyClient aborted before the forward started
503{"error":"…"} + Retry-AfterA refusal; see Errors
504upstream timeout (text)No response headers within forwards.timeoutMs (30 s)
508{"error":"subrequest depth exceeded"}Instance call depth over 50
500{"error":"internal error"}Unhandled error

Check order: id, attestation, depth, data-plane rule, hostname binding, caller scope, resolve, inflight cap, forward.

Limits

LimitDefaultOption
Wait for response headers30 sforwards.timeoutMs
Forwards awaiting headers, per worker1024forwards.maxInflight
Body idle on a streamed response (Node entry)60 snone
TCP connect to a worker (Node entry)5 snone

A streaming response body is never cut by the header timeout.