mirror of
https://github.com/hzrd149/blossom.git
synced 2026-01-24 22:28:51 +00:00
Compare commits
70 Commits
multi-part
...
4f0a47ff0b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f0a47ff0b | ||
|
|
442d5c6293 | ||
|
|
1305788e98 | ||
|
|
a3b1ef577b | ||
|
|
42b6c568fc | ||
|
|
342cae9e51 | ||
|
|
05a6c68dd8 | ||
|
|
fe8906369c | ||
|
|
f1847b56d7 | ||
|
|
0ccf399577 | ||
|
|
7efca7a2a5 | ||
|
|
e8d0a1ec44 | ||
|
|
847f449acf | ||
|
|
90affdd4d9 | ||
|
|
385913adef | ||
|
|
39ce39aa4d | ||
|
|
85de0197f0 | ||
|
|
658c608b11 | ||
|
|
b1a336fe75 | ||
|
|
611272e251 | ||
|
|
1a085ed7bf | ||
|
|
cacfa520dd | ||
|
|
5ef2889547 | ||
|
|
e1299a6ce5 | ||
|
|
6a27b156ba | ||
|
|
977d0be083 | ||
|
|
2cbdc130a0 | ||
|
|
065756a976 | ||
|
|
d6c2f9721f | ||
|
|
3f2aa40eb9 | ||
|
|
0baee02851 | ||
|
|
620d74c2a2 | ||
|
|
2d1593d634 | ||
|
|
fca1c42406 | ||
|
|
66e6dcec74 | ||
|
|
3ae2361b41 | ||
|
|
2aa65cc373 | ||
|
|
542c654045 | ||
|
|
39d1ae9e93 | ||
|
|
a63959f1e0 | ||
|
|
8e12280410 | ||
|
|
4d9b22a96c | ||
|
|
3cb8c92197 | ||
|
|
463f28da7b | ||
|
|
73fcfbfbd3 | ||
|
|
f9f44fc592 | ||
|
|
38274c6a5e | ||
|
|
8f95ad7468 | ||
|
|
ffe55bbffc | ||
|
|
0d039843a0 | ||
|
|
cda53cf47a | ||
|
|
e003b22318 | ||
|
|
8600dbecfc | ||
|
|
0aa5a9dd6f | ||
|
|
18a57e361c | ||
|
|
970fc2b072 | ||
|
|
8a4728e3e6 | ||
|
|
b450680b00 | ||
|
|
3524b81bac | ||
|
|
bf417ae115 | ||
|
|
5c0ecbb4fa | ||
|
|
942fb60e97 | ||
|
|
cd778dec22 | ||
|
|
40a7cd943c | ||
|
|
7a57b0c19a | ||
|
|
f0ac329e90 | ||
|
|
b6bd9b9a94 | ||
|
|
c3f7a5da0d | ||
|
|
17d6814fd0 | ||
|
|
2bd04954a4 |
41
README.md
41
README.md
@@ -4,13 +4,31 @@ Blossom uses [nostr](https://github.com/nostr-protocol/nostr) public / private k
|
||||
|
||||
## What is it?
|
||||
|
||||
Blossom is a spec for a set of HTTP endpoints that allow users to store blobs of data on publicly accessible servers
|
||||
Blossom is a specification for a set of HTTP endpoints that allow users to store blobs of data on publicly accessible servers
|
||||
|
||||
## What are blobs
|
||||
|
||||
Blobs are packs of binary data addressed by their sha256 hash
|
||||
|
||||
## How does it work?
|
||||
## Protocol specification (BUDs)
|
||||
|
||||
BUDs or **Blossom Upgrade Documents** are short documents that outline an additional feature that a blossom server may implement.
|
||||
|
||||
## BUDs
|
||||
|
||||
- [BUD-00: Blossom Upgrade Documents](./buds/00.md)
|
||||
- [BUD-01: Server requirements and blob retrieval](./buds/01.md)
|
||||
- [BUD-02: Blob upload and management](./buds/02.md)
|
||||
- [BUD-03: User Server List](./buds/03.md)
|
||||
- [BUD-04: Mirroring blobs](./buds/04.md)
|
||||
- [BUD-05: Media optimization](./buds/05.md)
|
||||
- [BUD-06: Upload requirements](./buds/06.md)
|
||||
- [BUD-07: Payment required](./buds/07.md)
|
||||
- [BUD-08: Nostr File Metadata Tags](./buds/08.md)
|
||||
- [BUD-09: Blob Report](./buds/09.md)
|
||||
- [BUD-10: Blossom URI Schema](./buds/10.md)
|
||||
|
||||
## Endpoints
|
||||
|
||||
Blossom Servers expose a few endpoints for managing blobs
|
||||
|
||||
@@ -20,7 +38,7 @@ Blossom Servers expose a few endpoints for managing blobs
|
||||
- `Authentication`: Signed [nostr event](./buds/02.md#upload-authorization-required)
|
||||
- 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-unrecommended) _(optional, unrecommended)_
|
||||
- Returns an array of blob descriptors
|
||||
- `Authentication` _(optional)_: Signed [nostr event](./buds/02.md#list-authorization-optional)
|
||||
- `DELETE /<sha256>` [BUD-02](./buds/02.md#delete-sha256---delete-blob)
|
||||
@@ -32,23 +50,6 @@ Blossom Servers expose a few endpoints for managing blobs
|
||||
- `Authentication`: Signed [nostr event](./buds/05.md#upload-authorization)
|
||||
- `PUT /report` [BUD-09](./buds/09.md)
|
||||
|
||||
## Protocol specification (BUDs)
|
||||
|
||||
BUDs stand for **Blossom Upgrade Documents**.
|
||||
|
||||
See the [BUDs](./buds) folder and specifically [BUD-01](./buds/01.md) and [BUD-02](./buds/02.md) for a detailed explanation of the endpoints
|
||||
|
||||
## BUDs
|
||||
|
||||
- [BUD-01: Server requirements and blob retrieval](./buds/01.md)
|
||||
- [BUD-02: Blob upload and management](./buds/02.md)
|
||||
- [BUD-03: User Server List](./buds/03.md)
|
||||
- [BUD-04: Mirroring blobs](./buds/04.md)
|
||||
- [BUD-05: Media optimization](./buds/05.md)
|
||||
- [BUD-06: Upload requirements](./buds/06.md)
|
||||
- [BUD-08: Nostr File Metadata Tags](./buds/08.md)
|
||||
- [BUD-09: Blob Report](./buds/09.md)
|
||||
|
||||
## Event kinds
|
||||
|
||||
| kind | description | BUD |
|
||||
|
||||
19
buds/00.md
Normal file
19
buds/00.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# BUD-00
|
||||
|
||||
## Blossom Upgrade Documents
|
||||
|
||||
`draft` `mandatory`
|
||||
|
||||
This document details the common language for all following BUDs
|
||||
|
||||
## Language
|
||||
|
||||
All occurences of "MUST", "MUST NOT", "SHOULD", "SHOULD NOT" MUST be interpreted as per [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119)
|
||||
|
||||
## BUDs
|
||||
|
||||
BUDs or "Blossom Upgrade Documents" are short documents that outline an additional requirement or feature that a blossom server MUST or MAY implement.
|
||||
|
||||
## Blobs
|
||||
|
||||
Blobs are raw binary data addressed by the sha256 hash of the data.
|
||||
32
buds/01.md
32
buds/01.md
@@ -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, PUT,
|
||||
servers MUST also set, at minimum, the `Access-Control-Allow-Headers: Authorization, *` and `Access-Control-Allow-Methods: GET, HEAD, PUT,
|
||||
DELETE` headers.
|
||||
|
||||
The header `Access-Control-Max-Age: 86400` MAY be set to cache the results of a preflight request for 24 hours.
|
||||
@@ -28,7 +28,7 @@ Authorization events must be generic and must NOT be scoped to specific servers.
|
||||
|
||||
Events MUST be kind `24242` and have a `t` tag with a verb of `get`, `upload`, `list`, or `delete`
|
||||
|
||||
Events MUST have the `content` set to a human readable string explaining to the user what the events inteded use is. For example `Upload Blob`, `Delete dog-picture.png`, `List Images`, etc
|
||||
Events MUST have the `content` set to a human readable string explaining to the user what the events intended use is. For example `Upload Blob`, `Delete dog-picture.png`, `List Images`, etc
|
||||
|
||||
All events MUST have a [NIP-40](https://github.com/nostr-protocol/nips/blob/master/40.md) `expiration` tag set to a unix timestamp at which the event should be considered expired.
|
||||
|
||||
@@ -75,12 +75,29 @@ All endpoints MUST be served from the root of the domain (eg. the `/upload` endp
|
||||
|
||||
## GET /sha256 - Get Blob
|
||||
|
||||
The `GET /<sha256>` endpoint MUST return the contents of the blob with the `Content-Type` header set to the appropriate MIME-type
|
||||
The `GET /<sha256>` endpoint MUST return the contents of the blob in the response body. the `Content-Type` header SHOULD beset to the appropriate MIME-type
|
||||
|
||||
The endpoint MUST accept an optional file extension in the URL. ie. `.pdf`, `.png`, etc
|
||||
|
||||
If the endpoints returns a 301 or 302 redirect it MUST redirect to a URL containing the same sha256 hash as the requested blob.
|
||||
This ensures that if a user was to copy or reuse the redirect URL it would still contain the original sha256 hash
|
||||
Regardless of the file extension, the server MUST return the MIME type of the blob in the `Content-Type` header. If the
|
||||
server does not know the MIME type of the blob, it MUST default to `application/octet-stream`
|
||||
|
||||
### Proxying and Redirection (Optional)
|
||||
|
||||
If the endpoint returns a redirection 3xx status code such as 307 or 308 ([RFC 9110 section
|
||||
15.4](https://datatracker.ietf.org/doc/html/rfc9110#name-redirection-3xx)), it MUST redirect to a URL containing the
|
||||
same sha256 hash as the requested blob. This ensures that if a user copies or reuses the redirect URL, it will
|
||||
contain the original sha256 hash.
|
||||
|
||||
While the final blob may not be served from a Blossom server (e.g. CDN, IPFS, object storage, etc.), the destination
|
||||
server MUST set the `Access-Control-Allow-Origin: *` header on the response to allow cross-origin requests, as well as
|
||||
the `Content-Type` and `Content-Length` headers to ensure the blob can be correctly displayed by clients. Two ways to
|
||||
guarantee this are:
|
||||
|
||||
1. Proxying the blob through the Blossom server, allowing it to override headers such as `Content-Type`.
|
||||
2. Manipulating the redirect URL to include a file extension that matches the blob type, such as `.pdf`, `.png`, etc. If
|
||||
the server is unable to determine the MIME type of the blob, it MUST default to `application/octet-stream` and MAY
|
||||
include a file extension in the URL that reflects the blob type (e.g. `.bin`, `.dat`, etc.).
|
||||
|
||||
### Get Authorization (optional)
|
||||
|
||||
@@ -131,7 +148,10 @@ Example event for retrieving multiple blobs from single server:
|
||||
|
||||
## HEAD /sha256 - Has Blob
|
||||
|
||||
The `HEAD /<sha256>` endpoint MUST respond with either a `200` or `404` status code
|
||||
The `HEAD /<sha256>` endpoint SHOULD be identical to the `GET /<sha256>` endpoint except that it MUST NOT return the
|
||||
blob in the reponse body per [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231#section-4.3.2)
|
||||
|
||||
The endpoint MUST respond with the same `Content-Type` and `Content-Length` headers as the `GET /<sha256>` endpoint.
|
||||
|
||||
The endpoint MUST accept an optional file extension in the URL similar to the `GET /<sha256>` endpoint. ie. `.pdf`, `.png`, etc
|
||||
|
||||
|
||||
43
buds/02.md
43
buds/02.md
@@ -15,7 +15,7 @@ A blob descriptor is a JSON object containing `url`, `sha256`, `size`, `type`, a
|
||||
- `url` A publicly accessible URL to the [BUD-01](./01.md#get-sha256---get-blob) `GET /<sha256>` endpoint with a file extension
|
||||
- `sha256` The sha256 hash of the blob
|
||||
- `size` The size of the blob in bytes
|
||||
- `type` (optional) The MIME type of the blob
|
||||
- `type` The MIME type of the blob (falling back to `application/octet-stream` if unknown)
|
||||
- `uploaded` The unix timestamp of when the blob was uploaded to the server
|
||||
|
||||
Servers MUST include a file extension in the URL in the `url` field to allow clients to easily embed the URL in social posts or other content
|
||||
@@ -38,18 +38,25 @@ Example:
|
||||
|
||||
The `PUT /upload` 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 data
|
||||
|
||||
The endpoint MUST NOT modify the blob in any way and should return the exact same sha256 that was uploaded. This is critical to allow users to re-upload their blobs to new servers
|
||||
The endpoint MUST NOT modify the blob in any way and SHOULD return the exact same sha256 that was uploaded. This is critical to allow users to re-upload their blobs to new servers
|
||||
|
||||
The endpoint MUST return a [Blob Descriptor](#blob-descriptor) if the upload was successful or an error object if it was not
|
||||
|
||||
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
|
||||
|
||||
### 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](./01.md#proxying-and-redirection-optional)), as external
|
||||
servers may rely on the file extension to serve the blob correctly.
|
||||
|
||||
### Upload Authorization (Optional)
|
||||
|
||||
Servers MAY 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`
|
||||
2. MUST contain at least one `x` tag matching the sha256 hash of the body of the request
|
||||
2. The authorization event MUST contain at least one `x` tag matching the sha256 hash of the body of the request
|
||||
|
||||
Example Authorization event:
|
||||
|
||||
@@ -69,21 +76,25 @@ Example Authorization event:
|
||||
}
|
||||
```
|
||||
|
||||
## GET /list/pubkey - List Blobs (Optional)
|
||||
## GET /list/pubkey - List Blobs (Unrecommended)
|
||||
|
||||
The `/list/<pubkey>` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that where uploaded by the specified pubkey
|
||||
**Note:** The `/list` endpoint is optional and unrecommended. It is not necessary for all servers to implement the `/list` endpoint. Servers MAY implement this endpoint, but are not required to do so.
|
||||
|
||||
The endpoint MUST support a `since` and `until` query parameter to limit the returned blobs by their `uploaded` date
|
||||
The `/list/<pubkey>` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that were uploaded by the specified pubkey
|
||||
|
||||
Servers may reject a list for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
|
||||
The endpoint MUST support `cursor` and `limit` query parameters for cursor based pagination. The `cursor` parameter MUST be the `sha256` hash of the last blob in the previous page, or omitted to request the first page. The `limit` parameter specifies the maximum number of results to return. The returned array of blob descriptors MUST be sorted by the `uploaded` date in descending order and MUST NOT include the blob at the cursor
|
||||
|
||||
The endpoint MAY support `since` and `until` query parameters to filter the list of blobs by their `uploaded` date. These parameters are deprecated for pagination purposes as they do not preserve server resources
|
||||
|
||||
Servers MAY reject a list request for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
|
||||
|
||||
### List Authorization (optional)
|
||||
|
||||
The server may optionally require Authorization when listing blobs uploaded by the pubkey
|
||||
The server MAY optionally require Authorization when listing blobs uploaded by the pubkey
|
||||
|
||||
In this case the server must perform additional checks on the authorization event
|
||||
In this case the server MUST perform additional checks on the authorization event
|
||||
|
||||
1. The `t` tag must be set to `list`
|
||||
1. The `t` tag MUST be set to `list`
|
||||
|
||||
Example Authorization event:
|
||||
|
||||
@@ -106,16 +117,16 @@ Example Authorization event:
|
||||
|
||||
Servers MUST accept `DELETE` requests to the `/<sha256>` endpoint
|
||||
|
||||
Servers may reject a delete request 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 a delete request for any reason and SHOULD respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
|
||||
|
||||
### Delete Authorization (required)
|
||||
|
||||
Servers MUST accept an authorization event when deleting blobs
|
||||
|
||||
Servers should perform additional checks on the authorization event
|
||||
Servers SHOULD perform additional checks on the authorization event
|
||||
|
||||
1. The `t` tag must be set to `delete`
|
||||
2. MUST contain at least one `x` tag matching the sha256 hash of the blob being deleted
|
||||
1. The `t` tag MUST be set to `delete`
|
||||
2. The authorization event MUST contain at least one `x` tag matching the sha256 hash of the blob being deleted
|
||||
|
||||
When multiple `x` tags are present on the authorization event the server MUST only delete the blob listed in the URL.
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ Take the following event as an example
|
||||
|
||||
Once the client discovers that the URL `https://cdn.broken-domain.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf` is no longer available. It can perform the following steps to find the blob:
|
||||
|
||||
1. Get the SHA256 has from the URL
|
||||
1. Get the SHA256 hash from the URL
|
||||
2. Look for the authors server list `kind:10063`
|
||||
3. If found, Attempt to retrieve the blob from each `server` listed started with the first
|
||||
4. If not found, the client MAY fallback to using a well-known popular blossom server to retrieve the blob
|
||||
|
||||
29
buds/04.md
29
buds/04.md
@@ -8,7 +8,7 @@ Defines the `/mirror` endpoint
|
||||
|
||||
## PUT /mirror - Mirror Blob
|
||||
|
||||
A server may expose a `PUT /mirror` endpoint to allow users to copy a blob from a URL instead of uploading it
|
||||
A server MAY expose a `PUT /mirror` endpoint to allow users to copy a blob from a URL instead of uploading it
|
||||
|
||||
Clients MUST pass the URL of the remote blob as a stringified JSON object in the request body
|
||||
|
||||
@@ -19,23 +19,28 @@ Clients MUST pass the URL of the remote blob as a stringified JSON object in the
|
||||
}
|
||||
```
|
||||
|
||||
Clients MAY set the `Authorization` header to an upload authorization event defined in [BUD-02](./02.md#upload-authorization-required). When using authorization, the event MUST be of type "upload".
|
||||
Clients MAY set the `Authorization` header to an upload authorization event defined in [BUD-02](./02.md#upload-authorization-optional). When using authorization, the event MUST be of type "upload".
|
||||
|
||||
The `/mirror` endpoint MUST download the blob from the specified URL and verify that there is at least one `x` tag in the authorization event matching the sha256 hash of the download blob
|
||||
|
||||
**Multiple `x` tags in the authorization event MUST NOT be interpreted as the user requesting a bulk mirror.**
|
||||
**Multiple `x` tags in the authorization event MUST NOT be interpreted as the user requesting to mirror multiple blobs.**
|
||||
|
||||
The endpoint MUST return a [Blob Descriptor](#blob-descriptor) if the mirroring was successful or an error object if it was not
|
||||
The endpoint MUST return a [Blob Descriptor](#blob-descriptor) and a `2xx` status code if the mirroring was successful
|
||||
or a `4xx` status code and error message if it was not.
|
||||
|
||||
Servers should re-use the `Content-Type` header returned from the URL to discover the mime type of the blob. if none is returned it may use the file extension in the URL
|
||||
The destination server SHOULD use the `Content-Type` header returned from the origin server 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 reject a mirror request 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 use the `Content-Length` header to determine the size of the blob.
|
||||
|
||||
Servers MAY reject a mirror request for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection.
|
||||
|
||||
## Example Flow
|
||||
|
||||
1. Client signs authorization event and uploads blob to Server A
|
||||
1. Server A returns blob descriptor with `url`
|
||||
1. Client sends the `url` to Server B `/mirror` using the original authorization event
|
||||
1. Server B downloads blob from Server A using the url
|
||||
1. Server B verifies downloaded blob hash matches `x` tag in authorization event
|
||||
1. Server B returns [Blob Descriptor](./02.md#blob-descriptor)
|
||||
1. Client signs an `upload` authorization event and uploads blob to Server A
|
||||
1. Server A returns a [Blob Descriptor](./02.md#blob-descriptor) with the `url`
|
||||
1. Client sends the `url` to Server B `/mirror` using the original `upload` authorization event
|
||||
1. Server B downloads the blob from Server A using the `url`
|
||||
1. Server B verifies the downloaded blob hash matches the `x` tag in the authorization event
|
||||
1. Server B returns a [Blob Descriptor](./02.md#blob-descriptor)
|
||||
|
||||
@@ -20,7 +20,7 @@ Servers MAY reject media uploads for any reason and should respond with the appr
|
||||
|
||||
Servers MAY require a `media` [authorization event](./02.md#upload-authorization-required) to identify the uploader
|
||||
|
||||
If a server requires a `media` authorization event it MUST preform the following checks
|
||||
If a server requires a `media` authorization event it MUST perform the following checks
|
||||
|
||||
1. The `t` tag MUST be set to `media`
|
||||
2. MUST contain at least one `x` tag matching the sha256 hash of the body of the request
|
||||
@@ -33,7 +33,7 @@ Servers MUST respond to `HEAD` requests on the `/media` endpoint in a similar wa
|
||||
|
||||
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
|
||||
How the blob is optimized is the sole responsibility 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
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Defines how clients can verify if the upload can be completed before sending the
|
||||
|
||||
## 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-Reason` to indicate some human readable message about the 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-Reason` to indicate some human readable message about the upload requirements.
|
||||
|
||||
### Headers
|
||||
|
||||
@@ -38,7 +38,7 @@ Example response from the server if the upload can be done:
|
||||
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-Reason` with a human readable error message.
|
||||
If the upload cannot proceed, the server MUST return an appropriate `4xx` HTTP status code and a custom header `X-Reason` with a human readable error message.
|
||||
|
||||
Some examples of error messages:
|
||||
|
||||
|
||||
105
buds/07.md
Normal file
105
buds/07.md
Normal file
@@ -0,0 +1,105 @@
|
||||
BUD-07
|
||||
======
|
||||
|
||||
Paid upload and download
|
||||
---------------
|
||||
|
||||
`draft` `optional`
|
||||
|
||||
Payment requirements for blob storage.
|
||||
|
||||
## Payment Required
|
||||
|
||||
Some servers MAY require payment for uploads, downloads, or any other endpoint. In such cases, these endpoints MUST return a **402 Payment Required** status code.
|
||||
|
||||
Some endpoints a server may require payment for:
|
||||
|
||||
- [`HEAD /upload`](./06.md) to signal that payment is required for the `PUT` request ( if [BUD-06](./06.md) is supported )
|
||||
- [`PUT /upload`](./02.md#put-upload---upload-blob) to require payment for uploads
|
||||
- [`HEAD /<sha256>`](./01.md#head-sha256---has-blob) to signal that payment is required for the `GET` request
|
||||
- [`GET /<sha256>`](./01.md#get-sha256---get-blob) to require payment for downloads ( maybe charge by MB downloaded? )
|
||||
- [`HEAD /media`](./05.md) and [`PUT /upload`](./05.md) to require payment for media optimizations ( if [BUD-06](./06.md) is supported )
|
||||
|
||||
When payment is required, the server MUST include one or more `X-{payment_method}` header(s), each corresponding to a supported payment method.
|
||||
|
||||
## Server headers
|
||||
|
||||
The 402 status code and `X-{payment_method}` header is used by the server to inform the client that a payment is required for the requested operation. The server MUST provide specific headers for each supported payment method.
|
||||
|
||||
Supported payment methods:
|
||||
|
||||
- `X-Cashu`: Payment details for the cashu payment method, adhering to the [NUT-24](https://github.com/cashubtc/nuts/blob/main/24.md) standard.
|
||||
- `X-Lightning`: Payment details for the lightning payment method, adhering to the [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) standard.
|
||||
|
||||
If a server supports multiple payment methods, it MAY send multiple `X-{payment_method}` headers in the same response.
|
||||
|
||||
Schema:
|
||||
|
||||
```http
|
||||
HTTP/1.1 402 Payment Required
|
||||
X-{payment_method}: "<encoded_payload_according_to_{payment_method}_spec>"
|
||||
```
|
||||
|
||||
### `X-Cashu` Header
|
||||
|
||||
When using the X-Cashu header, the server MUST adhere to the [NUT-24](https://github.com/cashubtc/nuts/blob/main/24.md) standard.
|
||||
|
||||
Example for cashu:
|
||||
|
||||
```http
|
||||
HTTP/1.1 402 Payment Required
|
||||
X-Cashu: creqApWF0gaNhdGVub3N0cmFheKlucHJvZmlsZTFxeTI4d3VtbjhnaGo3dW45ZDNzaGp0bnl2OWtoMnVld2Q5aHN6OW1od2RlbjV0ZTB3ZmprY2N0ZTljdXJ4dmVuOWVlaHFjdHJ2NWhzenJ0aHdkZW41dGUwZGVoaHh0bnZkYWtxcWd5ZGFxeTdjdXJrNDM5eWtwdGt5c3Y3dWRoZGh1NjhzdWNtMjk1YWtxZWZkZWhrZjBkNDk1Y3d1bmw1YWeBgmFuYjE3YWloYjdhOTAxNzZhYQphdWNzYXRhbYF4Imh0dHBzOi8vbm9mZWVzLnRlc3RudXQuY2FzaHUuc3BhY2U
|
||||
```
|
||||
|
||||
### `X-Lightning` Header
|
||||
|
||||
When using the X-Lightning header, the server MUST adhere to the [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) standard.
|
||||
Example for lightning:
|
||||
|
||||
```http
|
||||
HTTP/1.1 402 Payment Required
|
||||
X-Lightning: lnbc30n1pnnmw3lpp57727jjq8zxctahfavqacymellq56l70f7lwfkmhxfjva6dgul2zqhp5w48l28v60yvythn6qvnpq0lez54422a042yaw4kq8arvd68a6n7qcqzzsxqyz5vqsp5sqezejdfaxx5hge83tf59a50h6gagwah59fjn9mw2d5mn278jkys9qxpqysgqt2q2lhjl9kgfaqz864mhlsspftzdyr642lf3zdt6ljqj6wmathdhtgcn0e6f4ym34jl0qkt6gwnllygvzkhdlpq64c6yv3rta2hyzlqp8k28pz
|
||||
```
|
||||
|
||||
### Client implementation
|
||||
|
||||
Clients MUST parse and validate the `X-{payment_method}` header received from the server. The client SHOULD provide a way for the user to complete the payment and retry the request using the same `X-{payment_method}` header.
|
||||
|
||||
The client MUST provide the payment proof when re-trying the request using the same `X-{payment_method}` header that was chosen. The payment proof MUST align with the payment method specification:
|
||||
|
||||
- For cashu the payment proof should be a serialized `cashuB` token in the `X-Cashu` header according to [NUT-24](https://github.com/cashubtc/nuts/blob/main/24.md#client-payment).
|
||||
- For lightning the payment proof should be the preimage of the payment request according to [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md).
|
||||
|
||||
Schema:
|
||||
|
||||
```http
|
||||
X-{payment_method}: "<encoded_payment_proof_according_to_{payment_method}_spec>"
|
||||
```
|
||||
|
||||
Example for Cashu:
|
||||
|
||||
```http
|
||||
X-Cashu: cashuBo2F0gqJhaUgA_9SLj17PgGFwgaNhYQFhc3hAYWNjMTI0MzVlN2I4NDg0YzNjZjE4NTAxNDkyMThhZjkwZjcxNmE1MmJmNGE1ZWQzNDdlNDhlY2MxM2Y3NzM4OGFjWCECRFODGd5IXVW
|
||||
```
|
||||
|
||||
Example for Lightning:
|
||||
|
||||
```http
|
||||
X-Lightning: 966fcb8f153339372f9a187f725384ff4ceae0047c25b9ce607488d7c7e93bba
|
||||
```
|
||||
|
||||
**Special Note on HEAD Requests**
|
||||
|
||||
The HEAD endpoints are only used to retrieve blob or server information. They MUST NOT be retried with payment proof. Instead, clients should complete the payment and proceed with the `PUT` or `GET` request.
|
||||
|
||||
### Error handling
|
||||
|
||||
If the client fails to provide the payment proof (expired invoice, invalid token, etc.) the server MUST respond with **400 Bad request** status code and include a `X-Reason` header with a human-readable message. The client SHOULD inform the user about the error and provide a way to retry the request.
|
||||
|
||||
### Extending with Future Payment Methods
|
||||
|
||||
To support future payment methods (e.g., other Layer 2 solutions), the specification allows the addition of new X-{payment_method} headers. Each new method MUST adhere to the following:
|
||||
|
||||
New methods MUST use a unique `X-{payment_method}` header containing the specific payment details.
|
||||
|
||||
New methods MUST adhere their own specification, which MUST be publicly available and linked in the header.
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
This bud defines a new endpoint for clients and users to report blobs to servers.
|
||||
|
||||
|
||||
### PUT /report - reporting a blob
|
||||
|
||||
The request body MUST be a signed [NIP-56](https://github.com/nostr-protocol/nips/blob/master/56.md) report event with one or more `x` tags containing the hashes of the blobs being reported.
|
||||
@@ -35,7 +34,7 @@ The clients can show a blob report button on posts or in blob details. Or its RE
|
||||
|
||||
### Server behavior
|
||||
|
||||
The servers MAY keep the reports somewhere for operators to check and take action on them. they MAY use a list of trusted people or moderators to directly take action on blob without operator request.
|
||||
The servers MAY keep the reports somewhere for operators to check and take action on them. they MAY use a list of trusted people or moderators to directly take action on blob without operator request.
|
||||
|
||||
Servers MAY consider removed blobs sha256 as blocked to prevent rewrite.
|
||||
Servers SHOULD advertise a route or landing page to provide their rules and term of service which affects the report process.
|
||||
Servers SHOULD advertise a route or landing page to provide their rules and terms of service which affects the report process.
|
||||
|
||||
207
buds/10.md
Normal file
207
buds/10.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# BUD-10
|
||||
|
||||
## Blossom URI Schema
|
||||
|
||||
`draft` `optional`
|
||||
|
||||
Defines a URI schema for referencing Blossom blobs similar to magnet links. This allows users to share blob references that include discovery hints for locating the blob on other Blossom servers.
|
||||
|
||||
## URI Format
|
||||
|
||||
The `blossom:` URI schema MUST follow this format:
|
||||
|
||||
```
|
||||
blossom:<sha256>.<ext>[?param1=value1¶m2=value2...]
|
||||
```
|
||||
|
||||
### Components
|
||||
|
||||
- `blossom:` - The URI scheme identifier
|
||||
- `<sha256>` - A 64 character lowercase hexadecimal sha256 hash of the blob
|
||||
- `.<ext>` - A file extension (e.g., `.pdf`, `.png`, `.jpg`, `.mp4`). If the file extension is unknown, it MUST default to `.bin`
|
||||
- `[?params]` - Optional query parameters for discovery hints
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.png?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.bin
|
||||
```
|
||||
|
||||
## Query Parameters
|
||||
|
||||
The `blossom:` URI MAY include the following optional query parameters to assist with blob discovery:
|
||||
|
||||
### `as` - Author
|
||||
|
||||
The `as` parameter specifies the hex pubkey of a user who uploaded the blob. This parameter MAY be repeated multiple times to specify multiple potential authors.
|
||||
|
||||
Clients can use this parameter to lookup the author's [BUD-03](./03.md) server list (`kind:10063`) and attempt to retrieve the blob from those servers.
|
||||
|
||||
Example:
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0
|
||||
```
|
||||
|
||||
Multiple authors:
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&as=781208004e09102d7da3b7345e64fd193cd1bc3fce8fdae6008d77f9cabcd036
|
||||
```
|
||||
|
||||
### `xs` - Server
|
||||
|
||||
The `xs` parameter specifies a server domain where the blob may be available. This parameter MAY be repeated multiple times to specify multiple server hints.
|
||||
|
||||
The value SHOULD be a domain name only. Clients MUST assume the server operates at the root of the domain as per [BUD-01](./01.md#endpoints). The protocol scheme (http/https) MAY be included but is optional. When no scheme is specified, clients SHOULD try both `https://` and `http://` with preference given to `https://`.
|
||||
|
||||
Example:
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth
|
||||
```
|
||||
|
||||
With optional scheme:
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=https://cdn.satellite.earth
|
||||
```
|
||||
|
||||
Multiple servers:
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&xs=blossom.primal.net
|
||||
```
|
||||
|
||||
### `sz` - Size
|
||||
|
||||
The `sz` parameter MAY be used to specify the size of the blob in bytes. This can help clients:
|
||||
|
||||
- Verify the downloaded blob matches the expected size
|
||||
- Display download progress or estimated time
|
||||
- Decide whether to download the blob based on size constraints
|
||||
- Pre-allocate storage space
|
||||
|
||||
Example:
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?sz=184292
|
||||
```
|
||||
|
||||
The size MUST be a positive integer representing the exact number of bytes in the blob. Clients SHOULD verify that the downloaded blob size matches the `sz` parameter if provided.
|
||||
|
||||
### Combined Parameters
|
||||
|
||||
All parameters MAY be combined in a single URI:
|
||||
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&xs=blossom.primal.net&sz=184292
|
||||
```
|
||||
|
||||
## Client Implementation
|
||||
|
||||
### Parsing blossom URIs
|
||||
|
||||
When parsing a `blossom:` URI, clients MUST:
|
||||
|
||||
1. Verify the URI starts with the `blossom:` scheme
|
||||
2. Extract the 64 character hexadecimal sha256 hash
|
||||
3. Extract the file extension (which MUST be present)
|
||||
4. Parse any query parameters (`as`, `xs`, and `sz`) into appropriate types to handle multiple values
|
||||
|
||||
### Resolution Strategy
|
||||
|
||||
When resolving a `blossom:` URI to retrieve the actual blob, clients SHOULD attempt retrieval in the following order:
|
||||
|
||||
1. **Server Hints**: If the URI contains `xs` parameters, attempt to retrieve the blob from each specified server in the order they appear
|
||||
- For servers without a protocol scheme, try `https://` first, then `http://`
|
||||
- Request the blob using the [BUD-01](./01.md#get-sha256---get-blob) `GET /<sha256>` endpoint
|
||||
- Include the file extension from the URI if present
|
||||
- If the `sz` parameter is present, verify the `Content-Length` header matches before downloading
|
||||
|
||||
2. **Author Server Lists**: If the URI contains `as` parameters, for each author pubkey:
|
||||
- Fetch the author's [BUD-03](./03.md) server list (`kind:10063`)
|
||||
- Attempt to retrieve the blob from each server in the author's list in order
|
||||
- If multiple authors are specified, try each author's server list before giving up
|
||||
|
||||
3. **Fallback Servers**: If the blob cannot be found using hints, clients MAY fallback to:
|
||||
- Well-known public Blossom servers
|
||||
- Local cache or previously known locations
|
||||
- User-configured default servers
|
||||
|
||||
When downloading is complete, if the `sz` parameter was provided, clients SHOULD verify that the downloaded blob size matches the expected size.
|
||||
|
||||
### Example Resolution Flow
|
||||
|
||||
Given this URI:
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292
|
||||
```
|
||||
|
||||
A client would:
|
||||
|
||||
1. Try `http://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf`
|
||||
2. Check that `Content-Length` header is `184292` before downloading
|
||||
3. If that fails, fetch the `kind:10063` server list for pubkey `ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0`
|
||||
4. Try each server from the author's list in order
|
||||
5. Verify the downloaded blob is exactly `184292` bytes
|
||||
6. If still not found, fallback to well-known servers or local cache
|
||||
|
||||
### Creating and Sharing blossom URIs
|
||||
|
||||
When creating or sharing a `blossom:` URI, clients MUST:
|
||||
|
||||
1. Always include the sha256 hash
|
||||
2. Always include a file extension - if the file extension is unknown or cannot be determined, default to `.bin` (similar to how [BUD-01](./01.md#get-sha256---get-blob) defaults the MIME type to `application/octet-stream`)
|
||||
|
||||
Clients SHOULD also:
|
||||
|
||||
3. Include the `sz` parameter with the blob size in bytes to help with verification and download management
|
||||
4. Include at least one `xs` parameter pointing to a server where the blob is known to exist
|
||||
5. Include the `as` parameter with the uploader's pubkey to enable future discovery via their server list
|
||||
6. Include multiple `xs` parameters if the blob has been mirrored to multiple servers
|
||||
|
||||
Example of creating a URI after upload:
|
||||
|
||||
```javascript
|
||||
// After uploading to cdn.satellite.earth
|
||||
const uri = `blossom:${sha256}.${ext}?xs=cdn.satellite.earth&as=${userPubkey}&sz=${size}`;
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
The `blossom:` URI schema enables several use cases:
|
||||
|
||||
- **Decentralized Content Addressing**: Share content by hash with discovery hints instead of relying on a single server URL
|
||||
- **Resilient Links**: Links that can survive server outages by including multiple server hints or author information
|
||||
- **P2P Sharing**: Share blob references that don't depend on a specific server remaining online
|
||||
|
||||
## Examples
|
||||
|
||||
### Minimal URI
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf
|
||||
```
|
||||
|
||||
### Unknown File Type
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.bin
|
||||
```
|
||||
|
||||
### With Single Server Hint
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth
|
||||
```
|
||||
|
||||
### With Size and Author
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292
|
||||
```
|
||||
|
||||
### Full Featured URI
|
||||
```
|
||||
blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&xs=blossom.primal.net&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292
|
||||
```
|
||||
|
||||
### Image with Multiple Authors and Servers
|
||||
```
|
||||
blossom:a7b3c2d1e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1.png?xs=cdn.example.com&xs=media.nostr.build&as=781208004e09102d7da3b7345e64fd193cd1bc3fce8fdae6008d77f9cabcd036&as=b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e&sz=2547831
|
||||
```
|
||||
|
||||
13
implementations/README.md
Normal file
13
implementations/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Blossom Implementations
|
||||
|
||||
This directory contains possible uses and implementations of the Blossom protocol. They are not part of the official Blossom specification but provide examples and inspiration for how the protocol can be used.
|
||||
|
||||
## Implementations
|
||||
|
||||
- [Local Blossom Cache](./local-blossom-cache.md)
|
||||
- [HLS Video Formatting](./hls-video-formatting.md)
|
||||
|
||||
## Contributions
|
||||
|
||||
Contributions are welcome! Documents in this directory MUST be compatible with the existing [BUDs](../buds) and should be focused on a single use case or implementation.
|
||||
|
||||
118
implementations/hls-video-formatting.md
Normal file
118
implementations/hls-video-formatting.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# HLS Video Formatting
|
||||
|
||||
This document explains how to format [HLS](https://datatracker.ietf.org/doc/html/rfc8216) (HTTP Live Streaming) videos to be compatible with [BUD-01](./01.md) blob retrieval.
|
||||
|
||||
## Overview
|
||||
|
||||
HLS videos consist of multiple files:
|
||||
- A master playlist (`.m3u8`) that references variant playlists
|
||||
- Variant playlists (`.m3u8`) that reference media segments
|
||||
- Media segment files (typically `.ts` files)
|
||||
|
||||
Each file MUST be uploaded as a separate blob and referenced by its SHA256 hash using the [BUD-01](./01.md#get-sha256---get-blob) `GET /<sha256>` endpoint format.
|
||||
|
||||
## Relative Paths
|
||||
|
||||
To ensure compatibility across different Blossom servers and allow easy server switching, all URLs in HLS playlists MUST use relative paths containing the SHA256 hash of the referenced blob.
|
||||
|
||||
Clients MUST NOT include the full server domain in playlist URLs. This allows the same playlist to work with any Blossom server that hosts the referenced blobs.
|
||||
|
||||
## Master Playlist Format
|
||||
|
||||
The master playlist (`.m3u8`) MUST reference variant playlists using relative paths with SHA256 hashes.
|
||||
|
||||
The master playlist MUST have the MIME type `application/vnd.apple.mpegurl` or `application/x-mpegURL`.
|
||||
|
||||
Example master playlist:
|
||||
|
||||
```m3u8
|
||||
#EXTM3U
|
||||
#EXT-X-VERSION:3
|
||||
#EXT-X-STREAM-INF:BANDWIDTH=1280000,RESOLUTION=854x480
|
||||
a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456.m3u8
|
||||
#EXT-X-STREAM-INF:BANDWIDTH=2560000,RESOLUTION=1280x720
|
||||
f6e5d4c3b2a1098765432109876543210987654321fedcba0987654321fedcba.m3u8
|
||||
```
|
||||
|
||||
## Variant Playlist Format
|
||||
|
||||
Variant playlists (`.m3u8`) MUST reference media segments using relative paths with SHA256 hashes.
|
||||
|
||||
Each segment URL MUST be a relative path containing the SHA256 hash of the segment file. The file extension (`.ts`, `.m4s`, etc.) MAY be included for compatibility with HLS clients.
|
||||
|
||||
Example variant playlist:
|
||||
|
||||
```m3u8
|
||||
#EXTM3U
|
||||
#EXT-X-VERSION:3
|
||||
#EXT-X-TARGETDURATION:10
|
||||
#EXT-X-MEDIA-SEQUENCE:0
|
||||
#EXTINF:10.000,
|
||||
b82fcf4dbcec2d8fab7d94bdd48b070aa6e74d7240b1965a0b28c128d6858477.ts
|
||||
#EXTINF:10.000,
|
||||
cd2a98d055eef5ec3aca73bd136a40340539138da73144d589d9de5a3a52149a.ts
|
||||
#EXTINF:10.000,
|
||||
128e690f89419ecbea473a490c42cac94a2293ecf1f57d60492ceafce3d5cfdb.ts
|
||||
#EXT-X-ENDLIST
|
||||
```
|
||||
|
||||
## Media Segments
|
||||
|
||||
Media segment files (typically `.ts` files) MUST be uploaded as separate blobs. Each segment MUST be retrievable via the [BUD-01](./01.md#get-sha256---get-blob) `GET /<sha256>` endpoint.
|
||||
|
||||
The server SHOULD set the `Content-Type` header appropriately:
|
||||
- `.ts` files: `video/mp2t` or `video/MP2T`
|
||||
- `.m4s` files: `video/iso.segment` or `video/mp4`
|
||||
|
||||
## Client Implementation
|
||||
|
||||
When generating HLS playlists for Blossom:
|
||||
|
||||
1. Upload each media segment as a separate blob using [BUD-02](./02.md#put-upload---upload-blob) `PUT /upload`
|
||||
2. Upload each variant playlist as a separate blob
|
||||
3. Upload the master playlist as a separate blob
|
||||
4. In all playlists, use relative paths containing only the SHA256 hash (and optional file extension) of the referenced blob
|
||||
5. When serving the master playlist, clients MAY prepend the current server's base URL to resolve relative paths
|
||||
|
||||
Example client flow:
|
||||
|
||||
1. Upload segment `segment001.ts` → get SHA256: `1a2b3c4d...`
|
||||
2. Upload segment `segment002.ts` → get SHA256: `2b3c4d5e...`
|
||||
3. Create variant playlist referencing `1a2b3c4d...ts` and `2b3c4d5e...ts`
|
||||
4. Upload variant playlist → get SHA256: `a1b2c3d4...`
|
||||
5. Create master playlist referencing `a1b2c3d4...m3u8`
|
||||
6. Upload master playlist → get SHA256: `f9e8d7c6...`
|
||||
|
||||
## Server Implementation
|
||||
|
||||
When serving HLS playlists, servers MUST:
|
||||
|
||||
1. Return the playlist content with the appropriate `Content-Type` header (`application/vnd.apple.mpegurl` or `application/x-mpegURL`)
|
||||
2. Serve playlists via the [BUD-01](./01.md#get-sha256---get-blob) `GET /<sha256>` endpoint
|
||||
3. Support optional file extensions (e.g., `/<sha256>.m3u8`) as specified in [BUD-01](./01.md#get-sha256---get-blob)
|
||||
|
||||
When a client requests a playlist blob, the server MUST return the playlist content as-is, without modifying relative paths. The client is responsible for resolving relative paths to absolute URLs using the current server's base URL.
|
||||
|
||||
## URL Resolution
|
||||
|
||||
When a client retrieves a playlist from `https://cdn.example.com/<sha256>.m3u8`, relative paths in the playlist (e.g., `a1b2c3d4...m3u8`) MUST be resolved relative to the playlist's origin.
|
||||
|
||||
For example, if a playlist is served from `https://cdn.example.com/f9e8d7c6...m3u8` and contains a relative path `a1b2c3d4...m3u8`, the client SHOULD resolve it to `https://cdn.example.com/a1b2c3d4...m3u8`.
|
||||
|
||||
This allows the same playlist blob to work with any Blossom server, as long as all referenced blobs are available on that server.
|
||||
|
||||
## Example Complete Structure
|
||||
|
||||
```
|
||||
Master Playlist (SHA256: f9e8d7c6...)
|
||||
└─> Variant Playlist 1 (SHA256: a1b2c3d4...)
|
||||
└─> Segment 1 (SHA256: 1a2b3c4d...)
|
||||
└─> Segment 2 (SHA256: 2b3c4d5e...)
|
||||
└─> Segment 3 (SHA256: 3c4d5e6f...)
|
||||
└─> Variant Playlist 2 (SHA256: b2c3d4e5...)
|
||||
└─> Segment 1 (SHA256: 4d5e6f78...)
|
||||
└─> Segment 2 (SHA256: 5e6f7890...)
|
||||
└─> Segment 3 (SHA256: 6f789012...)
|
||||
```
|
||||
|
||||
All references between these files use relative paths containing only SHA256 hashes, making the entire HLS structure portable across different Blossom servers.
|
||||
102
implementations/local-blossom-cache.md
Normal file
102
implementations/local-blossom-cache.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Local Blossom Cache
|
||||
|
||||
This document defines the specification for a local blob cache server that can be hosted on `127.0.0.1:24242` to provide fast, local access to cached blobs or proxy requests to other public Blossom servers.
|
||||
|
||||
## Server Address
|
||||
|
||||
A local blob cache server MUST be accessible on `http://127.0.0.1:24242`. The port `24242` is chosen to align with the Nostr event kind used for Blossom authorization events.
|
||||
|
||||
## Health Check Endpoint
|
||||
|
||||
The server MUST respond with a 2xx HTTP status code (typically `200 OK`) on the `HEAD /` endpoint to allow local applications to easily detect if the cache server is available.
|
||||
|
||||
The `HEAD /` endpoint MUST return a 2xx HTTP status code. The response MUST NOT include a response body per [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231#section-4.3.2).
|
||||
|
||||
This endpoint enables simple health checks:
|
||||
|
||||
```bash
|
||||
curl -I http://127.0.0.1:24242/
|
||||
```
|
||||
|
||||
## Access Control
|
||||
|
||||
The server SHOULD NOT require any authentication for blob downloads or uploads. All requests MUST be served without requiring an `Authorization` header.
|
||||
|
||||
If an implementation needs to add access control, it SHOULD restrict access based on IP address to ensure requests only come from `127.0.0.1`. This ensures that local applications can freely access cached blobs without the overhead of signing authorization events.
|
||||
|
||||
## Blob Retrieval
|
||||
|
||||
The server MUST implement the `GET /<sha256>` and `HEAD /<sha256>` endpoints as defined in [BUD-01](./01.md#get-sha256---get-blob):
|
||||
|
||||
1. The server MUST accept optional file extensions in the URL (e.g., `/<sha256>.pdf`)
|
||||
2. The server MUST set appropriate `Content-Type` headers or default to `application/octet-stream`
|
||||
|
||||
## Range Requests
|
||||
|
||||
To better support mobile devices, video files, or low bandwidth connections, implementations SHOULD support range requests ([RFC 7233 section 3](https://www.rfc-editor.org/rfc/rfc7233#section-3)) on the `GET /<sha256>` endpoint and signal support using the `accept-ranges: bytes` and `content-length` headers on the `HEAD /<sha256>` endpoint.
|
||||
|
||||
See [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests) for more details.
|
||||
|
||||
## Proxy Hints
|
||||
|
||||
The server SHOULD accept [BUD-10](./10.md) query parameters `xs` (server) and `as` (author) hints on the `GET /<sha256>` endpoint to enable proxying blob requests to other Blossom servers when the blob is not available in the local cache.
|
||||
|
||||
### Query Parameter Format
|
||||
|
||||
When a blob is not found in the local cache, the server MAY use the following query parameters to attempt retrieval from other Blossom servers:
|
||||
|
||||
- `xs=<server>` - One or more server hints where the blob may be available
|
||||
- `as=<pubkey>` - One or more author pubkeys whose server lists may contain the blob
|
||||
|
||||
### Example Request
|
||||
|
||||
```
|
||||
GET /b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0
|
||||
```
|
||||
|
||||
### Proxy Behavior
|
||||
|
||||
When the server receives a request with proxy hints and the blob is not in the local cache:
|
||||
|
||||
1. The server SHOULD attempt to retrieve the blob from the servers specified in the `xs` parameters
|
||||
2. If `xs` hints fail, the server MAY attempt to retrieve the blob using the `as` parameters by:
|
||||
- Fetching the author's [BUD-03](./03.md) server list (`kind:10063`)
|
||||
- Attempting to retrieve the blob from servers in the author's list
|
||||
3. If the blob is successfully retrieved, the server SHOULD:
|
||||
- Cache the blob locally for future requests
|
||||
- Return the blob to the client with appropriate headers
|
||||
4. If the blob cannot be retrieved from any hint, the server MUST return a `404 Not Found` response
|
||||
|
||||
This proxy functionality allows the local cache server to act as a transparent proxy, automatically fetching and caching blobs from remote Blossom servers when needed.
|
||||
|
||||
## CORS Headers
|
||||
|
||||
The server MUST set the `Access-Control-Allow-Origin: *` header on all responses to ensure compatibility with web applications, as specified in [BUD-01](./01.md#cross-origin-headers).
|
||||
|
||||
## Use Cases
|
||||
|
||||
A local blob cache server enables several use cases:
|
||||
|
||||
- **Fast Local Access**: Applications can check the local cache first before making network requests to remote Blossom servers
|
||||
- **Offline Access**: Previously cached blobs remain accessible even when network connectivity is unavailable
|
||||
- **Bandwidth Savings**: Reduces redundant downloads of frequently accessed blobs
|
||||
- **Development**: Provides a simple local server for testing Blossom applications without requiring remote server access
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The server SHOULD implement efficient blob storage, such as using the sha256 hash as the filename or storage key
|
||||
- The server SHOULD implement cache eviction policies (e.g., LRU, size-based limits) to manage storage
|
||||
- The server SHOULD validate that downloaded blobs match their sha256 hash before caching
|
||||
- The server MAY implement the `HEAD /<sha256>` endpoint to allow clients to check blob availability without downloading
|
||||
|
||||
## Example Implementation Flow
|
||||
|
||||
1. Client requests blob: `GET http://127.0.0.1:24242/<sha256>`
|
||||
2. Server checks local cache
|
||||
3. If found: Return blob immediately
|
||||
4. If not found and proxy hints provided:
|
||||
- Attempt to fetch from `xs` server hints
|
||||
- If that fails, attempt to fetch using `as` author hints
|
||||
- Cache the blob if successfully retrieved
|
||||
- Return the blob to the client
|
||||
5. If not found and no proxy hints: Return `404 Not Found`
|
||||
Reference in New Issue
Block a user