69 lines
1.8 KiB
Elixir
69 lines
1.8 KiB
Elixir
defmodule Frenzy.HTTP do
|
|
require Logger
|
|
@redirect_codes [301, 302]
|
|
|
|
def get(url) do
|
|
case HTTPoison.get(url) do
|
|
{:ok, %HTTPoison.Response{status_code: 200} = response} ->
|
|
{:ok, response}
|
|
|
|
{:ok, %HTTPoison.Response{status_code: status_code, headers: headers}}
|
|
when status_code in @redirect_codes ->
|
|
headers
|
|
|> Enum.find(fn {name, _value} -> name == "Location" end)
|
|
|> case do
|
|
{"Location", 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}")
|
|
get(new_url)
|
|
|
|
_ ->
|
|
{: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, reason}
|
|
end
|
|
end
|
|
|
|
def resolve_uri(uri, site_uri) when is_binary(site_uri) do
|
|
resolve_uri(uri, URI.parse(site_uri))
|
|
end
|
|
|
|
def resolve_uri(%URI{host: nil, path: path}, %URI{} = site_uri) do
|
|
%URI{site_uri | path: path}
|
|
|> resolve_uri(site_uri)
|
|
end
|
|
|
|
def resolve_uri(%URI{scheme: nil} = uri, %URI{scheme: scheme} = site_uri) do
|
|
scheme =
|
|
case scheme do
|
|
nil -> "https"
|
|
_ -> scheme
|
|
end
|
|
|
|
%URI{uri | scheme: scheme}
|
|
|> resolve_uri(site_uri)
|
|
end
|
|
|
|
def resolve_uri(uri, _), do: uri
|
|
end
|