Coelho.Plug.Attachments (coelho v0.2.0)

Copy Markdown View Source

Serves attachment bytes, behind a signature.

plug Coelho.Plug.Attachments,
  at: "/attachments",
  storage: Coelho.Storage.Disk.new("priv/uploads"),
  secret: {MyApp.Uploads, :secret, []},
  metadata: {MyApp.Uploads, :metadata, []}

Requests that do not match :at fall through untouched.

Options

  • :at — the path prefix to serve from, required
  • :storage — a Coelho.Storage, or an {m, f, a} returning one, required. The {m, f, a} form matters in an endpoint, where init/1 may run at compile time and a storage built then would freeze the configuration it was built from
  • :secret — the signing secret, as a binary or an {m, f, a} read at request time, required. It has to match what built the URL; see Coelho.Attachments.signed_url/4
  • :metadata — an {m, f, a} called with the key, returning %{content_type: …, filename: …} or nil. Coelho does not hold a repo, so this is how the row reaches the response

Serving other people's files

Uploads served from the application's own origin are a standing hazard: a file the browser decides to render as HTML runs as the application. So a response carrying bytes always has x-content-type-options: nosniff, and only a short list of image types is served inline. Everything else — including SVG, which is a document that can carry script — is sent as a download, whatever it claims to be.

A redirect carries none of those headers, which is why one is only offered for the types that would have been served inline anyway, and why a storage implementing Coelho.Storage.redirect_url/3 is expected to honour the :content_type it is given.