README.md 5.88 KB
Newer Older
James Calfee's avatar
James Calfee committed
1

Johan Nordberg's avatar
Johan Nordberg committed
2
3
imagehoster
===========
James Calfee's avatar
James Calfee committed
4

Johan Nordberg's avatar
Johan Nordberg committed
5
Steem-powered image hosting and proxying service.
James Calfee's avatar
James Calfee committed
6

7

Johan Nordberg's avatar
Johan Nordberg committed
8
9
Developing
----------
10

Johan Nordberg's avatar
Johan Nordberg committed
11
With node.js installed, run:
12

Johan Nordberg's avatar
Johan Nordberg committed
13
14
15
```
make devserver
```
James Calfee's avatar
James Calfee committed
16

Johan Nordberg's avatar
Johan Nordberg committed
17
18
19
20
21
22
23
24
This will pull in all dependencies and spin up a hot-reloading development server.

Run `make lint` to run the autolinter, `make test` to run the unit tests.


Configuration
-------------

Johan Nordberg's avatar
Johan Nordberg committed
25
Defaults are in <./config/default.toml> and can be overridden by env vars as defined in <./config/custom-environment-variables.toml>
Johan Nordberg's avatar
Johan Nordberg committed
26
27
28
29

Load order is: env vars > `config/$NODE_ENV.toml` > `config/default.toml`

See the `config` module docs for more details.
James Calfee's avatar
James Calfee committed
30
31


Johan Nordberg's avatar
Johan Nordberg committed
32
33
API
---
34

Johan Nordberg's avatar
Johan Nordberg committed
35
36
37
38
39
40
41
42
43
44
45
Responses should be determined by the Content-Type header, errors will have a status of `>=400` and a Content-Type of `application/json` with the body in the format:

```json
{
    "error": {
        "name": "error_name",
        "info": {"optional": "metadata"}
    }
}
```

Johan Nordberg's avatar
Johan Nordberg committed
46
#### `POST /<username>/<signature>` - upload an image.
Johan Nordberg's avatar
Johan Nordberg committed
47
48
49
50
51
52
53
54
55
56
57
58
59
60

Multipart image upload, will only consider first file if there are multiple.

Returns a JSON object containing the url to the uploaded image, example:

```json
{
    "url": "https://images.example.com/DQmZi174Xz96UrRVBMNRHb6A2FfU3z1HRPwPPQCgSMgdiUT/test.jpg"
}
```

Requires a signature from a Steem account in good standing, see the "Signing uploads" section below for more information.


Johan Nordberg's avatar
Johan Nordberg committed
61
#### `GET /<image_hash>/[<filename>]` - fetch an uploaded image.
Johan Nordberg's avatar
Johan Nordberg committed
62
63
64
65

Download a previously uploaded image.

`filename` is optional but can be provided to help users and applications understand the content type (Content-Type header will still always reflect actual image type).
66

67

Johan Nordberg's avatar
Johan Nordberg committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#### `GET /p/<b58_image_url>[?options]` - proxy and resize an image.

Downloads and serves the provided image, note that a copy will be taken of the image and that will be served on subsequent requests so even if the upstream is removed or changes you will still get the original from the proxy endpoint.

##### Params

  * `b58_image_url` - [Base58](https://en.wikipedia.org/wiki/Base58) encoded utf8 string containing the url to the image you wish to proxy.

##### Options

The options are set as query-strings and control how the image is transformed before being proxied.

  * `width` - Desired image width.
  * `height` - Desired image height.
  * `mode` - Resizing mode.
    * `cover` *default* - When set the image will be center cropped if the original aspect ratio does not match the aspect ratio of the upstream image.
    * `fit` - Does not crop the image, it will always keep the upstream aspect ratio and resized to fit within the width and height given.
  * `format` - Output image encoding.
    * `match` *default* - Matches the encoding of the upstream image.
    * `jpeg` - Use JPEG encoding.
    * `png` - Use PNG encoding.
    * `webp` - Use WebP encoding.

If only `width` or `height` are given their counterpart will be calculated based on the upstream image aspect ratio.

##### Examples

Upstream image: `https://ipfs.io/ipfs/QmXa4dAFEhGEuZaX7uUSEvBjbEY5mPxkaS2zHZSnHvocpn` (Base58 encoded `46aP2QbqUqBqwzwxM6L1P6uLNceBDDCM9ZJdv282fpHyc9Wgcz1FduB11aVXtczv9TiCSHF1eEmnRSSdQWQEXA5krJNq`)

Proxy the image as-is:
```
https://steemitimages.com/p/46aP2QbqUqBqwzwxM6L1P6uLNceBDDCM9ZJdv282fpHyc9Wgcz1FduB11aVXtczv9TiCSHF1eEmnRSSdQWQEXA5krJNq
```

Center cropped 512x512px avatar image in WebP format:
```
https://steemitimages.com/p/46aP2QbqUqBqwzwxM6L1P6uLNceBDDCM9ZJdv282fpHyc9Wgcz1FduB11aVXtczv9TiCSHF1eEmnRSSdQWQEXA5krJNq?width=512&height=512&format=webp
```

Aspect resized image fitting inside a 200x500px container:
```
https://steemitimages.com/p/46aP2QbqUqBqwzwxM6L1P6uLNceBDDCM9ZJdv282fpHyc9Wgcz1FduB11aVXtczv9TiCSHF1eEmnRSSdQWQEXA5krJNq?width=200&height=500&mode=fit
```

Aspect resized image with variable width and a height of max 100px:
```
https://steemitimages.com/p/46aP2QbqUqBqwzwxM6L1P6uLNceBDDCM9ZJdv282fpHyc9Wgcz1FduB11aVXtczv9TiCSHF1eEmnRSSdQWQEXA5krJNq?&height=100
```

Johan Nordberg's avatar
Johan Nordberg committed
117
#### `GET /<width>x<height>/<image_url>` - proxy and resize an image.
118

Johan Nordberg's avatar
Johan Nordberg committed
119
120
## DEPRECATED

Johan Nordberg's avatar
Johan Nordberg committed
121
122
123
124
Downloads and serves the provided `image_url`, note that a copy will be taken of the image and that will be served on subsequent requests so even if the upstream is removed or changes you will still get the original from the proxy endpoint.

`width` and `height` can be set to `0` to preserve the image dimensions, if they are `>0` the image will be aspect resized (down-sample only) to fit inside the rectangle.

Johan Nordberg's avatar
Johan Nordberg committed
125
#### `GET /u/<username>/avatar/[<size>]` - get user avatar image.
Johan Nordberg's avatar
Johan Nordberg committed
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

Serves the avatar for `username`, if no avatar is set a default image will be served (set in service config).

Sizes are:

  * `small` - 64x64
  * `medium` - 128x128
  * `large` - 512x512

Note that the avatars follow the same sizing rules as proxied images, so you are not guaranteed to get a square image, just an image fitting inside of the `size` square.


Signing uploads
---------------

Uploads require a signature made with by a Steem account's posting authority, further that account has to be above a (service configurable) reputation threshold.

Creating a signature (psuedocode):

```python
signature = secp256k1_sign(sha256('ImageSigningChallenge'+image_data), account_private_posting_key)
```
148

Johan Nordberg's avatar
Johan Nordberg committed
149
Creating a signature (node.js & [dsteem](https://github.com/jnordberg/dsteem))
150

Johan Nordberg's avatar
Johan Nordberg committed
151
152
```js
#!/usr/bin/env node
153

Johan Nordberg's avatar
Johan Nordberg committed
154
155
156
const dsteem = require('dsteem')
const crypto = require('crypto')
const fs = require('fs')
James Calfee's avatar
James Calfee committed
157

Johan Nordberg's avatar
Johan Nordberg committed
158
const [wif, file] = process.argv.slice(2)
James Calfee's avatar
James Calfee committed
159

Johan Nordberg's avatar
Johan Nordberg committed
160
161
162
163
if (!wif || !file) {
    process.stderr.write(`Usage: ./sign.js <posting_wif> <file>\n`)
    process.exit(1)
}
James Calfee's avatar
James Calfee committed
164

Johan Nordberg's avatar
Johan Nordberg committed
165
166
167
168
169
170
const data = fs.readFileSync(file)
const key = dsteem.PrivateKey.fromString(wif)
const imageHash = crypto.createHash('sha256')
    .update('ImageSigningChallenge')
    .update(data)
    .digest()
James Calfee's avatar
James Calfee committed
171

Johan Nordberg's avatar
Johan Nordberg committed
172
process.stdout.write(key.sign(imageHash).toString() + '\n')
James Calfee's avatar
James Calfee committed
173
174
```

Johan Nordberg's avatar
Johan Nordberg committed
175
176
177
```sh
$ ./sign.js 5J9jN691Gf3MKdwvqWVx54drx9qub6koyA3mjhenyN12CURua8W test.jpg
1f78d007a0b12cd17f2d349446c3f9b7cfa096ae53903a11608d6232781fb994a2086263f21e4da831d2a2b0b372f701b83042a629ba3d87791d05f393d5504db2
James Calfee's avatar
James Calfee committed
178
```