mirror of
https://github.com/hzrd149/blossom.git
synced 2026-08-08 23:34:41 +00:00
Add BUD-14 path-based multipart upload
Define PATCH /<sha256>[.ext] as a BUD-13 extension so multipart uploads use the path hash as the upload identity and no longer require X-SHA-256.
This commit is contained in:
@@ -30,6 +30,7 @@ BUDs or **Blossom Upgrade Documents** are short documents that outline an additi
|
||||
- [BUD-11: Nostr Authorization](./buds/11.md)
|
||||
- [BUD-12: Blob management endpoints](./buds/12.md)
|
||||
- [BUD-13: Path-based blob upload](./buds/13.md)
|
||||
- [BUD-14: Path-based multi-part upload](./buds/14.md)
|
||||
|
||||
## Endpoints
|
||||
|
||||
@@ -38,6 +39,7 @@ Blossom Servers expose a few endpoints for managing blobs
|
||||
- `GET /<sha256>` (optional file `.ext`) [BUD-01](./buds/01.md#get-sha256---get-blob)
|
||||
- `HEAD /<sha256>` (optional file `.ext`) [BUD-01](./buds/01.md#head-sha256---has-blob)
|
||||
- `PUT /<sha256>` [BUD-13](./buds/13.md#put-sha256---upload-blob)
|
||||
- `PATCH /<sha256>` (optional file `.ext`) [BUD-14](./buds/14.md#patch-sha256ext---upload-blob-in-parts)
|
||||
- `HEAD /upload` [BUD-06](./buds/06.md#head-upload---upload-requirements-optional)
|
||||
- `GET /list/<pubkey>` [BUD-12](./buds/12.md#get-listpubkey---list-blobs-unrecommended) _(unrecommended)_
|
||||
- `DELETE /<sha256>` [BUD-12](./buds/12.md#delete-sha256---delete-blob)
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ _All pubkeys MUST be in hex format_
|
||||
Servers MUST set the `Access-Control-Allow-Origin: *` header on all responses to ensure compatibility with applications hosted on other domains.
|
||||
|
||||
For [preflight](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests) (`OPTIONS`) requests,
|
||||
servers MUST also set, at minimum, the `Access-Control-Allow-Headers: Authorization, *` and `Access-Control-Allow-Methods: GET, HEAD, PUT, DELETE` headers.
|
||||
servers MUST also set, at minimum, the `Access-Control-Allow-Headers: Authorization, *` and `Access-Control-Allow-Methods: GET, HEAD, PUT, DELETE` headers. Servers that implement [BUD-14](./14.md) MUST also include `PATCH`.
|
||||
|
||||
The header `Access-Control-Max-Age: 86400` MAY be set to cache the results of a preflight request for 24 hours.
|
||||
|
||||
|
||||
+12
-11
@@ -70,17 +70,18 @@ To validate an authorization token, a server MUST perform the following checks:
|
||||
|
||||
The table below defines, for each endpoint, the required `t` tag action, the implied blob hash (if any), and whether at least one matching `x` tag is required.
|
||||
|
||||
| Endpoint | Required `t` | Implied Blob Hash | `x` Tag Requirement |
|
||||
| -------------------- | ------------ | ---------------------------- | ------------------- |
|
||||
| `GET /<sha256>` | `get` | `<sha256>` from the URL | optional |
|
||||
| `HEAD /<sha256>` | `get` | `<sha256>` from the URL | optional |
|
||||
| `PUT /<sha256>` | `upload` | `<sha256>` from the URL | required |
|
||||
| `HEAD /upload` | `upload` | `X-SHA-256` request header | required |
|
||||
| `DELETE /<sha256>` | `delete` | `<sha256>` from the URL | required |
|
||||
| `GET /list/<pubkey>` | `list` | — | not applicable |
|
||||
| `PUT /mirror` | `upload` | SHA-256 of the mirrored blob | required |
|
||||
| `PUT /media` | `media` | `X-SHA-256` request header | required |
|
||||
| `HEAD /media` | `media` | `X-SHA-256` request header | required |
|
||||
| Endpoint | Required `t` | Implied Blob Hash | `x` Tag Requirement |
|
||||
| ------------------------ | ------------ | ---------------------------- | ------------------- |
|
||||
| `GET /<sha256>` | `get` | `<sha256>` from the URL | optional |
|
||||
| `HEAD /<sha256>` | `get` | `<sha256>` from the URL | optional |
|
||||
| `PUT /<sha256>` | `upload` | `<sha256>` from the URL | required |
|
||||
| `PATCH /<sha256>[.ext]` | `upload` | `<sha256>` from the URL | required |
|
||||
| `HEAD /upload` | `upload` | `X-SHA-256` request header | required |
|
||||
| `DELETE /<sha256>` | `delete` | `<sha256>` from the URL | required |
|
||||
| `GET /list/<pubkey>` | `list` | — | not applicable |
|
||||
| `PUT /mirror` | `upload` | SHA-256 of the mirrored blob | required |
|
||||
| `PUT /media` | `media` | `X-SHA-256` request header | required |
|
||||
| `HEAD /media` | `media` | `X-SHA-256` request header | required |
|
||||
|
||||
## Security Considerations
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ Servers that implement this document MAY continue to support the `PUT /upload` e
|
||||
|
||||
Defines the `PUT /<sha256>` endpoint.
|
||||
|
||||
Multi-part uploads for the same path-based blob identity are defined in [BUD-14](./14.md).
|
||||
|
||||
The [Blob Descriptor](./02.md#blob-descriptor) type is defined in [BUD-02](./02.md).
|
||||
|
||||
## PUT /sha256 - Upload Blob
|
||||
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
# BUD-14
|
||||
|
||||
## Path-based multi-part upload
|
||||
|
||||
`draft` `optional`
|
||||
|
||||
_All pubkeys MUST be in hex format_
|
||||
|
||||
This document extends [BUD-13](./13.md) by defining the `PATCH /<sha256>[.ext]` endpoint for multi-part uploads.
|
||||
|
||||
Servers that implement this document MUST also implement [BUD-13](./13.md).
|
||||
|
||||
The [Blob Descriptor](./02.md#blob-descriptor) type is defined in [BUD-02](./02.md).
|
||||
|
||||
## PATCH /sha256[.ext] - Upload Blob In Parts
|
||||
|
||||
The `PATCH /<sha256>` endpoint MUST accept binary chunk data in the request body.
|
||||
|
||||
The endpoint MUST also accept an optional file extension in the URL, similar to [BUD-01](./01.md#get-sha256---get-blob). The optional file extension MUST NOT affect blob identity or hash validation. `PATCH /<sha256>` and `PATCH /<sha256>.ext` refer to the same blob.
|
||||
|
||||
The `<sha256>` path segment MUST be a lowercase hex-encoded sha256 hash of the final blob.
|
||||
|
||||
The server MUST NOT make the blob available at `/<sha256>` until it has received enough data to reconstruct the full blob and has verified that the computed sha256 of the reconstructed bytes matches the `<sha256>` path segment.
|
||||
|
||||
### Signaling support
|
||||
|
||||
A server that supports multi-part upload SHOULD respond to an `OPTIONS /<sha256>[.ext]` request with `204 No Content` and include `PATCH` in the `Allow` header.
|
||||
|
||||
### Upload requirements
|
||||
|
||||
Clients MAY use [`HEAD /upload` from BUD-06](./06.md#head-upload---upload-requirements-optional) before sending any chunks.
|
||||
|
||||
This pre-flight request remains only an optimization. Clients MAY skip it entirely, and servers MUST handle `PATCH /<sha256>[.ext]` correctly regardless of whether the client performed a `HEAD /upload` request first.
|
||||
|
||||
### Chunking strategy
|
||||
|
||||
The client MAY split the blob into as many chunks as needed and MAY include overlap in the chunks if needed.
|
||||
|
||||
Each chunk is positioned within the final blob using the `Upload-Offset` and `Content-Length` headers.
|
||||
|
||||
The server MUST reconstruct the final blob using the received chunks according to their offsets so that overlapping chunks are handled correctly.
|
||||
|
||||
The server MUST support chunks arriving out of order and SHOULD support concurrent chunk uploads for the same blob.
|
||||
|
||||
### Request headers
|
||||
|
||||
Clients MUST send the following headers in each `PATCH /<sha256>[.ext]` request:
|
||||
|
||||
- `Upload-Type`: The MIME type of the final blob. This header follows the same format as `Content-Type` in [RFC-9110](https://httpwg.org/specs/rfc9110.html#field.content-type).
|
||||
- `Upload-Length`: The total length of the final blob in bytes.
|
||||
- `Upload-Offset`: The byte offset of this chunk within the final blob.
|
||||
- `Content-Length`: The length of the chunk in bytes.
|
||||
- `Content-Type`: MUST be `application/octet-stream`.
|
||||
|
||||
Servers MUST validate that each chunk fits within `Upload-Length`. Servers MUST reject chunks whose declared range is invalid.
|
||||
|
||||
### Completion
|
||||
|
||||
If the chunk was accepted but the upload is not yet complete, the server MUST respond with `204 No Content`.
|
||||
|
||||
Once the server has received enough chunks to cover the full `Upload-Length`, it MUST verify the sha256 hash of the reconstructed blob against the `<sha256>` path segment.
|
||||
|
||||
If the computed sha256 does not match the `<sha256>` path segment, the server MUST reject the upload with `409 Conflict` and MUST NOT make the blob available at `/<sha256>`.
|
||||
|
||||
If the reconstructed blob is valid, the server MUST respond as defined by [BUD-13](./13.md#put-sha256---upload-blob):
|
||||
|
||||
- `201 Created` if the blob was newly stored
|
||||
- `200 OK` if the blob already exists
|
||||
|
||||
The response body MUST contain a [Blob Descriptor](./02.md#blob-descriptor).
|
||||
|
||||
### Authorization
|
||||
|
||||
The server MAY require authorization for `PATCH /<sha256>[.ext]` requests as defined in [BUD-11](./11.md).
|
||||
|
||||
The authorization event MUST use the `upload` verb.
|
||||
|
||||
The blob hash is implied by the `<sha256>` path segment, using the same authorization semantics as `PUT /<sha256>` from [BUD-13](./13.md).
|
||||
|
||||
Servers MUST NOT require one `x` tag per chunk hash.
|
||||
|
||||
### Partial upload timeout
|
||||
|
||||
Servers MAY impose a timeout on in-progress uploads. If no `PATCH` request is received for a partial upload within the timeout window, the server MAY discard the partial upload and free associated resources.
|
||||
|
||||
The RECOMMENDED timeout is 60 seconds of inactivity between chunks.
|
||||
|
||||
### Resuming uploads
|
||||
|
||||
Clients SHOULD keep track of which chunks have been uploaded so they can resume an interrupted upload.
|
||||
|
||||
This document does not define a standardized offset-discovery endpoint. Clients SHOULD assume they are responsible for local upload state.
|
||||
|
||||
### Status codes
|
||||
|
||||
Servers SHOULD use the following status codes for `PATCH /<sha256>[.ext]` responses:
|
||||
|
||||
| Status Code | Meaning |
|
||||
| ---------------------------- | ------- |
|
||||
| `200 OK` | The blob already exists and the server is returning the existing [Blob Descriptor](./02.md#blob-descriptor). |
|
||||
| `201 Created` | The blob was fully reconstructed, stored successfully, and the server is returning its [Blob Descriptor](./02.md#blob-descriptor). |
|
||||
| `204 No Content` | The chunk was accepted but the upload is not yet complete. |
|
||||
| `400 Bad Request` | The sha256 path, optional file extension, request headers, or chunk body are malformed. |
|
||||
| `401 Unauthorized` | Authorization is required and missing or invalid. See [BUD-11](./11.md#endpoint-authorization-requirements). |
|
||||
| `402 Payment Required` | Payment is required before the upload can proceed. See [BUD-07](./07.md). |
|
||||
| `403 Forbidden` | The request is understood but not allowed by server policy. |
|
||||
| `409 Conflict` | The reconstructed blob does not match the sha256 from the URL. |
|
||||
| `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. |
|
||||
| `416 Range Not Satisfiable` | The chunk offset or length is outside the declared upload length. |
|
||||
| `429 Too Many Requests` | The client has exceeded a rate limit or quota. |
|
||||
| `503 Service Unavailable` | The upload service is temporarily unavailable. |
|
||||
|
||||
If included, `X-Reason` MUST be treated as a human readable diagnostic message only and clients MUST NOT parse it for control flow.
|
||||
Reference in New Issue
Block a user