# 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).

![](./http.png)

## 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