@ -1,114 +1,128 @@
# noxy is a nostr proxy
# noxy is a nostr proxy
noxy receives a [nostr ](https://nostr.info/ ) event id, fetches images and
noxy proxies URL preview metadata, images and other media files.
link previews, and returns the result in a JSON object. the idea is to run
the idea is to run such proxies to reduce IP address leaks and client
such proxies to reduce IP address leaks and client fingerprinting.
fingerprinting.
## API v1
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:
over HTTP, noxy exposes a single endpoint accepting a nostr event id and
- 0: `set_metadata` ; `picture` URL
a relay to fetch the event from:
- 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`
GET /api/v1/e/< event-id > ?relay=< relay-uri >
## API
the response is an array of objects:
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
```json
[
{
{
"url": "< original url > ",
"type": "< OGP type > ",
"cache": "< noxy url > ",
"title": "< OGP title > ",
"kind": "media|preview",
"descr": "< OGP description > ",
"size": 123,
"images": ["< URL > ", ...]
"title": "resource title",
"descr": "resource description"
}
}
]
```
```
where `url` is the original url found in a nostr event payload and `cache` is the
where image URLs are taken from `og:image:secure_url` or `og:image` ; the former
proxied url or a link preview image. the other fields presence and their values
is preferred. other fields are copied verbatim from `og:type` , `og:title`
depend on the `kind` of the resource.
and `og:description` , respectively. future versions may also employ
[oEmbed ](https://oembed.com/ ) and other metadata formats parsing.
for images, videos and audio the `kind` field is `media` and the `size` is th e
the web page at `url` must be served with `text/html` content type. if the pag e
file size in bytes as stored in cache. if the file size is unknown at the time
contains no or empty OGP metadata, noxy response with 200 OK and blank fields.
of a response, it is 0 .
otherwise, the response is a 4xx status code .
for link previews, the `kind` field is `preview` , `cache` url points to a link
### /data
preview image and the `size` is the preview image size. link preview image,
`title` and `descr` field values are collected using
[the open graph protocol ](https://ogp.me/ ) or [oEmbed ](https://oembed.com/ ).
some examples follow.
data endpoint request is of the following form. all parameter values are
expected to be url-encoded.
### fetch a pubkey profile picture, event kind 0
GET /data?id=< nostr-event-id > & relay=< relay-uri > & url=< file-url >
the parameters are:
request example:
- `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.
GET /api/v1/e/e01ac1cfc5cb68b54183f878261b21ef30a65f5e06a24356cfe3ecdacce14bae?relay=wss%3A%2F%2Frelay.nostr.info
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.
response:
### example: fetch a pubkey profile picture, event kind 0
```json
$ eventid=e01ac1cfc5cb68b54183f878261b21ef30a65f5e06a24356cfe3ecdacce14bae
[
$ relay=wss://relay.nostr.info
{
$ url=https://git.qcode.ch/avatars/5a8071777eba7ebf178143fa650c8012?size=870
"url": "https://git.qcode.ch/avatars/5a8071777eba7ebf178143fa650c8012?size=870",
$ curl -o /tmp/img "https://noxy.nostr.ch/data?id=$eventid& relay=$relay& url=$url"
"cache": "https://noxy.example.org/abcdef/abcdef0123456789.png",
$ file /tmp/img
"kind": "media",
/tmp/img: PNG image data, 290 x 290, 16-bit/color RGB, non-interlaced
"size": 279342
}
]
```
[event raw data → ](https://nostr.com/e/e01ac1cfc5cb68b54183f878261b21ef30a65f5e06a24356cfe3ecdacce14bae )
[event raw data → ](https://nostr.com/e/e01ac1cfc5cb68b54183f878261b21ef30a65f5e06a24356cfe3ecdacce14bae )
if a noxy instance is unable to fetch the original, it responds with an empty array:
### example: fetch images from a text note, event kind 1
```json
$ 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
### fetch images from a text note, event kind 1
[event raw data → ](https://nostr.com/e/d822fdd220d8a74d2f025f331840eec8a640a663f1d3ca3de9f6a74ff0cc61fa )
request example:
### example: fetch link preview from a text note, event kind 1
GET /api/v1/e/d822fdd220d8a74d2f025f331840eec8a640a663f1d3ca3de9f6a74ff0cc61fa?relay=wss%3A%2F%2Frelay.damus.io
$ 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:
response:
```json
```json
[
{
{
"url": "https://res.cloudinary.com/eskema/image/upload/v1668636521/osso_vt7qh7.png ",
"type": "object ",
"cache": "https://noxy.example.org/fedcba/fedcba9876543210.png ",
"title": "publish,message: accept content from stdin by x1ddos · Pull Request #24 · fiatjaf/noscl ",
"kin d": "media",
"descr ": "if the arg to publish or message comman d is '-', it is re ad from stdin.\ncloses #19 ",
"size": 93241
"images": [
}
"https://opengraph.githubassets.com/dc27bad9f4d71ea7803c4bd07a9991c0bcb798bbdc451aebc42d222e5d7692c8/fiatjaf/noscl/pull/24"
]
]
}
```
```
[event raw data → ](https://nostr.com/e/d822fdd220d8a74d2f025f331840eec8a640a663f1d3ca3de9f6a74ff0cc61fa )
now, fetch the preview image. note the change from `/meta` to `/data` endpoint:
### fetch link preview from a text note, event kind 1
$ 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
request example:
[event raw data → ](https://nostr.com/e/af30dac1d800acc25b87d0d6d0dd33bddf49e7f356556540a6c7722e3cb363fe )
GET /api/v1/e/af30dac1d800acc25b87d0d6d0dd33bddf49e7f356556540a6c7722e3cb363fe?relay=wss%3A%2F%2Fnostr.x1ddos.ch%2F
response:
```json
[
{
"url": "https://github.com/fiatjaf/noscl/pull/24",
"cache": "https://noxy.example.org/beef01/beef0123456789.png",
"kind": "preview",
"size": 110480,
"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 "
}
]
```
[event raw data → ](https://nostr.com/e/af30dac1d800acc25b87d0d6d0dd33bddf49e7f356556540a6c7722e3cb363fe )