12 KiB
BUD-13
Path-based blob upload
draft optional
All pubkeys MUST be in hex format
This document supersedes the PUT /upload endpoint definition from BUD-02.
Servers that implement this document MAY continue to support the PUT /upload endpoint from BUD-02 for compatibility.
Defines the PUT /<sha256> and POST /<sha256> endpoints.
The Blob Descriptor type is defined in BUD-02.
The <sha256> path segment MUST be a lowercase hex-encoded sha256 hash of the blob being stored.
PUT /sha256 - Upload Blob
The PUT /<sha256> endpoint MUST accept binary data in the request body.
The server MUST NOT modify the blob in any way and MUST compute the sha256 hash over the exact bytes received. This requirement ensures that users can re-upload blobs to other servers without discrepancies.
Clients SHOULD include Content-Type and Content-Length headers specifying the MIME type and size of the blob.
If the computed sha256 of the request body does not match the <sha256> path segment, the server MUST reject the request with 409 Conflict and MUST NOT persist the blob.
Servers MUST reject PUT /<sha256> requests containing one or more url query parameters with 400 Bad Request. Remote source references are only accepted in the request body of POST /<sha256>.
If the blob was newly stored, the endpoint MUST respond with 201 Created and a Blob Descriptor in the response body.
If the blob already exists, the endpoint MUST respond with 200 OK and a Blob Descriptor in the response body.
Servers MUST handle uploads correctly regardless of whether the client performed a HEAD /upload request first.
Checking support
Clients SHOULD send OPTIONS /<sha256> using any syntactically valid hash as defined in BUD-01. Path-based uploads are supported when both Allow and Access-Control-Allow-Methods include PUT; the presence or absence of POST independently indicates mirroring support.
Status codes
Servers SHOULD use the following status codes for PUT /<sha256> responses:
| Status Code | Meaning |
|---|---|
200 OK |
The blob already exists and the server is returning the existing Blob Descriptor. |
201 Created |
The blob was stored successfully and the server is returning its Blob Descriptor. |
400 Bad Request |
The sha256 path, request headers, body, or query parameters are malformed. |
401 Unauthorized |
Authorization is required and missing or invalid. See BUD-11. |
402 Payment Required |
Payment is required before the upload can proceed. See BUD-07. |
403 Forbidden |
The request is understood but not allowed by server policy. |
409 Conflict |
The sha256 from the path does not match the request body. |
411 Length Required |
A required Content-Length header is missing. |
413 Content Too Large |
The blob exceeds server size limits. |
415 Unsupported Media Type |
The blob type is not supported. |
429 Too Many Requests |
The client has exceeded a rate limit or quota. |
If included, X-Reason MUST be treated as a human readable diagnostic message only and clients MUST NOT parse it for control flow.
POST /sha256 - Mirror Blob
Servers MAY accept POST /<sha256> requests containing one or more source references that tell the server where to fetch the blob. This replaces the mirroring flow from BUD-04 while retaining the blob hash in the path and allowing clients to reuse the same BUD-11 upload authorization token as long as at least one x tag matches the <sha256> path.
The request body MUST be UTF-8 plain text containing one source reference per line. Clients SHOULD set the Content-Type header to text/plain; charset=utf-8. Servers MUST accept lines separated by either LF or CRLF, MUST accept a final line without a trailing newline, and MUST ignore empty lines. Leading and trailing ASCII whitespace is not part of a source reference and MUST be removed from each line.
The request Content-Type and Content-Length headers describe the source list itself and MUST NOT be used as metadata for the mirrored blob.
Each non-empty line MUST be one of the following:
- An absolute
httporhttpsURL. - A valid
blossom:URI from BUD-10.
The request body MUST contain at least one valid source reference after empty lines are removed. Servers MUST reject an empty body, invalid UTF-8, or any malformed or unsupported source reference with 400 Bad Request.
To provide a single HTTP source, clients MUST send one line:
POST /b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553
Content-Type: text/plain; charset=utf-8
https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf
Clients MAY mix HTTP URLs and Blossom URIs in the same request body:
POST /b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553
Content-Type: text/plain; charset=utf-8
https://cdn-a.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf
https://cdn-b.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn-c.example.com&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0
For a blossom: URI, the sha256 hash in the URI MUST match the <sha256> path segment. Servers MUST reject the request with 409 Conflict if any blossom: URI contains a different hash. Servers MUST resolve valid blossom: URIs using the BUD-10 resolution strategy.
When multiple source references are provided, servers MAY try any or all of them in any order. Servers MUST only store the blob if the sha256 hash of the fetched bytes matches the <sha256> path segment. If the fetched blob hash does not match the <sha256> path segment, the server MUST reject the request with 409 Conflict and MUST NOT persist the blob.
The destination server SHOULD use the Content-Type header returned from the successful origin response to infer the MIME type of the blob. If the Content-Type header is not present, the destination server SHOULD attempt to detect the Content-Type from the blob contents and file extension, falling back to application/octet-stream if it cannot determine the type.
Servers MAY use the origin Content-Length header to reject blobs that exceed server size limits before downloading the full response.
If the blob was newly stored, the endpoint MUST respond with 201 Created and a Blob Descriptor in the response body.
If the blob already exists, the endpoint MUST respond with 200 OK and a Blob Descriptor in the response body.
Checking support
Clients SHOULD send OPTIONS /<sha256> using any syntactically valid hash as defined in BUD-01. Mirroring is supported when both Allow and Access-Control-Allow-Methods include POST; a server MAY advertise PUT while omitting POST when it supports direct uploads only.
Status codes
Servers SHOULD use the following status codes for POST /<sha256> responses:
| Status Code | Meaning |
|---|---|
200 OK |
The blob already exists and the server is returning the existing Blob Descriptor. |
201 Created |
The blob was mirrored and stored successfully and the server is returning its Blob Descriptor. |
400 Bad Request |
The sha256 path or request body is malformed, empty, or contains an unsupported source reference. |
401 Unauthorized |
Authorization is required and missing or invalid. See BUD-11. |
402 Payment Required |
Payment is required before mirroring can proceed. See BUD-07. |
403 Forbidden |
The request is understood but not allowed by server policy. |
405 Method Not Allowed |
The server does not support mirroring and returns an Allow header listing its supported methods. |
409 Conflict |
The sha256 from the path does not match a blossom: URI or the fetched remote blob. |
413 Content Too Large |
The mirrored blob exceeds server size limits. |
415 Unsupported Media Type |
The mirrored blob type is not supported. |
429 Too Many Requests |
The client has exceeded a rate limit or quota. |
502 Bad Gateway |
The server could not resolve or fetch the blob from any source reference, or every origin response was unusable. |
If included, X-Reason MUST be treated as a human readable diagnostic message only and clients MUST NOT parse it for control flow.
File extension normalization (Optional)
When storing blobs, servers MAY normalise the file extension to a standard format (e.g. .pdf, .png, etc.) based on the MIME type of the blob. This can be especially useful when the GET /<sha256> endpoint is redirected to an external URL (see the proxying and redirection section from BUD-01), as external servers may rely on the file extension to serve the blob correctly.
Pre-flight upload acceptance checks
Clients MAY use HEAD /upload from BUD-06 as an optimization step before PUT /<sha256>.
Servers that implement PUT /<sha256> SHOULD preserve the existing HEAD /upload semantics from BUD-06 so clients can continue checking whether an upload would be accepted before sending the request body.
This pre-flight request is only an optimization. Clients MAY skip it entirely, and the result is not a guarantee of the eventual PUT /<sha256> outcome because server state may change between requests.
Clients that want to check whether a blob already exists on the server SHOULD use HEAD /<sha256> from BUD-01.
HTTP 100 Continue (Optional)
Clients MAY use the HTTP Expect: 100-continue mechanism with PUT /<sha256> to allow a server or intermediary to reject an upload before the request body is sent.
Servers MAY support this optimization, but clients MUST NOT rely on it because support varies across server frameworks, reverse proxies, and intermediaries.
Clients that need a portable and explicit pre-flight mechanism SHOULD use HEAD /upload.