Current section

Files

Jump to
transloaditex lib tus_client head.ex
Raw

lib/tus_client/head.ex

defmodule TusClient.Head do
@moduledoc false
alias TusClient.Utils
require Logger
def request(url, headers \\ [], opts \\ []) do
url
|> HTTPoison.head(headers, Utils.httpoison_opts([], opts))
|> Utils.maybe_follow_redirect(&parse/1, &request(&1, headers, opts))
end
defp parse({:ok, %{status_code: status} = resp}) when status in [200, 204] do
resp
|> process()
end
defp parse({:ok, %{status_code: status}}) when status in [403, 404, 410] do
{:error, :not_found}
end
defp parse({:ok, resp}) do
Logger.error("HEAD response not handled: #{inspect(resp)}")
{:error, :generic}
end
defp parse({:error, err}) do
Logger.error("HEAD request failed: #{inspect(err)}")
{:error, :transport}
end
defp process(%{headers: []}), do: {:error, :preconditions}
defp process(%{headers: headers}) do
with {:ok, offset} <- get_upload_offset(headers),
:ok <- ensure_no_cache(headers),
{:ok, len} <- get_upload_len(headers) do
{:ok,
%{
upload_offset: offset,
upload_length: len
}}
else
{:error, :no_offset} -> {:error, :preconditions}
{:error, :wrong_cache} -> {:error, :preconditions}
end
end
defp get_upload_len(headers) do
case Utils.get_header(headers, "upload-length") do
v when is_binary(v) -> {:ok, String.to_integer(v)}
_ -> {:ok, nil}
end
end
defp get_upload_offset(headers) do
case Utils.get_header(headers, "upload-offset") do
v when is_binary(v) -> {:ok, String.to_integer(v)}
_ -> {:error, :no_offset}
end
end
defp ensure_no_cache(headers) do
case Utils.get_header(headers, "cache-control") do
"no-store" -> :ok
_ -> {:error, :wrong_cache}
end
end
end