8
8
"""
9
9
10
10
import json
11
+ import os
11
12
import socket
13
+ import tempfile
12
14
import time
13
15
14
16
import pytest
23
25
@pytest .fixture (scope = "module" )
24
26
def http_server (request ):
25
27
"""
26
- Slightly modified version of the `` pytest_localserver.plugin.http_server` `
28
+ Slightly modified version of the :func:` pytest_localserver.plugin.httpserver `
27
29
fixture that will only start and stop the server application once for test
28
30
performance reasons.
29
31
"""
@@ -33,18 +35,48 @@ def http_server(request):
33
35
return server
34
36
35
37
38
+ @pytest .fixture (scope = "module" )
39
+ def http_server_uds (request ):
40
+ """Like :func:`http_server` but will listen on a Unix domain socket instead
41
+
42
+ If the current platform does not support Unix domain sockets, the
43
+ corresponding test will be skipped.
44
+ """
45
+ if not hasattr (socket , "AF_UNIX" ):
46
+ pytest .skip ("Platform does not support Unix domain sockets" )
47
+
48
+ uds_path = tempfile .mktemp (".sock" )
49
+ def remove_uds_path ():
50
+ try :
51
+ os .remove (uds_path )
52
+ except FileNotFoundError :
53
+ pass
54
+ request .addfinalizer (remove_uds_path )
55
+
56
+ server = pytest_localserver .http .ContentServer ("unix://{0}" .format (uds_path ))
57
+ server .start ()
58
+ request .addfinalizer (server .stop )
59
+ return server
60
+
61
+
36
62
@pytest .fixture
37
63
def http_client (http_server ):
38
64
return ipfshttpclient .http .ClientSync (
39
65
"/ip4/{0}/tcp/{1}/http" .format (* http_server .server_address ),
40
- ipfshttpclient .DEFAULT_BASE
66
+ ipfshttpclient .DEFAULT_BASE ,
67
+ )
68
+
69
+
70
+ @pytest .fixture
71
+ def http_client_uds (http_server_uds ):
72
+ return ipfshttpclient .http .ClientSync (
73
+ "/unix/{0}" .format (http_server_uds .server_address .lstrip ("/" )),
74
+ ipfshttpclient .DEFAULT_BASE ,
41
75
)
42
76
43
77
44
78
def broken_http_server_app (environ , start_response ):
45
- """
46
- HTTP server application that will be slower to respond (0.5 seconds)
47
- """
79
+ """HTTP server application that will return a malformed response"""
48
80
start_response ("0 What the heck?" , [])
49
81
50
82
yield b""
@@ -58,9 +90,7 @@ def broken_http_server(request):
58
90
59
91
60
92
def slow_http_server_app (environ , start_response ):
61
- """
62
- HTTP server application that will be slower to respond (0.5 seconds)
63
- """
93
+ """HTTP server application that will be slower to respond (0.5 seconds)"""
64
94
start_response ("400 Bad Request" , [
65
95
("Content-Type" , "text/json" )
66
96
])
@@ -86,13 +116,28 @@ def test_successful_request(http_client, http_server):
86
116
res = http_client .request ("/okay" )
87
117
assert res == b"okay"
88
118
119
+ def test_successful_request_uds (http_client_uds , http_server_uds ):
120
+ """Tests that a successful http request returns the proper message."""
121
+ http_server_uds .serve_content ("okay" , 200 )
122
+
123
+ res = http_client_uds .request ("/okay" )
124
+ assert res == b"okay"
125
+ print (http_server_uds .requests [0 ].headers )
126
+
89
127
def test_generic_failure (http_client , http_server ):
90
128
"""Tests that a failed http request raises an HTTPError."""
91
129
http_server .serve_content ("fail" , 500 )
92
130
93
131
with pytest .raises (ipfshttpclient .exceptions .StatusError ):
94
132
http_client .request ("/fail" )
95
133
134
+ def test_generic_failure_uds (http_client_uds , http_server_uds ):
135
+ """Tests that a failed http request raises an HTTPError."""
136
+ http_server_uds .serve_content ("fail" , 500 )
137
+
138
+ with pytest .raises (ipfshttpclient .exceptions .StatusError ):
139
+ http_client_uds .request ("/fail" )
140
+
96
141
def test_http_client_failure (http_client , http_server ):
97
142
"""Tests that an http client failure raises an ipfsHTTPClientError."""
98
143
http_server .serve_content (json .dumps ({
@@ -366,26 +411,33 @@ def test_readable_stream_wrapper_read_single_bytes(mocker):
366
411
367
412
@pytest .mark .parametrize ("args,expected" , [
368
413
(("/dns/localhost/tcp/5001" , "api/v0" ),
369
- ("http://localhost:5001/api/v0/" , socket .AF_UNSPEC , False )),
414
+ ("http://localhost:5001/api/v0/" , None , socket .AF_UNSPEC , False )),
370
415
371
416
(("/dns/localhost/tcp/5001/http" , "api/v0" ),
372
- ("http://localhost:5001/api/v0/" , socket .AF_UNSPEC , False )),
417
+ ("http://localhost:5001/api/v0/" , None , socket .AF_UNSPEC , False )),
373
418
374
419
(("/dns4/localhost/tcp/5001/http" , "api/v0" ),
375
- ("http://localhost:5001/api/v0/" , socket .AF_INET , False )),
420
+ ("http://localhost:5001/api/v0/" , None , socket .AF_INET , False )),
376
421
377
422
(("/dns6/localhost/tcp/5001/http" , "api/v0/" ),
378
- ("http://localhost:5001/api/v0/" , socket .AF_INET6 , False )),
423
+ ("http://localhost:5001/api/v0/" , None , socket .AF_INET6 , False )),
379
424
380
425
(("/ip4/127.0.0.1/tcp/5001/https" , "api/v1/" ),
381
- ("https://127.0.0.1:5001/api/v1/" , socket .AF_INET , True )),
426
+ ("https://127.0.0.1:5001/api/v1/" , None , socket .AF_INET , True )),
382
427
383
428
(("/ip6/::1/tcp/5001/https" , "api/v1" ),
384
- ("https://[::1]:5001/api/v1/" , socket .AF_INET6 , True )),
429
+ ("https://[::1]:5001/api/v1/" , None , socket .AF_INET6 , True )),
385
430
386
431
(("/dns4/ietf.org/tcp/443/https" , "/base/" ),
387
- ("https://ietf.org:443/base/" , socket .AF_INET , False )),
388
- ])
432
+ ("https://ietf.org:443/base/" , None , socket .AF_INET , False )),
433
+ ] + ([ # Unix domain sockets aren't supported on all target platforms
434
+ (("/unix/run/ipfs/ipfs.sock" , "api/v0" ),
435
+ ("http://%2Frun%2Fipfs%2Fipfs.sock/api/v0/" , "/run/ipfs/ipfs.sock" , socket .AF_UNIX , False )),
436
+ # Stupid, but standard behaviour: There is no way to append a target protocol item, after
437
+ # a path protocol like /unix, so terminating it with /https ends up part of the /unix path
438
+ (("/unix/run/ipfs/ipfs.sock/https" , "api/v0" ),
439
+ ("http://%2Frun%2Fipfs%2Fipfs.sock%2Fhttps/api/v0/" , "/run/ipfs/ipfs.sock/https" , socket .AF_UNIX , False )),
440
+ ] if hasattr (socket , "AF_UNIX" ) else []))
389
441
def test_multiaddr_to_url_data (args , expected ):
390
442
assert ipfshttpclient .http_common .multiaddr_to_url_data (* args ) == expected
391
443
@@ -395,12 +447,18 @@ def test_multiaddr_to_url_data(args, expected):
395
447
("/ip4/192.168.250.1/tcp/4001/p2p/QmVgNoP89mzpgEAAqK8owYoDEyB97MkcGvoWZir8otE9Uc" , "api/v1/" ),
396
448
("/ip4/::1/sctp/5001/https" , "api/v1/" ),
397
449
("/sctp/5001/http" , "api/v0" ),
450
+ ("/unix" , "api/v0" ),
451
+
452
+ # Should work, but needs support in py-multiaddr first (tls protocol)
453
+ ("/ip6/::1/tcp/5001/tls/http" , "api/v1" ),
398
454
399
- # Should work, but currently doesn't (no proxy support)
400
- ("/dns/localhost/tcp/5001/socks5/dns/ietf.org/tcp/80/http" , "/base/" ),
401
- ("/dns/proxy-servers.example/tcp/5001/https/dns/ietf.org/tcp/80/http" , "/base/" ),
455
+ # Should work, but needs support in py-multiaddr first (proxying protocols)
456
+ ("/dns/localhost/tcp/1080/socks5/dns/ietf.org/tcp/80/http" , "/base/" ),
457
+ ("/dns/localhost/tcp/1080/socks5/ip6/2001:1234:5678:9ABC::1/tcp/80/http" , "/base/" ),
458
+ ("/dns/localhost/tcp/80/http-tunnel/dns/mgnt.my-server.example/tcp/443/https" , "/srv/ipfs/api/v0" ),
459
+ ("/dns/proxy-servers.example/tcp/443/tls/http-tunnel/dns/my-server.example/tcp/5001/http" , "/base/" ),
402
460
403
- # Maybe should also work, but currently doesn't (HTTP/3)
461
+ # Maybe should also work eventually , but currently doesn't (HTTP/3)
404
462
("/dns/localhost/udp/5001/quic/http" , "/base" ),
405
463
])
406
464
def test_multiaddr_to_url_data_invalid (args ):
0 commit comments