clacks/lib/clacks/http.ex

61 lines
1.9 KiB
Elixir

defmodule Clacks.HTTP do
require Logger
@spec get(url :: String.t(), headers :: HTTPoison.headers()) ::
{:ok, HTTPoison.Response.t()} | {:error, String.t()}
def get(url, headers \\ []) do
fetch(:get, url, headers)
end
@spec head(url :: String.t(), headers :: HTTPoison.headers()) ::
{: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 =
URI.merge(URI.parse(url), URI.parse(new_url))
|> URI.to_string()
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
@spec post(String.t(), any(), HTTPoison.headers()) ::
{:ok, HTTPoison.Response.t()} | {:error, HTTPoison.Error.t()}
def post(url, body, headers \\ []) do
HTTPoison.post(url, body, headers)
end
end