Storehouse.Proxy (Storehouse v0.2.0)

Copy Markdown View Source

A file of the store sent through the app: it checks that the person may see it, then streams it from the store, a part at a time, so that the bucket's address never leaves the app and a CDN in front keeps what it may. The sibling of Storehouse.Redirect, which sends the person to a signed URL instead.

In the router, in a scope that has the person:

forward "/files", Storehouse.Proxy, authorize: &MyAppWeb.Files.allowed?/2

/files/2026/10/0b6…-board.png then sends the file. The function takes the conn and the key; a key it refuses, a key that is not valid, or a file that is not there, gives 404, so that no one learns which files exist.

Responses

  • The file's type is the store's, through the allow-list of Storehouse.Check.content_type/1: another is sent as application/octet-stream. With X-Content-Type-Options: nosniff and Content-Security-Policy: default-src 'none'; sandbox, and Content-Disposition: attachment for every type a browser should not show, as Storehouse.Local.Plug sends them.
  • A single Range gives 206 with that part, as for Storehouse.Local.Plug; Accept-Ranges: bytes always.
  • ETag (from the file's SHA-256, where the store keeps it) and Last-Modified (where the store says): a request with If-None-Match or If-Modified-Since that still holds gives 304, and no byte is read.

Options

  • :authorize - the function (required). true lets everyone in: a public bucket kept behind the app.
  • :cache_control - the Cache-Control header. The default is "private, max-age=0, must-revalidate": a file only some may see is never kept by a CDN for others. For files everyone may see, "public, max-age=31536000, immutable".
  • :cache_tag - true sends the file's Cache-Tag (Storehouse.Purge.cache_tag/1).
  • :chunk_bytes - the size of each read from the store. The default is 4 MiB.
  • :adapter - the store. It must read files a part at a time (Storehouse.Adapter.read_range/3): Storehouse.Local and Storehouse.S3 do. The default is Storehouse.adapter/0.