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