Current section

Files

Jump to
transloaditex lib tus_client post.ex
Raw

lib/tus_client/post.ex

defmodule TusClient.Post do
@moduledoc false
alias TusClient.Utils
require Logger
def request(url, path, headers \\ [], opts \\ []) do
path
|> get_filesize()
|> do_request(url, headers, opts)
end
defp do_request({:ok, size}, url, headers, opts) do
hdrs =
[{"upload-length", to_string(size)}]
|> Utils.add_version_hdr()
|> Kernel.++(headers)
|> Enum.uniq()
|> add_metadata(opts)
req_opts =
[method: :post, url: url, headers: hdrs, body: ""] ++ Utils.req_options(opts)
case Req.request(req_opts) do
{:ok, %{status: 201} = resp} ->
process(resp)
{:ok, %{status: 413}} ->
{:error, :too_large}
{:ok, resp} ->
Logger.error("POST response not handled: #{inspect(resp)}")
{:error, :generic}
{:error, err} ->
Logger.error("POST request failed: #{inspect(err)}")
{:error, :transport}
end
end
defp do_request(err, _url, _headers, _opts), do: err
defp process(%{headers: headers}) when map_size(headers) == 0, do: {:error, :not_supported}
defp process(%{headers: headers}) do
case get_location(headers) do
{:ok, location} -> {:ok, %{location: location}}
_ -> {:error, :location}
end
end
defp get_location(headers) do
case Utils.get_header(headers, "location") do
v when is_binary(v) -> {:ok, v}
_ -> {:error, :location}
end
end
defp get_filesize(path) do
case File.stat(path) do
{:ok, %{size: size}} -> {:ok, size}
_ -> {:error, :file_error}
end
end
defp add_metadata(headers, opts) do
case Keyword.get(opts, :metadata) do
md when is_map(md) ->
new_md = cleanup_metadata(md)
if Enum.empty?(new_md) do
headers
else
headers ++ [{"upload-metadata", encode_metadata(new_md)}]
end
_ ->
headers
end
end
defp cleanup_metadata(md) do
md
|> Enum.map(fn {k, v} -> {"#{k}", v} end)
|> Enum.filter(fn {k, _v} ->
if k =~ ~r/^[a-zA-Z0-9_\-\.]+$/ do
true
else
Logger.warning("Discarding invalid key #{k}")
false
end
end)
|> Map.new()
end
defp encode_metadata(md) do
md
|> Enum.map(fn {k, v} ->
value = v |> to_string() |> Base.encode64()
"#{k} #{value}"
end)
|> Enum.join(",")
end
end