You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
noxy/README.md

158 lines
5.5 KiB
Markdown

# noxy is a nostr proxy
noxy proxies URL preview metadata, images and other media files.
the idea is to run such proxies to reduce IP address leaks and client
fingerprinting.
to limit noxy abuse, it works only with URLs linked to
from [nostr](https://nostr.info/) events. the following nostr event kinds
are currently supported:
- 0: `set_metadata`; `picture` URL
- 1: `text_note`; any URL in the `content`
- 40: create channel; `picture` URL
- 41: set channel metadata; `picture` URL
- 42: channel message; any URL in the `content`
## API
over HTTP, noxy exposes two endpoints: one for meta info of URL preview,
and the other one for file (data) transfer.
### /meta
the request has the following form. all parameter values are expected to be
url-encoded.
GET /meta?id=<nostr-event-id>&relay=<relay-uri>&url=<original-url>
the parameters are:
- `id`: nostr event id as described in [NIP-01](https://github.com/nostr-protocol/nips/blob/master/01.md)
- `relay`: a URL of a nostr relay where the event was posted to
- `url`: any URL found in the event text note or the `picture` for structured messages
noxy fetches HTML at `url`, looks for [OGP](https://ogp.me/) metadata
and responds with a JSON object containing the following keys:
```json
{
"type": "<OGP type>",
"title": "<OGP title>",
"descr": "<OGP description>",
"images": ["<URL>", ...]
}
```
where image URLs are taken from `og:image:secure_url` or `og:image`; the former
is preferred. other fields are copied verbatim from `og:type`, `og:title`
and `og:description`, respectively. future versions may also employ
[oEmbed](https://oembed.com/) and other metadata formats parsing.
the web page at `url` must be served with `text/html` content type. if the page
contains no or empty OGP metadata, noxy response with 200 OK and blank fields.
otherwise, the response is a 4xx status code.
### /data
data endpoint request is of the following form. all parameter values are
expected to be url-encoded.
GET /data?id=<nostr-event-id>&relay=<relay-uri>&url=<file-url>
the parameters are:
- `id`: a nostr event id
- `relay`: a URL of a nostr relay where the event was posted to
- `url`: any URL found either in the event text note, `picture` field for
structured messages, or an `images` array element of a `/meta` endpoint response
produced from the same event id.
the data endpoint simply streams contents at the `url` to the client
with the same `content-type` as the original. `content-length` may or may
not be present. in the latter case, the response is chunked.
### example: fetch a pubkey profile picture, event kind 0
$ eventid=e01ac1cfc5cb68b54183f878261b21ef30a65f5e06a24356cfe3ecdacce14bae
$ relay=wss://relay.nostr.info
$ url=https://git.qcode.ch/avatars/5a8071777eba7ebf178143fa650c8012?size=870
$ curl -o /tmp/img "https://noxy.nostr.ch/data?id=$eventid&relay=$relay&url=$url"
$ file /tmp/img
/tmp/img: PNG image data, 290 x 290, 16-bit/color RGB, non-interlaced
[event raw data &rightarrow;](https://nostr.com/e/e01ac1cfc5cb68b54183f878261b21ef30a65f5e06a24356cfe3ecdacce14bae)
### example: fetch images from a text note, event kind 1
$ eventid=d822fdd220d8a74d2f025f331840eec8a640a663f1d3ca3de9f6a74ff0cc61fa
$ relay=wss://relay.damus.io
$ url=https://res.cloudinary.com/eskema/image/upload/v1668636521/osso_vt7qh7.png
$ curl -o /tmp/img "https://noxy.nostr.ch/data?id=$eventid&relay=$relay&url=$url"
$ file /tmp/img
/tmp/img: PNG image data, 800 x 800, 8-bit/color RGB, non-interlaced
[event raw data &rightarrow;](https://nostr.com/e/d822fdd220d8a74d2f025f331840eec8a640a663f1d3ca3de9f6a74ff0cc61fa)
### example: fetch link preview from a text note, event kind 1
$ EVENTID=af30dac1d800acc25b87d0d6d0dd33bddf49e7f356556540a6c7722e3cb363fe
$ RELAY=wss://nostr.x1ddos.ch/
$ URL=https://github.com/fiatjaf/noscl/pull/24
$ curl "https://noxy.nostr.ch/meta?id=$EVENTID&relay=$RELAY&url=$URL"
response:
```json
{
"type": "object",
"title": "publish,message: accept content from stdin by x1ddos · Pull Request #24 · fiatjaf/noscl",
"descr": "if the arg to publish or message command is '-', it is read from stdin.\ncloses #19",
"images": [
"https://opengraph.githubassets.com/dc27bad9f4d71ea7803c4bd07a9991c0bcb798bbdc451aebc42d222e5d7692c8/fiatjaf/noscl/pull/24"
]
}
```
now, fetch the preview image. note the change from `/meta` to `/data` endpoint:
$ URL=https://opengraph.githubassets.com/dc27bad9f4d71ea7803c4bd07a9991c0bcb798bbdc451aebc42d222e5d7692c8/fiatjaf/noscl/pull/24
$ curl -o /tmp/img "https://noxy.nostr.ch/data?id=$EVENTID&relay=$RELAY&url=$URL"
$ file /tmp/img
/tmp/img: PNG image data, 1200 x 600, 8-bit/color RGBA, non-interlaced
[event raw data &rightarrow;](https://nostr.com/e/af30dac1d800acc25b87d0d6d0dd33bddf49e7f356556540a6c7722e3cb363fe)
## development
the binary's entry point is [cmd/noxy/main.go](cmd/noxy/main.go).
it imports packages in the root of the repo. the actual proxy is implemented
by `Noxer` in [noxy.go](noxy.go).
running the server locally:
mkdir cache
go run ./cmd/noxy -cachedir $PWD/cache
before sending a patch, make sure the code is passing tests:
go test -race
files are formatted:
go fmt ./...
and the go module file is updated:
go mod tidy
## release
a release binary is built using the following script.
it produces `noxy` executable in the root of the repo.
./tools/release.sh
before making a new release, you'll probably want to create a new git tag.
the tag is used as the noxy version, also printed when `-V` flag is specified.