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