mirror of https://github.com/hzrd149/blossom.git
153 lines
6.3 KiB
Markdown
153 lines
6.3 KiB
Markdown
# BUD-01
|
|
|
|
## Server requirements and blob retrieval
|
|
|
|
`draft` `mandatory`
|
|
|
|
_All pubkeys MUST be in hex format_
|
|
|
|
## Cross origin headers
|
|
|
|
Servers MUST set the `Access-Control-Allow-Origin: *` header on all responses to ensure compatibility with applications hosted on other domains.
|
|
|
|
For [preflight](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests) (`OPTIONS`) requests,
|
|
servers MUST also set, at minimum, the `Access-Control-Allow-Headers: Authorization, *` and `Access-Control-Allow-Methods: GET, PUT,
|
|
DELETE` headers.
|
|
|
|
The header `Access-Control-Max-Age: 86400` MAY be set to cache the results of a preflight request for 24 hours.
|
|
|
|
## Authorization events
|
|
|
|
Authorization events are used to identify the users to the server
|
|
|
|
Authorization events must be generic and must NOT be scoped to specific servers. This allows pubkeys to sign a single event and interact the same way with multiple 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
|
|
|
|
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.
|
|
|
|
Authorization events MAY have multiple `x` tags for endpoints that require a sha256 hash.
|
|
|
|
Example event:
|
|
|
|
```json
|
|
{
|
|
"id": "bb653c815da18c089f3124b41c4b5ec072a40b87ca0f50bbbc6ecde9aca442eb",
|
|
"pubkey": "b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e",
|
|
"kind": 24242,
|
|
"content": "Upload bitcoin.pdf",
|
|
"created_at": 1708773959,
|
|
"tags": [
|
|
["t", "upload"],
|
|
// Authorization events MAY have multiple "x" tags
|
|
["x", "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553"],
|
|
["expiration", "1708858680"]
|
|
],
|
|
"sig": "d0d58c92afb3f4f1925120b99c39cffe77d93e82f488c5f8f482e8f97df75c5357175b5098c338661c37d1074b0a18ab5e75a9df08967bfb200930ec6a76562f"
|
|
}
|
|
```
|
|
|
|
Servers must perform the following checks in order to validate the event
|
|
|
|
1. The `kind` must be `24242`
|
|
2. `created_at` must be in the past
|
|
3. The `expiration` tag must be set to a Unix timestamp in the future
|
|
4. The `t` tag must have a verb matching the intended action of the endpoint
|
|
5. Additional checks for specific endpoints. `/upload`, `/delete`, etc
|
|
|
|
Using the `Authorization` HTTP header, the kind `24242` event MUST be base64 encoded and use the Authorization scheme Nostr
|
|
|
|
Example HTTP Authorization header:
|
|
|
|
```
|
|
Authorization: Nostr eyJpZCI6IjhlY2JkY2RkNTMyOTIwMDEwNTUyNGExNDI4NzkxMzg4MWIzOWQxNDA5ZDhiOTBjY2RiNGI0M2Y4ZjBmYzlkMGMiLCJwdWJrZXkiOiI5ZjBjYzE3MDIzYjJjZjUwOWUwZjFkMzA1NzkzZDIwZTdjNzIyNzY5MjhmZDliZjg1NTM2ODg3YWM1NzBhMjgwIiwiY3JlYXRlZF9hdCI6MTcwODc3MTIyNywia2luZCI6MjQyNDIsInRhZ3MiOltbInQiLCJnZXQiXSxbImV4cGlyYXRpb24iLCIxNzA4ODU3NTQwIl1dLCJjb250ZW50IjoiR2V0IEJsb2JzIiwic2lnIjoiMDJmMGQyYWIyM2IwNDQ0NjI4NGIwNzFhOTVjOThjNjE2YjVlOGM3NWFmMDY2N2Y5NmNlMmIzMWM1M2UwN2I0MjFmOGVmYWRhYzZkOTBiYTc1NTFlMzA4NWJhN2M0ZjU2NzRmZWJkMTVlYjQ4NTFjZTM5MGI4MzI4MjJiNDcwZDIifQ==
|
|
```
|
|
|
|
## Endpoints
|
|
|
|
All endpoints MUST be served from the root path (eg. `https://cdn.example.com/upload`, etc). This allows clients to talk to servers interchangeably when uploading or retrieving blobs
|
|
|
|
## Error Responses
|
|
|
|
For HTTP `4xx` and `5xx` status codes servers MUST repond with `Content-Type: application/json` and a JSON object containing `message`
|
|
|
|
The `message` field MUST be human readable and should explain the reason for the error. Optionally servers may include other fields for the client with more information about the error
|
|
|
|
Example Error response:
|
|
|
|
```
|
|
HTTP/2 401
|
|
content-type: application/json; charset=utf-8
|
|
content-length: 32
|
|
access-control-allow-origin: *
|
|
access-control-expose-headers: *
|
|
access-control-allow-headers: authorization,*
|
|
access-control-allow-methods: get, put, delete
|
|
|
|
{"message":"Missing Auth event"}
|
|
```
|
|
|
|
## 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 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 requested blob.
|
|
This ensures that if a user was to copy or reuse the redirect URL it would still contain the original sha256 hash
|
|
|
|
### Get Authorization (optional)
|
|
|
|
The server may optionally require authorization when retrieving blobs from the `GET /<sha256>` endpoint
|
|
|
|
In this case the server MUST perform additional checks on the authorization event
|
|
|
|
1. A `t` tag MUST be present and set to `get`
|
|
2. The event MUST contain either a `server` tag containing the full URL to the server or MUST contain at least one `x` tag matching the sha256 hash of the blob being retrieved
|
|
|
|
If the client did not send an `Authorization` header the server must respond with the appropriate HTTP status code `401` (Unauthorized)
|
|
|
|
Example event for retrieving a single blob:
|
|
|
|
```json
|
|
{
|
|
"id": "06d4842b9d7f8bf72440471704de4efa9ef8f0348e366d097405573994f66294",
|
|
"pubkey": "ec0d11351457798907a3900fe465bfdc3b081be6efeb3d68c4d67774c0bc1f9a",
|
|
"kind": 24242,
|
|
"content": "Get bitcoin.pdf",
|
|
"created_at": 1708771927,
|
|
"tags": [
|
|
["t", "get"],
|
|
["expiration", "1708857340"],
|
|
["x", "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553"]
|
|
],
|
|
"sig": "22ecb5116ba143e4c3d6dc4b53d549aed6970ec455f6d25d145e0ad1fd7c0e26c465b2e92d5fdf699c7050fa43e6a41f087ef167208d4f06425f61548168fd7f"
|
|
}
|
|
```
|
|
|
|
Example event for retrieving multiple blobs from single server:
|
|
|
|
```json
|
|
{
|
|
"id": "d9484f18533d5e36f000f902a45b15a7eecf5fbfcb046789756d57ea87115dc5",
|
|
"pubkey": "b5f07faa8d3529f03bd898a23dfb3257bab8d8f5490777c46076ff9647e205dc",
|
|
"kind": 24242,
|
|
"content": "Get blobs from example.com",
|
|
"created_at": 1708771927,
|
|
"tags": [
|
|
["t", "get"],
|
|
["expiration", "1708857340"],
|
|
["server", "https://cdn.example.com/"]
|
|
],
|
|
"sig": "e402ade78e1714d40cd6bd3091bc5f4ada8e904e90301b5a2b9b5f0b6e95ce908d4f22b15e9fb86f8268a2131f8adbb3d1f0e7e7afd1ab0f4f08acb15822a999"
|
|
}
|
|
```
|
|
|
|
## HEAD /sha256 - Has Blob
|
|
|
|
The `HEAD /<sha256>` endpoint MUST respond with either a `200` or `404` status code
|
|
|
|
The endpoint MUST accept an optional file extension in the URL similar to the `GET /<sha256>` endpoint. ie. `.pdf`, `.png`, etc
|