From 8571ebf03016b8b1537864aaee704e29bdf9cbdd Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 27 Feb 2024 09:51:21 +0000 Subject: [PATCH] finish upload endpoint more details on error response --- Client.md | 10 +++++ Nostr.md | 6 ++- Server.md | 120 +++++++++++++++++++++++++++++++----------------------- 3 files changed, 84 insertions(+), 52 deletions(-) diff --git a/Client.md b/Client.md index 73834cf..6d4e560 100644 --- a/Client.md +++ b/Client.md @@ -1,3 +1,13 @@ # Blossom Client Implementation +## Upload Blob + +Clients should perform the following steps when uploading blobs + +1. Prompt the user to sign an [Authorization event](./Server.md#upload-authorization-required) for the blob +2. Get the users [Server Discovery](./Nostr.md#user-server-discovery) +3. Make a `PUT /upload` request with the authorization event to each server on the list + +## Implementations + Example implementation (Typescript) [blossom-client](https://github.com/hzrd149/blossom-client) diff --git a/Nostr.md b/Nostr.md index 2c2e0fb..43de7ae 100644 --- a/Nostr.md +++ b/Nostr.md @@ -1,10 +1,12 @@ # Blossom nostr integration -Blossom uses nostr for public / private key identities. Users are expected to sign "Client Authentication" events to prove their identity when uploading or deleting blobs +Blossom uses nostr for public / private key identities. Users are expected to sign authentication events to prove their identity when uploading or deleting blobs + +See [Authorization events](./Server.md#authorization-events) ## User Server Discovery -Users may publish a kind `10063` event with a list of `r` tags indicating where others should look to find their published blobs +Users should publish a kind `10063` event with a list of `r` tags indicating servers that others users should use when getting their blobs ### Example diff --git a/Server.md b/Server.md index c8a4518..0360160 100644 --- a/Server.md +++ b/Server.md @@ -1,10 +1,10 @@ # Blossom Server Implementation -_All pubkeys must be in hex format_ +_All pubkeys MUST be in hex format_ ## CORS -Servers must set `Access-Control-Allow-Origin: *` and `Access-Control-Allow-Methods: GET, PUT, DELETE` headers on all endpoint to ensure compatibility with apps hosted on other domains +Servers MUST set `Access-Control-Allow-Origin: *`, `Access-Control-Allow-Headers: Authorization,*` and `Access-Control-Allow-Methods: GET, PUT, DELETE` headers on all endpoint to ensure compatibility with apps hosted on other domains ## Authorization events @@ -12,10 +12,10 @@ Authorization events are used to identify the users pubkey with the server Authorization events must 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 have the `content` set to a human readable string explaining to the user what the events inteded use is. for example `Upload Blob`, `Delete family-picture.png`, `List Images`, etc - 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. Example event: @@ -25,7 +25,7 @@ Example event: "id": "65c72db0c3b82ffcb395589d01f3e2849c28753e9e7156ceb88e5dd937ca845f", "pubkey": "6ea2ab6f206844b1fe48bd8a7eb22ed6e4114a5b2a5252700a729a88142b2bc3", "kind": 24242, - "content": "Upload bitcoin.pdf", + "content": "Upload bitcoin.pdf", "created_at": 1708773959, "tags": [ ["t", "upload"], @@ -54,33 +54,48 @@ Authorization: Nostr eyJpZCI6IjhlY2JkY2RkNTMyOTIwMDEwNTUyNGExNDI4NzkxMzg4MWIzOWQ ## Endpoints -Servers must make all endpoints avaliable at the root path. This allows users to easily talk to server interchangeably +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 fetching blobs -Servers must repond with a stringified JSON object with a `message` field for all errors +Servers MUST repond with `Content-Type: application/json` and a JSON object containing `message` for all error responses + +The `message` field MUST be human readable and should explain the reason for the error. Optinally 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: * + +{"message":"Missing Auth event"} +``` ### GET /sha256 - Get Blob -The `GET /` endpoint must return the contents of the blob with the `Content-Type` header set to the appropriate MIME type +The `GET /` 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 #### Get Authorization (optional) The server may optionally require authorization when fetching blobs from the `GET /` endpoint -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 `get` If the client did not send an `Authorization` header the server must respond with the appropriate HTTP status code `401` (Unauthorized) Example Authorization event: + ```json { "id": "3a2c0a58f88f86ab81ce7d111df57096e8cd9f41a75731a021e06e07c6df9d0e", "pubkey": "96ddb0e7c4a5786a842094fee014d4c6cbb1f1627a8d75ef6fb601baeb6c5054", "kind": 24242, - "content": "Get Blobs", + "content": "Get Blobs", "created_at": 1708771927, "tags": [ ["t", "get"], @@ -90,58 +105,29 @@ Example Authorization event: } ``` -### GET /list/pubkey - List Blobs - -The `/list/` endpoint must return a JSON array of "blob descriptors" that where uploaded by the specified pubkey - -The endpoint must also support a `since` and `until` query parameter to filter the returned "blob descriptors" by the `created` field - -#### List Authorization (optional) - -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 - -1. The `t` tag must be set to `list` - -Example Authorization event: -```json -{ - "id": "cbb1cab9566355bfdf04e1f1fc1e655fe903ecc193e8a750092ee53beec2a0e8", - "pubkey": "a5fc3654296e6de3cda6ba3e8eba7224fac8b150fd035d66b4c3c1dc2888b8fc", - "kind": 24242, - "content": "List Blobs", - "created_at": 1708772350, - "tags": [ - ["t", "list"], - ["expiration", "1708858680"] - ], - "sig": "ff9c716f8de0f633738036472be553ce4b58dc71d423a0ef403f95f64ef28582ef82129b41d4d0ef64d2338eb4aeeb66dbc03f8b3a3ed405054ea8ecb14fa36c" -} -``` - ### PUT /upload - Upload Blob -The `PUT /upload` endpoint ... +The `PUT /upload` endpoint should expect the `Content-Type` header of the request to be set to the MIME type of the blob. and the body of the request to the raw data of the blob -Servers may reject an upload 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 return a [Blob Descriptor](./README.md#blob-descriptor) if the upload was successful. or an error object if not + +Servers may reject an upload for any reason and should respond with the approperate HTTP `4xx` status code and an erorr message explaining the reason for the rejection #### Upload Authorization (required) -Servers must accept an authorization event when uploading blobs - -Servers must perform additional checks on the authorization event +Servers must accept an authorization event when uploading blobs and should perform additional checks 1. The `t` tag must be set to `upload` 2. A `size` tag must be present and set to the total size of the uploaded blob Example Authorization event: + ```json { "id": "65c72db0c3b82ffcb395589d01f3e2849c28753e9e7156ceb88e5dd937ca845f", "pubkey": "6ea2ab6f206844b1fe48bd8a7eb22ed6e4114a5b2a5252700a729a88142b2bc3", "kind": 24242, - "content": "Upload bitcoin.pdf", + "content": "Upload bitcoin.pdf", "created_at": 1708773959, "tags": [ ["t", "upload"], @@ -152,22 +138,56 @@ Example Authorization event: } ``` +### GET /list/pubkey - List Blobs + +The `/list/` endpoint must return a JSON array of [Blob Descriptor](./README.md#blob-descriptor) that where uploaded by the specified pubkey + +The endpoint must support a `since` and `until` query parameter to limit the returned blob descriptors by the `created` field + +Servers may reject an upload 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 + +In this case the server must perform additional checks on the authorization event + +1. The `t` tag must be set to `list` + +Example Authorization event: + +```json +{ + "id": "cbb1cab9566355bfdf04e1f1fc1e655fe903ecc193e8a750092ee53beec2a0e8", + "pubkey": "a5fc3654296e6de3cda6ba3e8eba7224fac8b150fd035d66b4c3c1dc2888b8fc", + "kind": 24242, + "content": "List Blobs", + "created_at": 1708772350, + "tags": [ + ["t", "list"], + ["expiration", "1708858680"] + ], + "sig": "ff9c716f8de0f633738036472be553ce4b58dc71d423a0ef403f95f64ef28582ef82129b41d4d0ef64d2338eb4aeeb66dbc03f8b3a3ed405054ea8ecb14fa36c" +} +``` + ### DELETE /sha256 - Delete Blob -Servers must accept `DELETE` requests to the `/` endpoint +Servers MUST accept `DELETE` requests to the `/` endpoint -Servers may reject a delete request for any reason and must respond with the aproperate 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 aproperate 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 must 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. A `x` tag must be present and set to the sha256 hash of the blob being deleted Example Authorization event: + ```json { "id": "a92868bd8ea740706d931f5d205308eaa0e6698e5f8026a990e78ee34ce47fe8",