mirror of
https://github.com/hzrd149/blossom.git
synced 2025-12-10 23:38:51 +00:00
Compare commits
1 Commits
42b6c568fc
...
multi-part
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
edb095118a |
39
README.md
39
README.md
@@ -4,31 +4,13 @@ Blossom uses [nostr](https://github.com/nostr-protocol/nostr) public / private k
|
|||||||
|
|
||||||
## What is it?
|
## What is it?
|
||||||
|
|
||||||
Blossom is a specification for a set of HTTP endpoints that allow users to store blobs of data on publicly accessible servers
|
Blossom is a spec for a set of HTTP endpoints that allow users to store blobs of data on publicly accessible servers
|
||||||
|
|
||||||
## What are blobs
|
## What are blobs
|
||||||
|
|
||||||
Blobs are packs of binary data addressed by their sha256 hash
|
Blobs are packs of binary data addressed by their sha256 hash
|
||||||
|
|
||||||
## Protocol specification (BUDs)
|
## How does it work?
|
||||||
|
|
||||||
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
|
Blossom Servers expose a few endpoints for managing blobs
|
||||||
|
|
||||||
@@ -50,6 +32,23 @@ Blossom Servers expose a few endpoints for managing blobs
|
|||||||
- `Authentication`: Signed [nostr event](./buds/05.md#upload-authorization)
|
- `Authentication`: Signed [nostr event](./buds/05.md#upload-authorization)
|
||||||
- `PUT /report` [BUD-09](./buds/09.md)
|
- `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
|
## Event kinds
|
||||||
|
|
||||||
| kind | description | BUD |
|
| kind | description | BUD |
|
||||||
|
|||||||
19
buds/00.md
19
buds/00.md
@@ -1,19 +0,0 @@
|
|||||||
# 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.
|
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,
|
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,
|
servers MUST also set, at minimum, the `Access-Control-Allow-Headers: Authorization, *` and `Access-Control-Allow-Methods: GET, PUT,
|
||||||
DELETE` headers.
|
DELETE` headers.
|
||||||
|
|
||||||
The header `Access-Control-Max-Age: 86400` MAY be set to cache the results of a preflight request for 24 hours.
|
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 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 intended 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 inteded 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.
|
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,29 +75,12 @@ All endpoints MUST be served from the root of the domain (eg. the `/upload` endp
|
|||||||
|
|
||||||
## GET /sha256 - Get Blob
|
## GET /sha256 - Get Blob
|
||||||
|
|
||||||
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 `GET /<sha256>` endpoint MUST return the contents of the blob with the `Content-Type` header set to the appropriate MIME-type
|
||||||
|
|
||||||
The endpoint MUST accept an optional file extension in the URL. ie. `.pdf`, `.png`, etc
|
The endpoint MUST accept an optional file extension in the URL. ie. `.pdf`, `.png`, etc
|
||||||
|
|
||||||
Regardless of the file extension, the server MUST return the MIME type of the blob in the `Content-Type` header. If the
|
If the endpoints returns a 301 or 302 redirect it MUST redirect to a URL containing the same sha256 hash as the requested blob.
|
||||||
server does not know the MIME type of the blob, it MUST default to `application/octet-stream`
|
This ensures that if a user was to copy or reuse the redirect URL it would still contain the original sha256 hash
|
||||||
|
|
||||||
### 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)
|
### Get Authorization (optional)
|
||||||
|
|
||||||
@@ -148,10 +131,7 @@ Example event for retrieving multiple blobs from single server:
|
|||||||
|
|
||||||
## HEAD /sha256 - Has Blob
|
## HEAD /sha256 - Has Blob
|
||||||
|
|
||||||
The `HEAD /<sha256>` endpoint SHOULD be identical to the `GET /<sha256>` endpoint except that it MUST NOT return the
|
The `HEAD /<sha256>` endpoint MUST respond with either a `200` or `404` status code
|
||||||
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
|
The endpoint MUST accept an optional file extension in the URL similar to the `GET /<sha256>` endpoint. ie. `.pdf`, `.png`, etc
|
||||||
|
|
||||||
|
|||||||
39
buds/02.md
39
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
|
- `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
|
- `sha256` The sha256 hash of the blob
|
||||||
- `size` The size of the blob in bytes
|
- `size` The size of the blob in bytes
|
||||||
- `type` The MIME type of the blob (falling back to `application/octet-stream` if unknown)
|
- `type` (optional) The MIME type of the blob
|
||||||
- `uploaded` The unix timestamp of when the blob was uploaded to the server
|
- `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
|
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,25 +38,18 @@ 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 `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
|
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)
|
### 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`
|
1. The `t` tag MUST be set to `upload`
|
||||||
2. The authorization event 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 body of the request
|
||||||
|
|
||||||
Example Authorization event:
|
Example Authorization event:
|
||||||
|
|
||||||
@@ -78,21 +71,19 @@ Example Authorization event:
|
|||||||
|
|
||||||
## GET /list/pubkey - List Blobs (Optional)
|
## GET /list/pubkey - List Blobs (Optional)
|
||||||
|
|
||||||
The `/list/<pubkey>` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that were 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
|
||||||
|
|
||||||
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 MUST support a `since` and `until` query parameter to limit the returned blobs by their `uploaded` date
|
||||||
|
|
||||||
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 for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection
|
||||||
|
|
||||||
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)
|
### 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:
|
Example Authorization event:
|
||||||
|
|
||||||
@@ -115,16 +106,16 @@ Example Authorization event:
|
|||||||
|
|
||||||
Servers MUST accept `DELETE` requests to the `/<sha256>` endpoint
|
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)
|
### Delete Authorization (required)
|
||||||
|
|
||||||
Servers MUST accept an authorization event when deleting blobs
|
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`
|
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
|
2. 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.
|
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:
|
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 hash from the URL
|
1. Get the SHA256 has from the URL
|
||||||
2. Look for the authors server list `kind:10063`
|
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
|
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
|
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
|
## 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
|
Clients MUST pass the URL of the remote blob as a stringified JSON object in the request body
|
||||||
|
|
||||||
@@ -19,28 +19,23 @@ 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-optional). 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-required). 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
|
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 to mirror multiple blobs.**
|
**Multiple `x` tags in the authorization event MUST NOT be interpreted as the user requesting a bulk mirror.**
|
||||||
|
|
||||||
The endpoint MUST return a [Blob Descriptor](#blob-descriptor) and a `2xx` status code if the mirroring was successful
|
The endpoint MUST return a [Blob Descriptor](#blob-descriptor) if the mirroring was successful or an error object if it was not
|
||||||
or a `4xx` status code and error message if it was not.
|
|
||||||
|
|
||||||
The destination server SHOULD use the `Content-Type` header returned from the origin server to infer the mime type of
|
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 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 `Content-Length` header to determine the size of the blob.
|
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 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
|
## Example Flow
|
||||||
|
|
||||||
1. Client signs an `upload` authorization event and uploads blob to Server A
|
1. Client signs authorization event and uploads blob to Server A
|
||||||
1. Server A returns a [Blob Descriptor](./02.md#blob-descriptor) with the `url`
|
1. Server A returns blob descriptor with `url`
|
||||||
1. Client sends the `url` to Server B `/mirror` using the original `upload` authorization event
|
1. Client sends the `url` to Server B `/mirror` using the original authorization event
|
||||||
1. Server B downloads the blob from Server A using the `url`
|
1. Server B downloads 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 verifies downloaded blob hash matches `x` tag in authorization event
|
||||||
1. Server B returns a [Blob Descriptor](./02.md#blob-descriptor)
|
1. Server B returns [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
|
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 perform the following checks
|
If a server requires a `media` authorization event it MUST preform the following checks
|
||||||
|
|
||||||
1. The `t` tag MUST be set to `media`
|
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
|
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
|
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 responsibility of the server and the client should have no say in what optimization process is used
|
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
|
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
|
## 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
|
### Headers
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ Example response from the server if the upload can be done:
|
|||||||
HTTP/1.1 200 OK
|
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:
|
Some examples of error messages:
|
||||||
|
|
||||||
|
|||||||
105
buds/07.md
105
buds/07.md
@@ -1,105 +0,0 @@
|
|||||||
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,6 +6,7 @@
|
|||||||
|
|
||||||
This bud defines a new endpoint for clients and users to report blobs to servers.
|
This bud defines a new endpoint for clients and users to report blobs to servers.
|
||||||
|
|
||||||
|
|
||||||
### PUT /report - reporting a blob
|
### 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.
|
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.
|
||||||
@@ -37,4 +38,4 @@ The clients can show a blob report button on posts or in blob details. Or its RE
|
|||||||
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 MAY consider removed blobs sha256 as blocked to prevent rewrite.
|
||||||
Servers SHOULD advertise a route or landing page to provide their rules and terms of service which affects the report process.
|
Servers SHOULD advertise a route or landing page to provide their rules and term of service which affects the report process.
|
||||||
|
|||||||
285
buds/10.md
285
buds/10.md
@@ -1,207 +1,96 @@
|
|||||||
# BUD-10
|
# BUD-10
|
||||||
|
|
||||||
## Blossom URI Schema
|
## Multi-part uploads
|
||||||
|
|
||||||
`draft` `optional`
|
`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.
|
This bud defines a new `PATCH` method for the `/upload` endpoint to allow clients to upload blobs in multiple parts.
|
||||||
|
|
||||||
## URI Format
|
### Signaling support for multi-part uploads
|
||||||
|
|
||||||
The `blossom:` URI schema MUST follow this format:
|
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
|
||||||
|
}
|
||||||
```
|
```
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user