Storehouse.Local.Plug (Storehouse v0.1.0)

Copy Markdown View Source

Serves the files of Storehouse.Local, and takes the ones a browser uploads straight to it, when the store signed the upload.

In the endpoint, before the router:

plug Storehouse.Local.Plug

The plug answers GET and HEAD requests under the :at path (by default the configured :url_prefix of Storehouse.Local), and passes every other request on. In a router, forward strips the path, so give at: "/":

forward "/uploads", Storehouse.Local.Plug, at: "/"

Options

  • :at - the request path of the files. The default is the configured :url_prefix.
  • :root - the directory. The default is the configured :root.
  • :max_age - the max-age of the Cache-Control header, in seconds. The default is 3600.
  • :private - when true, a file is served only at a URL the store signed (Storehouse.signed_url/2), until it expires. The default is false: every file is served, and a signed URL as well.

Uploads

A PUT of a file at a URL the store signed (Storehouse.presign_upload/4) writes it under its key: of the signed type (its Content-Type), of the signed size exactly, before the signature expires, and only where no file is. The answer is 200; 403 for a signature that is not the store's or has expired, 409 for a key that has a file, 400 for a body of another size or type. Put the plug before Plug.Parsers, which would read the body first.

Responses

  • The content type comes from the file extension, through the allow-list of Storehouse.Check.content_type/1: an extension that is not in it (.html, .svg, …) is sent as application/octet-stream.
  • Cache-Control: private, max-age=…, X-Content-Type-Options: nosniff and Content-Security-Policy: default-src 'none'; sandbox, so a file cannot run a script on the app's origin.
  • PNG, JPEG, GIF and WebP images, PDF files and MP4 and WebM videos are served inline; every other file has Content-Disposition: attachment.
  • Accept-Ranges: bytes, and a GET with a single Range (bytes=0-99, bytes=100-, bytes=-100) gives 206 with that part of the file and Content-Range. A range that starts after the end of the file gives 416. Several ranges, or a header that is not valid, give the whole file. Browsers need ranges to seek in a video, and Safari to play one.
  • A path with a segment that is not a valid key segment (.., ., or a character other than ASCII letters, digits, ., - and _) gives 400. A key with no regular file gives 404: a directory, a symbolic link to a file, and a path through a symbolic link to a directory included.