cdn.si

rendered markdown titpetric

Publishing with curl

The HTTP side writes one file per request. Reads are public; a write carries a short-lived token that the SSH login issues for the user whose GitHub key it verified.

Get a token

ssh -p 8022 alice@cdn.si token

The token is HMAC-SHA256 over the user, an expiry and a nonce. It is valid for CDN_TOKEN_TTL, 15 minutes unless the instance sets another value, and it can be used more than once before it expires.

Write one file

PUT /<user>/<path> replaces or creates the file. The token goes in Authorization: Bearer.

TOKEN=$(ssh -p 8022 alice@cdn.si token)

curl -T coverage.html \
  -H "Authorization: Bearer $TOKEN" \
  https://cdn.si/alice/docs/coverage.html

curl -T sends a PUT. A stored file answers 201 Created.

The body is written to a temporary file in the target folder and renamed into place, so a reader never sees half a file.

Upload several files

POST /upload takes a multipart form: user, path, token and one or more file parts. It answers 303 with the folder listing as Location, and the listing says how many files arrived.

curl -F user=alice \
  -F path=docs \
  -F token="$TOKEN" \
  -F file=@README.md \
  -F file=@docs/usage-curl.md \
  https://cdn.si/upload

Answers

Status Meaning
201 the PUT stored the file
303 the multipart upload stored the files
400 the user, the path or a file name is not valid
401 the token is missing, expired or belongs to another user
413 the write would exceed the 50 MiB quota, or the body is too large
409 a directory already exists where the file would go

A write is checked against the quota before anything is renamed into place, so a refused write leaves the tree as it was.

A .md file is rendered as an HTML page at the address it was uploaded to, so https://cdn.si/alice/docs/README.md serves the document and not its source. Other files read by type: an image is drawn, text arrives as text/plain, and a binary is downloaded. An .html file is text, never a page.

Publishing with rsync covers a whole folder.