37489e1a4501ecb5607049402ab31b435067abc0
[akkoma] / test / http / adapter / gun_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.HTTP.Adapter.GunTest do
6 use ExUnit.Case, async: true
7 use Pleroma.Tests.Helpers
8 import ExUnit.CaptureLog
9 alias Pleroma.Config
10 alias Pleroma.HTTP.Adapter.Gun
11 alias Pleroma.Pool.Connections
12
13 setup_all do
14 {:ok, _} = Registry.start_link(keys: :unique, name: Pleroma.Gun.API.Mock)
15 :ok
16 end
17
18 describe "options/1" do
19 clear_config([:http, :adapter]) do
20 Config.put([:http, :adapter], a: 1, b: 2)
21 end
22
23 test "https url with default port" do
24 uri = URI.parse("https://example.com")
25
26 opts = Gun.options(uri)
27 assert opts[:certificates_verification]
28 tls_opts = opts[:tls_opts]
29 assert tls_opts[:verify] == :verify_peer
30 assert tls_opts[:depth] == 20
31 assert tls_opts[:reuse_sessions] == false
32
33 assert tls_opts[:verify_fun] ==
34 {&:ssl_verify_hostname.verify_fun/3, [check_hostname: 'example.com']}
35
36 assert File.exists?(tls_opts[:cacertfile])
37
38 assert opts[:original] == "example.com:443"
39 end
40
41 test "https ipv4 with default port" do
42 uri = URI.parse("https://127.0.0.1")
43
44 opts = Gun.options(uri)
45
46 assert opts[:tls_opts][:verify_fun] ==
47 {&:ssl_verify_hostname.verify_fun/3, [check_hostname: '127.0.0.1']}
48
49 assert opts[:original] == "127.0.0.1:443"
50 end
51
52 test "https ipv6 with default port" do
53 uri = URI.parse("https://[2a03:2880:f10c:83:face:b00c:0:25de]")
54
55 opts = Gun.options(uri)
56
57 assert opts[:tls_opts][:verify_fun] ==
58 {&:ssl_verify_hostname.verify_fun/3,
59 [check_hostname: '2a03:2880:f10c:83:face:b00c:0:25de']}
60
61 assert opts[:original] == "2a03:2880:f10c:83:face:b00c:0:25de:443"
62 end
63
64 test "https url with non standart port" do
65 uri = URI.parse("https://example.com:115")
66
67 opts = Gun.options(uri)
68
69 assert opts[:certificates_verification]
70 assert opts[:transport] == :tls
71 end
72
73 test "receive conn by default" do
74 uri = URI.parse("http://another-domain.com")
75 :ok = Connections.open_conn(uri, :gun_connections)
76
77 received_opts = Gun.options(uri)
78 assert received_opts[:close_conn] == false
79 assert is_pid(received_opts[:conn])
80 end
81
82 test "don't receive conn if receive_conn is false" do
83 uri = URI.parse("http://another-domain2.com")
84 :ok = Connections.open_conn(uri, :gun_connections)
85
86 opts = [receive_conn: false]
87 received_opts = Gun.options(opts, uri)
88 assert received_opts[:close_conn] == nil
89 assert received_opts[:conn] == nil
90 end
91
92 test "get conn on next request" do
93 level = Application.get_env(:logger, :level)
94 Logger.configure(level: :info)
95 on_exit(fn -> Logger.configure(level: level) end)
96 uri = URI.parse("http://some-domain2.com")
97
98 assert capture_log(fn ->
99 opts = Gun.options(uri)
100
101 assert opts[:conn] == nil
102 assert opts[:close_conn] == nil
103 end) =~
104 "Gun connections pool checkin was not succesfull. Trying to open conn for next request."
105
106 opts = Gun.options(uri)
107
108 assert is_pid(opts[:conn])
109 assert opts[:close_conn] == false
110 end
111
112 test "merges with defaul http adapter config" do
113 defaults = Gun.options(URI.parse("https://example.com"))
114 assert Keyword.has_key?(defaults, :a)
115 assert Keyword.has_key?(defaults, :b)
116 end
117
118 test "default ssl adapter opts with connection" do
119 uri = URI.parse("https://some-domain.com")
120
121 :ok = Connections.open_conn(uri, :gun_connections)
122
123 opts = Gun.options(uri)
124
125 assert opts[:certificates_verification]
126 tls_opts = opts[:tls_opts]
127 assert tls_opts[:verify] == :verify_peer
128 assert tls_opts[:depth] == 20
129 assert tls_opts[:reuse_sessions] == false
130
131 assert opts[:original] == "some-domain.com:443"
132 assert opts[:close_conn] == false
133 assert is_pid(opts[:conn])
134 end
135
136 test "parses string proxy host & port" do
137 proxy = Config.get([:http, :proxy_url])
138 Config.put([:http, :proxy_url], "localhost:8123")
139 on_exit(fn -> Config.put([:http, :proxy_url], proxy) end)
140
141 uri = URI.parse("https://some-domain.com")
142 opts = Gun.options([receive_conn: false], uri)
143 assert opts[:proxy] == {'localhost', 8123}
144 end
145
146 test "parses tuple proxy scheme host and port" do
147 proxy = Config.get([:http, :proxy_url])
148 Config.put([:http, :proxy_url], {:socks, 'localhost', 1234})
149 on_exit(fn -> Config.put([:http, :proxy_url], proxy) end)
150
151 uri = URI.parse("https://some-domain.com")
152 opts = Gun.options([receive_conn: false], uri)
153 assert opts[:proxy] == {:socks, 'localhost', 1234}
154 end
155
156 test "passed opts have more weight than defaults" do
157 proxy = Config.get([:http, :proxy_url])
158 Config.put([:http, :proxy_url], {:socks5, 'localhost', 1234})
159 on_exit(fn -> Config.put([:http, :proxy_url], proxy) end)
160 uri = URI.parse("https://some-domain.com")
161 opts = Gun.options([receive_conn: false, proxy: {'example.com', 4321}], uri)
162
163 assert opts[:proxy] == {'example.com', 4321}
164 end
165 end
166
167 describe "after_request/1" do
168 test "body_as not chunks" do
169 uri = URI.parse("http://some-domain.com")
170 :ok = Connections.open_conn(uri, :gun_connections)
171 opts = Gun.options(uri)
172 :ok = Gun.after_request(opts)
173 conn = opts[:conn]
174
175 assert %Connections{
176 conns: %{
177 "http:some-domain.com:80" => %Pleroma.Gun.Conn{
178 conn: ^conn,
179 conn_state: :idle,
180 used_by: []
181 }
182 }
183 } = Connections.get_state(:gun_connections)
184 end
185
186 test "body_as chunks" do
187 uri = URI.parse("http://some-domain.com")
188 :ok = Connections.open_conn(uri, :gun_connections)
189 opts = Gun.options([body_as: :chunks], uri)
190 :ok = Gun.after_request(opts)
191 conn = opts[:conn]
192 self = self()
193
194 assert %Connections{
195 conns: %{
196 "http:some-domain.com:80" => %Pleroma.Gun.Conn{
197 conn: ^conn,
198 conn_state: :active,
199 used_by: [{^self, _}]
200 }
201 }
202 } = Connections.get_state(:gun_connections)
203 end
204
205 test "with no connection" do
206 uri = URI.parse("http://uniq-domain.com")
207
208 :ok = Connections.open_conn(uri, :gun_connections)
209
210 opts = Gun.options([body_as: :chunks], uri)
211 conn = opts[:conn]
212 opts = Keyword.delete(opts, :conn)
213 self = self()
214
215 :ok = Gun.after_request(opts)
216
217 assert %Connections{
218 conns: %{
219 "http:uniq-domain.com:80" => %Pleroma.Gun.Conn{
220 conn: ^conn,
221 conn_state: :active,
222 used_by: [{^self, _}]
223 }
224 }
225 } = Connections.get_state(:gun_connections)
226 end
227
228 test "with ipv4" do
229 uri = URI.parse("http://127.0.0.1")
230 :ok = Connections.open_conn(uri, :gun_connections)
231 opts = Gun.options(uri)
232 send(:gun_connections, {:gun_up, opts[:conn], :http})
233 :ok = Gun.after_request(opts)
234 conn = opts[:conn]
235
236 assert %Connections{
237 conns: %{
238 "http:127.0.0.1:80" => %Pleroma.Gun.Conn{
239 conn: ^conn,
240 conn_state: :idle,
241 used_by: []
242 }
243 }
244 } = Connections.get_state(:gun_connections)
245 end
246
247 test "with ipv6" do
248 uri = URI.parse("http://[2a03:2880:f10c:83:face:b00c:0:25de]")
249 :ok = Connections.open_conn(uri, :gun_connections)
250 opts = Gun.options(uri)
251 send(:gun_connections, {:gun_up, opts[:conn], :http})
252 :ok = Gun.after_request(opts)
253 conn = opts[:conn]
254
255 assert %Connections{
256 conns: %{
257 "http:2a03:2880:f10c:83:face:b00c:0:25de:80" => %Pleroma.Gun.Conn{
258 conn: ^conn,
259 conn_state: :idle,
260 used_by: []
261 }
262 }
263 } = Connections.get_state(:gun_connections)
264 end
265 end
266 end