# `Storehouse.Tus.Plug`
[🔗](https://github.com/hattoriai/storehouse/blob/v0.2.0/lib/storehouse/tus/plug.ex#L1)

Resumable uploads through the app, by the [tus](https://tus.io) protocol
(1.0.0): for clients that speak it (Uppy's Tus plugin, tus-js-client,
the mobile and desktop clients), and for stores the browser cannot send
to straight (the local disk). A connection lost halfway carries on from
the last byte the app has.

    # lib/my_app_web/router.ex, behind your authentication
    forward "/files/tus", Storehouse.Tus.Plug,
      owner: &MyAppWeb.Files.owner/1,
      room: &MyAppWeb.Files.room/1,
      accept: ["video/mp4", "video/quicktime"],
      max_bytes: 20_000_000_000,
      then: &MyAppWeb.Files.uploaded/2

and `Storehouse.Tus` in the app's supervision tree, where the uploads in
progress are kept. For a browser that can send straight to a bucket,
`Storehouse.Plug.Multipart` keeps the bytes out of the app altogether.

## Extensions

`creation` (and `creation-with-upload`: the first bytes with the
`POST`), `termination` (`DELETE`) and `expiration` (`Upload-Expires`;
an upload not finished in `:expires_in` is given up). `Upload-Metadata`'s
`filename` and `filetype` (or `name` and `type`) are the file's name and
claimed type.

## Where the bytes go

On a store of multipart uploads (`Storehouse.S3`), into its multipart
upload as they come, a part at a time (`:part_bytes`); the bytes past
the last whole part wait in the upload's state until the next. On
another (`Storehouse.Local`), into a file of `:dir` on the app's disk,
stored when it is whole. Either way the file is checked as every upload
is: its claimed type, size and the owner's room when it is created, its
type by its first bytes when it is whole, and deleted when it is not
what it said.

## Options

  * `:owner`, `:room`, `:existing` - functions of the conn, as for
    `Storehouse.Plug.Presign`. A request for an upload of another owner
    is answered `404`.
  * `:accept`, `:max_bytes` (sent as `Tus-Max-Size`), `:max_pixels`,
    `:metadata`, `:cache_control`, `:adapter` - as for `Storehouse.store/2`.
  * `:then` - a function of the conn and the stored file, called when
    the upload is whole and checked, that gives the conn: to save the
    file in a record, to send its key in a header.
  * `:expires_in` - seconds an upload has to finish. The default is a
    day.
  * `:max_uploads` - the uploads one owner may have in progress at once:
    another is refused with `429`. The default is 10. Those in progress
    count against the owner's `:room` too, by their sizes. (With a
    `:state` that has `c:Storehouse.Tus.State.owned/1`.)
  * `:part_bytes` - the parts of a multipart upload, at least 5 MiB. The
    default is 8 MiB.
  * `:dir` - the directory of the uploads to a store without multipart
    uploads. The default is `storehouse-tus` in the system's temporary
    directory: on several nodes, one they share.
  * `:state` - where uploads are kept between requests, a module of
    `Storehouse.Tus.State`. The default is `Storehouse.Tus.State.ETS`.

## Why not tussle

`tussle` (a fork of the `tus` package) is a tus server for Elixir with
storage of its own (the disk, S3 through ExAws). Storehouse writes
through its own stores instead, with no dependency, and checks a file
as every other upload is checked; the protocol itself is small.

---

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