6.9 KiB
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 (OPTIONS
) requests,
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.
Error responses
Every time a server sends an error response (HTTP status codes >=400), it may include a human-readable header X-Reason
that can be displayed to the user.
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 intended use is. For example Upload Blob
, Delete dog-picture.png
, List Images
, etc
All events MUST have a NIP-40 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:
{
"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
- The
kind
must be24242
created_at
must be in the past- The
expiration
tag must be set to a Unix timestamp in the future - The
t
tag must have a verb matching the intended action of the endpoint - 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 of the domain (eg. the /upload
endpoint MUST be accessible from https://cdn.example.com/upload
, etc). This allows clients to talk to servers interchangeably when uploading or retrieving blobs
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 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
server does not know the MIME type of the blob, it MUST default to application/octet-stream
If the endpoint 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
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
- A
t
tag MUST be present and set toget
- The event MUST contain either a
server
tag containing the full URL to the server or MUST contain at least onex
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:
{
"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:
{
"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 SHOULD be identical to the GET /<sha256>
endpoint except that it MUST NOT return the
blob in the reponse body per RFC 7231
The endpoint MUST respond with the same Content-Type
and Content-Length
headerers 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
Range requests
To better support mobile devices, video files, or low bandwidth connections. servers should support range requests (RFC 7233 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 for more details