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