a nostr images proxy
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.
 
 
alex 1ddf35e212
cmd/noxy: respond with appropriate status 5xx on context errors
2 years ago
cmd/noxy cmd/noxy: respond with appropriate status 5xx on context errors 2 years ago
tools basic implementation of the last api version 2 years ago
LICENSE initial: api v1 draft 2 years ago
README.md basic implementation of the last api version 2 years ago
cache.go basic implementation of the last api version 2 years ago
go.mod basic implementation of the last api version 2 years ago
go.sum basic implementation of the last api version 2 years ago
io.go basic implementation of the last api version 2 years ago
io_test.go basic implementation of the last api version 2 years ago
noxy.go verifyEventLink: check cache first to allow more valid URLs 2 years ago
noxy_test.go basic implementation of the last api version 2 years ago

README.md

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 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
  • 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 metadata and responds with a JSON object containing the following keys:

{
  "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 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 responds 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 →

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 →

$ 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:

{
  "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 →

development

the binary's entry point is cmd/noxy/main.go. it imports packages in the root of the repo. the actual proxy is implemented by Noxer in 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.