Cross-node serving
A node-prefixed URL means the same thing on every machine in the subnet. Paste
http://localhost:5474/kitsubito/f/report.md into a browser on hfenduleam
and the local daemon fetches the file from kitsubito and answers with it.
Nothing is copied: the owner serves the bytes, and the requesting node keeps
none of them.
How a peer’s URL is answered
The local listener resolves the first path segment. When it names a known subnet member (a node in this node’s roster, by its advertised label), the daemon opens one stream to that node and relays the owner’s answer:
- The owner resolves the path through the same router its own listener uses, so a registered file is read at request time. An edit is visible on the next fetch; a removed entry or a deleted source answers the owner’s own 404.
HEADreturns the owner’s headers with no body.Content-Typeis the owner’s.- A
Rangeheader is forwarded as-is. The owner answers206 Partial ContentwithContent-Range; a range past the end answers416naming the length. The same grammar applies to a local file:bytes=a-b,bytes=a-,bytes=-n. - The body streams back in bounded chunks as the owner sends it. A large file
never needs its size in memory on either node, and nothing is written under
the requesting node’s
$SPT_HOME. - The peer’s index page and its
?jsontwin are fetched the same way:/<peer>/lists what that node serves.
Reserved facets stay router-first on the requesting node: /<peer>/f/ with no
name, and the unbuilt m/, bin/ and install facets, are answered locally
and open no stream.
Who decides: the owner
The owning node runs its WEB access check before serving anything. The
origin it checks is the requesting node’s identity as proven by the transport
handshake, never a value in the request. The subject is the endpoint that
registered the entry, so a rule written against that endpoint governs its
served files wherever they are fetched from. See
Viewing access rules and posture for the
WEB row.
What each status means
| Status | Body starts with | Meaning |
|---|---|---|
200 / 206 | the owner’s bytes | Served by the owner. |
403 | ACCESS_DENIED: WEB: | The owner’s access rules refuse this node. The body names the surface, not a sender: WEB carries no sender identity yet. |
404 | NOT_FOUND: served resource <name> | The owner has no such served name (or its source is gone). |
404 | NO_DOCS_LANDED: or the docs page 404 | The first segment is not a known subnet member, so the request fell through to the local docs compatibility surface. |
502 | NODE_UNAVAILABLE: <node>: | The owner is a known member but could not be reached, dropped the stream, or never answered within the deadline. The body names the node and says why. |
A 502 arrives within a bounded time. The dial and each read are held to
the daemon’s peer deadlines, so an owner that is offline, or that runs a
version without cross-node serving, produces an answer rather than a hang.
Trying it
On the owning node:
spt serve add ./report.md
spt serve list
On any other node in the subnet, using the owner’s node name:
curl -s http://localhost:5474/<owner>/f/report.md
curl -sI http://localhost:5474/<owner>/f/report.md
curl -s -r 0-3 http://localhost:5474/<owner>/f/report.md