mirror of
https://github.com/hzrd149/blossom.git
synced 2025-12-09 15:18:49 +00:00
Compare commits
29 Commits
media-endp
...
1d855e1633
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d855e1633 | ||
|
|
51c93670aa | ||
|
|
e39afe2149 | ||
|
|
4d82f98b3c | ||
|
|
8fc2e3dc31 | ||
|
|
a23d784673 | ||
|
|
33714b6c0c | ||
|
|
06edffe984 | ||
|
|
097537d70c | ||
|
|
1262ffa989 | ||
|
|
5d774643e8 | ||
|
|
d9a53bda1c | ||
|
|
234b958339 | ||
|
|
f27cd777f2 | ||
|
|
2d392c1f58 | ||
|
|
53472888d3 | ||
|
|
8e633d00b9 | ||
|
|
381edc3777 | ||
|
|
86d8da4870 | ||
|
|
5593e3d389 | ||
|
|
00a378d81f | ||
|
|
4570963648 | ||
|
|
41cb9c9ef1 | ||
|
|
a1d41da92a | ||
|
|
cf32f7971e | ||
|
|
3b6de30719 | ||
|
|
ba4eb9b8f9 | ||
|
|
8c93401037 | ||
|
|
54cb633750 |
@@ -16,9 +16,10 @@ Blossom Servers expose four endpoints for managing blobs
|
|||||||
|
|
||||||
- `GET /<sha256>` (optional file `.ext`) [BUD-01](./buds/01.md#get-sha256---get-blob)
|
- `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)
|
- `HEAD /<sha256>` (optional file `.ext`) [BUD-01](./buds/01.md#head-sha256---has-blob)
|
||||||
- `PUT /upload` [BUD-2](./buds/02.md#put-upload---upload-blob)
|
- `PUT /upload` [BUD-02](./buds/02.md#put-upload---upload-blob)
|
||||||
- `Authentication`: Signed [nostr event](./buds/02.md#upload-authorization-required)
|
- `Authentication`: Signed [nostr event](./buds/02.md#upload-authorization-required)
|
||||||
- Return a blob descriptor
|
- Return a blob descriptor
|
||||||
|
- `HEAD /upload` [BUD-06](./buds/06.md#head-upload---upload-requirements)
|
||||||
- `GET /list/<pubkey>` [BUD-02](./buds/02.md#get-listpubkey---list-blobs)
|
- `GET /list/<pubkey>` [BUD-02](./buds/02.md#get-listpubkey---list-blobs)
|
||||||
- Returns an array of blob descriptors
|
- Returns an array of blob descriptors
|
||||||
- `Authentication` _(optional)_: Signed [nostr event](./buds/02.md#list-authorization-optional)
|
- `Authentication` _(optional)_: Signed [nostr event](./buds/02.md#list-authorization-optional)
|
||||||
@@ -39,6 +40,9 @@ See the [BUDs](./buds) folder and specifically [BUD-01](./buds/01.md) and [BUD-0
|
|||||||
- [BUD-02: Blob upload and management](./buds/02.md)
|
- [BUD-02: Blob upload and management](./buds/02.md)
|
||||||
- [BUD-03: User Server List](./buds/03.md)
|
- [BUD-03: User Server List](./buds/03.md)
|
||||||
- [BUD-04: Mirroring blobs](./buds/04.md)
|
- [BUD-04: Mirroring blobs](./buds/04.md)
|
||||||
|
- [BUD-06: Upload requirements](./buds/06.md)
|
||||||
|
- [BUD-08: Nostr File Metadata Tags](./buds/08.md)
|
||||||
|
- [BUD-10: Chunked blobs](./buds/10.md)
|
||||||
|
|
||||||
## Event kinds
|
## Event kinds
|
||||||
|
|
||||||
@@ -46,6 +50,7 @@ See the [BUDs](./buds) folder and specifically [BUD-01](./buds/01.md) and [BUD-0
|
|||||||
| ------- | ------------------- | ------------------ |
|
| ------- | ------------------- | ------------------ |
|
||||||
| `24242` | Authorization event | [01](./buds/01.md) |
|
| `24242` | Authorization event | [01](./buds/01.md) |
|
||||||
| `10063` | User Server List | [03](./buds/03.md) |
|
| `10063` | User Server List | [03](./buds/03.md) |
|
||||||
|
| `2001` | Merkle tree | [10](./buds/10.md) |
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,13 @@ _All pubkeys MUST be in hex format_
|
|||||||
|
|
||||||
## Cross origin headers
|
## Cross origin headers
|
||||||
|
|
||||||
Servers MUST set the `Access-Control-Allow-Origin: *`, `Access-Control-Allow-Headers: Authorization,*` and `Access-Control-Allow-Methods: GET, PUT, DELETE` headers on all endpoints to ensure compatibility with apps hosted on other domains
|
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, PUT,
|
||||||
|
DELETE` headers.
|
||||||
|
|
||||||
|
The header `Access-Control-Max-Age: 86400` MAY be set to cache the results of a preflight request for 24 hours.
|
||||||
|
|
||||||
## Authorization events
|
## Authorization events
|
||||||
|
|
||||||
|
|||||||
@@ -42,12 +42,12 @@ The endpoint MUST return a [Blob Descriptor](#blob-descriptor) if the upload was
|
|||||||
|
|
||||||
Servers MAY reject an upload for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
|
Servers MAY reject an upload for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
|
||||||
|
|
||||||
### Upload Authorization (required)
|
### Upload Authorization (Optional)
|
||||||
|
|
||||||
Servers MUST accept an authorization event when uploading blobs and should perform additional checks
|
Servers MAY accept an authorization event when uploading blobs and should perform additional checks
|
||||||
|
|
||||||
1. The `t` tag MUST be set to `upload`
|
1. The `t` tag MUST be set to `upload`
|
||||||
2. MUST contain at least one `x` tag matching the sha256 hash of the body of the request
|
2. MUST contain at least one `x` tag matching the sha256 hash of the blob being uploaded
|
||||||
|
|
||||||
Example Authorization event:
|
Example Authorization event:
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ Example Authorization event:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## GET /list/pubkey - List Blobs
|
## GET /list/pubkey - List Blobs (Optional)
|
||||||
|
|
||||||
The `/list/<pubkey>` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that where uploaded by the specified pubkey
|
The `/list/<pubkey>` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that where uploaded by the specified pubkey
|
||||||
|
|
||||||
|
|||||||
41
buds/05.md
41
buds/05.md
@@ -1,41 +0,0 @@
|
|||||||
# BUD-05
|
|
||||||
|
|
||||||
Media optimization endpoints
|
|
||||||
|
|
||||||
`draft` `optional`
|
|
||||||
|
|
||||||
Defines the `PUT /media` endpoint for processing and optimizing media
|
|
||||||
|
|
||||||
## PUT /media
|
|
||||||
|
|
||||||
The `PUT /media` endpoint MUST accept binary data in the body of the request and MAY use the `Content-Type` and `Content-Length` headers to get the MIME type and size of the media
|
|
||||||
|
|
||||||
The server should preform any optimizations or conversions it deems necessary in order to make the media more suitable for distribution
|
|
||||||
|
|
||||||
The endpoint MUST respond with a `2xx` status and a [blob descriptor](./02.md#blob-descriptor) of the new processed blob
|
|
||||||
|
|
||||||
Servers MAY reject media uploads for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
|
|
||||||
|
|
||||||
### Upload Authorization
|
|
||||||
|
|
||||||
Servers MAY require an `upload` [authorization event](./02.md#upload-authorization-required) to identify the uploader
|
|
||||||
|
|
||||||
If a server requires an `upload` authorization event it MUST preform all the checks outlined in the [`/upload`](./02.md#upload-authorization-required) endpoint
|
|
||||||
|
|
||||||
## Limitations
|
|
||||||
|
|
||||||
This endpoint is intentionally limited to optimizing a single blob with the goal of making it easier to distribute
|
|
||||||
|
|
||||||
How the blob is optimized is the sole respirability of the server and the client should have no say in what optimization process is used
|
|
||||||
|
|
||||||
The goal of this endpoint is to provide a simple "trusted" optimization endpoint clients can use to optimize media for distribution
|
|
||||||
|
|
||||||
If a longer optimization or transformation process is needed, or if the client needs to specify how a blob should be transformed. there are other tools and protocol that should be used.
|
|
||||||
|
|
||||||
## Client Implementation
|
|
||||||
|
|
||||||
Clients MAY let a user selected a "trusted processing" server for uploading images or short videos
|
|
||||||
|
|
||||||
Once a server has been selected, the client can upload the original media to the `/media` endpoint of the trusted server and get the optimized blob back
|
|
||||||
|
|
||||||
Then optionally the client can ask the user to sign another `upload` authorization event for the new optimized blob and call the `/mirror` endpoint on other servers to distribute the blob
|
|
||||||
74
buds/06.md
Normal file
74
buds/06.md
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# BUD-06
|
||||||
|
|
||||||
|
## Upload requirements
|
||||||
|
|
||||||
|
`draft` `optional`
|
||||||
|
|
||||||
|
Defines how clients can verify if the upload can be completed before sending the blob to the server. This mechanism helps prevent unnecessary traffic to other endpoints by rejecting files based on their hash, size, MIME type or other server-specific requirements.
|
||||||
|
|
||||||
|
## HEAD /upload - Upload requirements
|
||||||
|
|
||||||
|
The `HEAD /upload` endpoint `MUST` use the `X-SHA-256`, `X-Content-Type` and `X-Content-Length` headers sent by client to get the SHA-256 hash, MIME type and size of the blob that will be uploaded, returning a HTTP status code and a custom header `X-Upload-Message` to indicate some human readable message about the upload requirements.
|
||||||
|
|
||||||
|
### Headers
|
||||||
|
|
||||||
|
- `X-SHA-256`: A string that represents the blob's SHA-256 hash.
|
||||||
|
- `X-Content-Length`: An integer that represents the blob size in bytes.
|
||||||
|
- `X-Content-Type`: A string that specifies the blob's MIME type, like `application/pdf` or `image/png`.
|
||||||
|
- `X-Upload-Message`: A human readable message that explains the reason why the upload cannot proceed.
|
||||||
|
|
||||||
|
### Upload Authorization
|
||||||
|
|
||||||
|
The `HEAD /upload` endpoint MAY accept an `upload` authorization event using the `Authorization` header similar to what is used in the [`PUT /upload`](./02.md#upload-authorization-required) endpoint
|
||||||
|
|
||||||
|
If the server requires authorization to upload it may respond with the `401` status code, or if authorization was provided and is invalid or not permitted it may respond with `403` status code
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
Example request from the client:
|
||||||
|
|
||||||
|
```http
|
||||||
|
X-Content-Type: application/pdf
|
||||||
|
X-Content-Length: 184292
|
||||||
|
X-SHA-256: 88a74d0b866c8ba79251a11fe5ac807839226870e77355f02eaf68b156522576
|
||||||
|
```
|
||||||
|
|
||||||
|
Example response from the server if the upload can be done:
|
||||||
|
|
||||||
|
```http
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
```
|
||||||
|
|
||||||
|
If the upload cannot proceed, the server `MUST` return an appropriate `4xx` HTTP status code and a custom header `X-Upload-Message` with a human readable error message.
|
||||||
|
|
||||||
|
Some examples of error messages:
|
||||||
|
|
||||||
|
```http
|
||||||
|
HTTP/1.1 400 Bad Request
|
||||||
|
X-Upload-Message: Invalid X-SHA-256 header format. Expected a string.
|
||||||
|
```
|
||||||
|
|
||||||
|
```http
|
||||||
|
HTTP/1.1 401 Unauthorized
|
||||||
|
X-Upload-Message: Authorization required for uploading video files.
|
||||||
|
```
|
||||||
|
|
||||||
|
```http
|
||||||
|
HTTP/1.1 403 Forbidden
|
||||||
|
X-Upload-Message: SHA-256 hash banned.
|
||||||
|
```
|
||||||
|
|
||||||
|
```http
|
||||||
|
HTTP/1.1 411 Length Required
|
||||||
|
X-Upload-Message: Missing X-Content-Length header.
|
||||||
|
```
|
||||||
|
|
||||||
|
```http
|
||||||
|
HTTP/1.1 413 Content Too Large
|
||||||
|
X-Upload-Message: File too large. Max allowed size is 100MB.
|
||||||
|
```
|
||||||
|
|
||||||
|
```http
|
||||||
|
HTTP/1.1 415 Unsupported Media Type
|
||||||
|
X-Upload-Message: Unsupported file type.
|
||||||
|
```
|
||||||
33
buds/08.md
Normal file
33
buds/08.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Nostr File Metadata Tags
|
||||||
|
|
||||||
|
`draft` `optional`
|
||||||
|
|
||||||
|
Describes how a server could return nostr [NIP-94 File Metadata](https://github.com/nostr-protocol/nips/blob/master/94.md) tags from the `/upload` and `/mirror` endpoints
|
||||||
|
|
||||||
|
## Returning tags
|
||||||
|
|
||||||
|
As described in [BUD-02](./02.md#blob-descriptor) servers MAY add any additional fields to a blob descriptor
|
||||||
|
|
||||||
|
Servers MAY return an additional `nip94` field in the [blob descriptor](./02.md#blob-descriptor) from the `/upload` or `/mirror` endpoints
|
||||||
|
|
||||||
|
The `nip94` field should contain a JSON object with the keys being the tag names defined in [NIP-94](https://github.com/nostr-protocol/nips/blob/master/94.md)
|
||||||
|
|
||||||
|
An example response would look like:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"url": "https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf",
|
||||||
|
"sha256": "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553",
|
||||||
|
"size": 184292,
|
||||||
|
"type": "application/pdf",
|
||||||
|
"uploaded": 1725909682,
|
||||||
|
"nip94": {
|
||||||
|
"url": "https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf",
|
||||||
|
"m": "application/pdf",
|
||||||
|
"x": "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553",
|
||||||
|
"size": 184292,
|
||||||
|
"magnet": "magnet:?xt=urn:btih:9804c5286a3fb07b2244c968b39bc3cc814313bc&dn=bitcoin.pdf",
|
||||||
|
"i": "9804c5286a3fb07b2244c968b39bc3cc814313bc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
115
buds/10.md
Normal file
115
buds/10.md
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# BUD-10
|
||||||
|
|
||||||
|
## Chunked blobs
|
||||||
|
|
||||||
|
`draft` `optional`
|
||||||
|
|
||||||
|
Breaking large blobs into smaller chunks for distribution
|
||||||
|
|
||||||
|
### Chunking
|
||||||
|
|
||||||
|
The client MAY break large blobs into any number or size of chunks. although its recommended to use the size `1Mb` or `4Mb` for small and large chunks
|
||||||
|
|
||||||
|
Clients MUST NOT pad the remaining chunk, If clients need privacy they should use random chunk sizes and optionally encrypt the large blob
|
||||||
|
|
||||||
|
Clients MUST create a merkle tree using the chunk hashes as the leaf nodes
|
||||||
|
|
||||||
|
### Publishing
|
||||||
|
|
||||||
|
Clients should publish a `2001` kind event after chunking the file in order to store the list of chunks
|
||||||
|
|
||||||
|
The events MUST contain an ordered list of `chunk` tags with the sha256 hashes of the chunks
|
||||||
|
|
||||||
|
The `content` field MUST be a human readable description of the chunked file
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tags": [
|
||||||
|
[ "chunk", "7e668b56a58c7891e0cf263ea3f093b75eebade23d663a45aa9920f347b3d671"],
|
||||||
|
[ "chunk", "9b9c44a91396f19fd8700986eb0586dff2dcccf96c75bc2caefef302bcd78da1"],
|
||||||
|
[ "chunk", "7a281548f1223664b855b10b08e59e84389ccabeb742517f6cd75eda2724a798"],
|
||||||
|
[ "chunk", "fadeccee86b123088bbc452df10e8fbc99d4c2f22a70ef7a35605ec8e439c345"],
|
||||||
|
[ "chunk", "5d62398419e6d136771541f3d2215e0ce31b1be45e99dbc64b43a4b734b447ca"],
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The event MUST have an `x` tag with the sha256 hash of the ordered concatenated hashes of each chunk
|
||||||
|
|
||||||
|
Example using `xxd` and `sha256sum`:
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
hashes=(
|
||||||
|
"7e668b56a58c7891e0cf263ea3f093b75eebade23d663a45aa9920f347b3d671"
|
||||||
|
"9b9c44a91396f19fd8700986eb0586dff2dcccf96c75bc2caefef302bcd78da1"
|
||||||
|
"7a281548f1223664b855b10b08e59e84389ccabeb742517f6cd75eda2724a798"
|
||||||
|
"fadeccee86b123088bbc452df10e8fbc99d4c2f22a70ef7a35605ec8e439c345"
|
||||||
|
"5d62398419e6d136771541f3d2215e0ce31b1be45e99dbc64b43a4b734b447ca"
|
||||||
|
)
|
||||||
|
|
||||||
|
concatenated=""
|
||||||
|
for hex in "${hex_array[@]}"; do
|
||||||
|
concatenated="${concatenated}${hex}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Chunks:"
|
||||||
|
printf '%s\n' "${hex_array[@]}"
|
||||||
|
|
||||||
|
echo -e "\nConcatenated:"
|
||||||
|
echo "$concatenated"
|
||||||
|
|
||||||
|
echo -e "\nRoot hash:"
|
||||||
|
echo "$concatenated" | xxd -r -p | sha256sum
|
||||||
|
```
|
||||||
|
|
||||||
|
The final `chunk` tags and `x` tag should look something like this
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tags": [
|
||||||
|
[ "chunk", "7e668b56a58c7891e0cf263ea3f093b75eebade23d663a45aa9920f347b3d671"],
|
||||||
|
[ "chunk", "9b9c44a91396f19fd8700986eb0586dff2dcccf96c75bc2caefef302bcd78da1"],
|
||||||
|
[ "chunk", "7a281548f1223664b855b10b08e59e84389ccabeb742517f6cd75eda2724a798"],
|
||||||
|
[ "chunk", "fadeccee86b123088bbc452df10e8fbc99d4c2f22a70ef7a35605ec8e439c345"],
|
||||||
|
[ "chunk", "5d62398419e6d136771541f3d2215e0ce31b1be45e99dbc64b43a4b734b447ca"],
|
||||||
|
[ "x", "2d839865ac17d8bb10168490a88107637619f79dac21275fcec1705162581f39" ],
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Metadata
|
||||||
|
|
||||||
|
The `2001` event MAY include additional metadata tags to help other clients know the filename, mime type or servers to download from
|
||||||
|
|
||||||
|
Metadata tags:
|
||||||
|
- `name` Filename
|
||||||
|
- `mime` Mime type of file
|
||||||
|
- `size` Total size in bytes of the file
|
||||||
|
- `server` (multiple) Recommended servers to download chunks from
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
Example `2001` event
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "fd2f4da046851170576e7a09009e63f752dc469c61a24faca514b2cedfe641aa",
|
||||||
|
"pubkey": "5328e6c743a50271745e16476590ba7ea3dc591c65f3a5e2b03430814c1dabc0",
|
||||||
|
"created_at": 1731405194,
|
||||||
|
"kind": 2001,
|
||||||
|
"content": "Here is the original version",
|
||||||
|
"tags": [
|
||||||
|
[ "chunk", "7e668b56a58c7891e0cf263ea3f093b75eebade23d663a45aa9920f347b3d671"],
|
||||||
|
[ "chunk", "9b9c44a91396f19fd8700986eb0586dff2dcccf96c75bc2caefef302bcd78da1"],
|
||||||
|
[ "chunk", "7a281548f1223664b855b10b08e59e84389ccabeb742517f6cd75eda2724a798"],
|
||||||
|
[ "chunk", "fadeccee86b123088bbc452df10e8fbc99d4c2f22a70ef7a35605ec8e439c345"],
|
||||||
|
[ "chunk", "5d62398419e6d136771541f3d2215e0ce31b1be45e99dbc64b43a4b734b447ca"],
|
||||||
|
[ "x", "2d839865ac17d8bb10168490a88107637619f79dac21275fcec1705162581f39" ],
|
||||||
|
[ "name", "example.mp4" ],
|
||||||
|
[ "mime", "video/mp4" ],
|
||||||
|
[ "size", "4823449" ],
|
||||||
|
[ "server", "https://cdn.example.com" ],
|
||||||
|
[ "server", "https://nostr.download" ]
|
||||||
|
],
|
||||||
|
"sig": "cd589a4ea702185c69d1fec93a7704265071b674c5708a1da04d08bcba873f5277bc0abb379cbb014852fafa2ac951ed49abbdba60028a4f02ef4e31ff2599cb"
|
||||||
|
}
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user