61 lines
1.9 KiB
Elixir
61 lines
1.9 KiB
Elixir
defmodule Clacks.HTTP do
|
|
require Logger
|
|
|
|
@spec get(url :: String.t(), headers :: [{String.t(), String.t()}]) ::
|
|
{:ok, HTTPoison.Response.t()} | {:error, String.t()}
|
|
def get(url, headers \\ []) do
|
|
fetch(:get, url, headers)
|
|
end
|
|
|
|
@spec head(url :: String.t(), headers :: [{String.t(), String.t()}]) ::
|
|
{:ok, HTTPoison.Response.t()} | {:error, String.t()}
|
|
def head(url, headers \\ []) do
|
|
fetch(:head, url, headers)
|
|
end
|
|
|
|
defp fetch(method, url, headers) do
|
|
opts = [hackney: Application.get_env(:clacks, :hackney_opts, [])]
|
|
|
|
case HTTPoison.request(method, url, "", headers, opts) do
|
|
{:ok, %HTTPoison.Response{status_code: status_code} = response}
|
|
when status_code in 200..299 ->
|
|
{:ok, response}
|
|
|
|
{:ok, %HTTPoison.Response{status_code: status_code, headers: resp_headers}}
|
|
when status_code in [301, 302] ->
|
|
resp_headers
|
|
|> Enum.find(fn {name, _value} -> String.downcase(name) == "location" end)
|
|
|> case do
|
|
{_, new_url} ->
|
|
new_url =
|
|
case URI.parse(new_url) do
|
|
%URI{host: nil, path: path} ->
|
|
# relative path
|
|
%URI{URI.parse(url) | path: path} |> URI.to_string()
|
|
|
|
uri ->
|
|
uri
|
|
end
|
|
|
|
Logger.debug("Got 301 redirect from #{url} to #{new_url}")
|
|
fetch(method, new_url, headers)
|
|
|
|
_ ->
|
|
{:error, "Missing Location header for redirect"}
|
|
end
|
|
|
|
{:ok, %HTTPoison.Response{status_code: 403}} ->
|
|
{:error, "403 Forbidden"}
|
|
|
|
{:ok, %HTTPoison.Response{status_code: 404}} ->
|
|
{:error, "404 Not Found"}
|
|
|
|
{:ok, %HTTPoison.Response{status_code: status_code}} ->
|
|
{:error, "HTTP #{status_code}"}
|
|
|
|
{:error, %HTTPoison.Error{reason: reason}} ->
|
|
{:error, inspect(reason)}
|
|
end
|
|
end
|
|
end
|