This commit is contained in:
hzrd149 2025-07-30 13:01:01 -05:00 committed by GitHub
commit a2f7be2e6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 96 additions and 0 deletions

96
buds/10.md Normal file
View File

@ -0,0 +1,96 @@
# BUD-10
## Multi-part uploads
`draft` `optional`
This bud defines a new `PATCH` method for the `/upload` endpoint to allow clients to upload blobs in multiple parts.
### Signaling support for multi-part uploads
The server SHOULD respond to an `OPTIONS /upload` request with a `204` "No Content" response according to [RFC-9110](https://httpwg.org/specs/rfc9110.html#rfc.section.9.3.7) including the [`Allow`](https://httpwg.org/specs/rfc9110.html#field.allow) header with `PATCH`
### Upload requirements
The server SHOULD implement [BUD-06](06.md) "Upload requirements" to allow clients to check if a blob can be uploaded before uploading any chunks.
### Chunking strategy
The client MAY split the blob into as many chunks as needed and MAY include overlap in the chunks if needed.
The server MUST concatenate the chunks based on the `Upload-Offset` and `Content-Length` headers to reconstruct the final blob to ensure any overlap is accounted for.
### Uploading chunks
Clients MUST send the following headers in each `PATCH /upload` request:
- `X-SHA-256`: The sha256 hash of the final blob. this should be considered the "ID" of the multi-part upload.
- `Upload-Type`: The mine type of the final blob. should be set like `Content-Type` defined in [RFC-9110](https://httpwg.org/specs/rfc9110.html#field.content-type)
- `Upload-Length`: The total length of the blob. should be set like `Content-Length` defined in [RFC-9110](https://httpwg.org/specs/rfc9110.html#field.content-length)
- `Content-Length`: The length of the chunk in bytes.
- `Upload-Offset`: The offset of the chunk in the blob.
- `Content-Type`: The type of the chunk. MUST be set to `application/octet-stream`
The server MUST respond with a `204` "No Content" response if the chunk was accepted or a `4xx` status code if it was not.
### Uploading the final chunk
Once the server has received enough chunks to cover the `Upload-Length` of the blob the server MUST respond with a `2xx` status code following [BUD-02](02.md) or a `4xx` status code if the blob hash does not match the `X-SHA-256` header
### Authorization
The server MAY require authorization for uploads by checking the `Authorization` header similar to the [`PUT /upload`](./02.md#upload-authorization-required) endpoint
The server SHOULD validate that the authorization event contains the following tags:
- A `t` tag set to `upload`
- One `x` tag for each chunk with the sha256 hash of the chunk
- A final `x` tag with the sha256 hash of the final blob
### Resuming uploads
The client SHOULD keep track of a chunks it has uploaded in order to resume uploads after a failure.
### Example upload flow
```sh
# Client splits the blob into 4 chunks
split -b 46073 bitcoin.pdf chunk_
# Client uploads the first chunk
curl -X PATCH http://cdn.example.com/upload \
-H "X-SHA-256: b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553" \
-H "Upload-Type: application/pdf" \
-H "Upload-Length: 184292" \
-H "Upload-Offset: 0" \
-H "Content-Length: 46073" \
-H "Content-Type: application/octet-stream" \
--data-binary "@chunk_aa"
# Server accepts the chunk and responds with a 204
HTTP/1.1 204 No Content
# CLient uploads remaining chunks (2-4)
curl -X PATCH http://cdn.example.com/upload
# ..
--data-binary "@chunk_ab"
curl -X PATCH http://cdn.example.com/upload
# ...
--data-binary "@chunk_ac"
curl -X PATCH http://cdn.example.com/upload
# ...
--data-binary "@chunk_ad"
# Server responds with 200 OK
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Length: 184292
{
"url": "https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf",
"sha256": "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553",
"uploaded": 1725105921,
"type": "application/pdf",
"length": 184292
}
```