# `Storehouse.Proxy`
[🔗](https://github.com/hattoriai/storehouse/blob/v0.2.0/lib/storehouse/proxy.ex#L1)

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
    (`c:Storehouse.Adapter.read_range/3`): `Storehouse.Local` and
    `Storehouse.S3` do. The default is `Storehouse.adapter/0`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
