Generate Signed URLs for Google Cloud Storage in Elixir.
- Add
guss
to your list of dependencies inmix.exs
:
def deps do
[
{:guss, "~> 0.1.0"}
]
end
- If you're using Goth for authentication, be sure to configure your credentials:
config :goth,
json: {:system, "GCP_CREDENTIALS_JSON"}
Documentation can be found at https://hexdocs.pm/guss.
First, create a new resource with your URL components:
iex(1)> url = Guss.new("downloads", "movie.mp4", content_type: "video/mp4")
%Guss.Resource{bucket: "downloads", objectname: "movie.mp4"...}
Then, sign the url:
iex(2)> Guss.sign(url)
{:ok, "https://storage.googleapis.com/downloads/movie.mp4?Expires=1543..."}
By default, sign/1
will use the default credentials stored in the Goth config to generate the signature.
To specify an account other than the default, update the :account
on the resource:
Guss.sign(%{url | account: "[email protected]"})
It is also possible to use Guss without Goth.
The default :expires
value is 1 hour. You can use Guss.expires_in/1
to set a custom future timestamp:
iex(4)> url = Guss.new("downloads", "movie.mp4", expires: Guss.expires_in({1, :day}))
%Guss.Resource{
account: :default,
base_url: "https://storage.googleapis.com",
bucket: "downloads",
content_md5: nil,
content_type: nil,
expires: 1543526299,
extensions: [],
http_verb: :get,
objectname: "movie.mp4"
}
Setting the content type in the signature requires the Content-Type
header to be set on upload:
Guss.put("downloads", "movie.mp4", content_type: "video/mp4")
Guss can incorporate custom extension headers into the URL signature.
For instance, to set the canned ACL policy for the object during upload:
Guss.put("bucket", "objectname", acl: :public_read)
Any x-goog-
header can be included in the options list...
Guss.put("bucket", "objectname", content_length_range: "0,256")
...including x-goog-meta-
headers:
Guss.put("bucket", "objectname", meta: [project: [name: "My Project"]])
Please Note: All headers that appear within the signature MUST also appear in the request to the Signed URL, or the request will be rejected.
If you store your authentication data somewhere other than Goth, you can supply your own config module when signing URLs.
First, create a module that can return values for "client_email"
and "private_key"
:
defmodule MyGussConfig do
def get(account \\ :default, key)
def get(account, "client_email"), do: fetch_email(account)
def get(account, "private_key"), do: fetch_private_key(account)
end
Then, create a resource and sign it using your config module:
"bucket"
|> Guss.new("objectname", account: "[email protected]")
|> Guss.sign(config_module: MyGussConfig)