1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.ReverseProxy.Client.Hackney do
6 @behaviour Pleroma.ReverseProxy.Client
8 # redirect handler from Pleb, slightly modified to work with Hackney
9 # https://declin.eu/objects/d4f38e62-5429-4614-86d1-e8fc16e6bf33
10 # seven years without upstream fix!
11 # https://github.com/benoitc/hackney/issues/273
12 @redirect_statuses [301, 302, 303, 307, 308]
13 defp get_location(headers) do
15 Enum.find(headers, fn {header, _location} ->
16 String.downcase(header) == "location"
23 def request(method, url, headers, body, opts \\ []) do
24 if opts[:follow_redirect] != false do
25 {_state, req_opts} = Access.get_and_update(opts, :follow_redirect, fn a -> {a, false} end)
26 res = :hackney.request(method, url, headers, body, req_opts)
29 {:ok, code, reply_headers, _client} when code in @redirect_statuses ->
30 :hackney.request(method, get_location(reply_headers), headers, body, req_opts)
32 {:ok, code, reply_headers} when code in @redirect_statuses ->
33 :hackney.request(method, get_location(reply_headers), headers, body, req_opts)
39 :hackney.request(method, url, headers, body, opts)
44 def stream_body(ref) do
45 case :hackney.stream_body(ref) do
47 {:ok, data} -> {:ok, data, ref}
48 {:error, error} -> {:error, error}
53 def close(ref), do: :hackney.close(ref)