From 00c51e4ad9db837d3a66edf1e1ee029299defcd5 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 25 Apr 2020 22:43:57 -0400 Subject: [PATCH] Improve HTTP handling --- lib/clacks/activitypub/fetcher.ex | 7 +---- lib/clacks/http.ex | 46 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 lib/clacks/http.ex diff --git a/lib/clacks/activitypub/fetcher.ex b/lib/clacks/activitypub/fetcher.ex index cff52ff..98b37a7 100644 --- a/lib/clacks/activitypub/fetcher.ex +++ b/lib/clacks/activitypub/fetcher.ex @@ -40,15 +40,10 @@ defmodule Clacks.ActivityPub.Fetcher do headers = [Accept: "application/activity+json, application/ld+json"] opts = [hackney: Application.get_env(:clacks, :hackney_opts, [])] - with {:ok, %HTTPoison.Response{status_code: status_code, body: body}} - when status_code in 200..299 <- - HTTPoison.get(uri, headers, opts), + with {:ok, %HTTPoison.Response{body: body}} <- Clacks.HTTP.get(uri, headers, opts), {:ok, data} <- Jason.decode(body) do data else - {:ok, %HTTPoison.Response{}} -> - nil - {:error, reason} -> Logger.warn("Couldn't fetch AP object at #{uri}: #{inspect(reason)}") nil diff --git a/lib/clacks/http.ex b/lib/clacks/http.ex new file mode 100644 index 0000000..7eff8d1 --- /dev/null +++ b/lib/clacks/http.ex @@ -0,0 +1,46 @@ +defmodule Clacks.HTTP do + require Logger + + def get(url, headers \\ [], options \\ []) do + case HTTPoison.get(url, headers, options) 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}") + get(new_url, headers, options) + + _ -> + {: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 +end