# HTTP Messages A specification for sending/receiving HTTP messages (request/response) via a remote server. Header / Body etc are encrypted, either in the `content` (small messages) or via a blossom server (larger requests).  ## Overview Enables a local client to make and receive http requests (PUT, POST, GET, PATCH etc) from a remote computer. Requires: * A trusted machine to process the messages (can be a home PC or Raspberry Pi) * A relay (can be untrusted) * A blossom server (can be untrusted) ## Architecture ```mermaid architecture-beta group user(internet)[Nostr Client] group cloud(cloud)[Untrusted Servers] group home(server)[Trusted Device] service client(internet) in user service blossom(database)[Blossom Storage] in cloud service relay(logos:aws-ec2)[Relays] in cloud service pc(logos:aws-elb) in home service bbi[Big Bad Internet] client:R -- L:blossom client:B -- L:relay pc:L -- R:blossom pc:L -- R:relay pc:B <--> T:bbi ``` ## Sequence Diagram ```mermaid sequenceDiagram autoNumber participant c as Nostr Client participant r as Nostr Relay participant b as Blossom Server participant s as HTTP Server Note over c: Convert <br>HTTP Request<br>into kind 21120 c-->>b: Encrypt & push payload (if large) c->>r: Publish <br>Event r<<-->>s: Fetch event Note over s: Decrypt event s<<-->>b: Fetch payload <br>(if large) Note over s: Make HTTP REQUEST Note over s: Get HTTP RESPONSE s-->>b: Encrypt & push <br>payload (if large) Note over s: Create kind<br>21120 (Response) s->>r: Publish Event r<<-->>c: Fetch event Note over c: Decrypt event b<<-->>c: Fetch payload (if large) Note over c: Convert<br> kind 21120 into<br> HTTP Response c-->>b: Delete REQUEST blob (if exists) c->>r: Delete REQUEST event ``` The remote server should periodically scan for expired RESPONSE events (and associated blossom blobs) and delete them. ## Event Structure Example **request** with a small payload. Payload is in `content` and `P` tag is the npub of the remote HTTP server. ```jsonc { "kind": 21120, "pubkey": "<pubkey>", "content": "$encryptedPayload", "tags": [ ["p", "<pubkey of remote server>"], // P tag entry, this is a REQUEST ["key","nip44Encrypt($decryptkey)"], ["r", "https://relay.one"], ["expiration",<unix timestamp>] ], // other fields... } ``` Example **response** with a large payload. Valid JSON is in `content` and `E` tag is populated. For privacy, the requestor npub is NOT shown - the requestor instead should be fetching the response using the `E` tag. ```jsonc { "kind": 21120, "pubkey": "<pubkey>", "content": "encrypt({'url':'blossom.one','hash':'xx'},$decryptkey)", "tags": [ ["key","nip44Encrypt($decryptkey)"], ["E", "<request event id>"], // E tag entry, this is a RESPONSE ["expiration",<unix timestamp>] ], // other fields... } ``` Explanations: * `kind:21120` - BIP39 word #1120 ([message](https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt#L1120)), plus 20,000 to be treated as ephemeral (not stored by relays). * `"content"` - encrypted JSON with location of blob **OR** the content itself (if under a threshold). NIP-44 is NOT used as the payload may be large, affecting bunker signing stability. * `"p"` - the pubkey of the remote HTTP server. Indicates that this is a REQUEST. * `"key"` - the decryption key for the `content` field, also the key for the blossom blob (if used). * `"E"` - ID of the request event. Enables a response to be identified, and fetched. * `"expiration"` - remote servers should not process requests after this time. Relays SHOULD delete events after this time. * `"r"` - (optional) relay on which the response should be sent. For Requests only. ## Considerations This approach only makes sense in cases where privacy and anonymity are important, or if censorship is a concern. There are a number of drawbacks to the approach: - Complexity. Many more moving parts than a direct request. - Speed. Each request/response now requires: - Encrypting the payload - Loading to blossom (if large) - Signing event - broadcasting event - remote server fetching event - remote server decrypting event - remote server fetching blossom blob (if large) - remote server decrypting blossom blob (if used) - making the actual request And the same flow in reverse. So why would you use it? Several reasons: - enables a plethora of open source apps to be made available from inside private networks (localhost) but over nostr - maximum server privacy (no domain needed, or port forwarding) - Make regular API calls over Nostr