# 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=&relay=&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": "", "title": "", "descr": "", "images": ["", ...] } ``` 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=&relay=&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 →](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 →](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 →](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.