Fil.Plugin.URL (Fil v0.1.0)

Copy Markdown View Source

Builds URLs for any disk, served by Fil.Plug from your application.

disk =
  Fil.disk(adapter: Fil.Adapter.Local, root: "priv/storage/uploads")
  |> Fil.Plugin.URL.attach(base_url: "http://localhost:4000/storage/uploads", secret: secret)

Fil.url(disk, "avatars/1.png")
#=> {:ok, "http://localhost:4000/storage/uploads/avatars/1.png"}

Fil.signed_url(disk, "avatars/1.png", method: :put)
#=> {:ok, "http://localhost:4000/storage/uploads/avatars/1.png?expires=...&signature=..."}

The plugin answers Fil.url/2 and, with a :secret, Fil.signed_url/3 itself, so the adapter never runs. That's how local and memory disks get URLs, since there is no storage service that could build them. A public URL only works where Fil.Plug serves the disk with public: true (or something else serves the files at :base_url).

On an S3 disk, :base_url replaces the bucket URL in Fil.url/2, for a CDN in front of the bucket. Without a :secret, S3 still presigns Fil.signed_url/3 itself. With one, signed URLs go to your application, which then passes the file through: useful when the bucket shouldn't be reachable from outside, but every download and upload runs through your application, and files are read into memory whole.

A signed URL is :base_url, the path, and two query parameters: expires (Unix seconds) and signature, an HMAC-SHA256 over the method, the URL path and the expiry. expires_in: is capped at 7 days, as on S3, so a URL that works on one disk works on every disk.

Options

  • :base_url (String.t/0) - Required. The URL the disk root is served at, e.g. "http://localhost:4000/storage/uploads": Fil.Plug in your application, or a CDN in front of the disk.

  • :secret (String.t/0) - The key URLs are signed with. Use at least 32 random bytes (mix phx.gen.secret prints 64). Fil.Plug reads it from the disk, so it's only configured here. Without it, the plugin only builds public URLs, and Fil.signed_url/3 goes to the adapter.

Summary

Functions

Attaches the plugin to disk under the name Fil.Plugin.URL.

Functions

attach(disk, opts)

@spec attach(
  Fil.Disk.t(),
  keyword()
) :: Fil.Disk.t()

Attaches the plugin to disk under the name Fil.Plugin.URL.

The same as plugins: [{Fil.Plugin.URL, :call, opts}] in Fil.disk/1, except that the options are validated here instead of on the first URL.