-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
test_socketlevel.py
158 lines (117 loc) · 5.4 KB
/
test_socketlevel.py
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
from urllib3 import HTTPConnectionPool, HTTPSConnectionPool
from urllib3.poolmanager import proxy_from_url
from urllib3.exceptions import MaxRetryError, TimeoutError, SSLError
from dummyserver.testcase import SocketDummyServerTestCase
from threading import Event
try:
from ssl import HAS_SNI
except ImportError: # openssl without SNI
HAS_SNI = False
class TestCookies(SocketDummyServerTestCase):
def test_multi_setcookie(self):
def multicookie_response_handler(listener):
sock = listener.accept()[0]
buf = b''
while not buf.endswith(b'\r\n\r\n'):
buf += sock.recv(65536)
sock.send(b'HTTP/1.1 200 OK\r\n'
b'Set-Cookie: foo=1\r\n'
b'Set-Cookie: bar=1\r\n'
b'\r\n')
sock.close()
self._start_server(multicookie_response_handler)
pool = HTTPConnectionPool(self.host, self.port)
r = pool.request('GET', '/', retries=0)
self.assertEquals(r.headers, {'set-cookie': 'foo=1, bar=1'})
if HAS_SNI:
class TestSNI(SocketDummyServerTestCase):
def test_hostname_in_first_request_packet(self):
done_receiving = Event()
self.buf = b''
def socket_handler(listener):
sock = listener.accept()[0]
self.buf = sock.recv(65536) # We only accept one packet
done_receiving.set() # let the test know it can proceed
self._start_server(socket_handler)
pool = HTTPSConnectionPool(self.host, self.port)
try:
pool.request('GET', '/', retries=0)
except SSLError: # We are violating the protocol
pass
done_receiving.wait()
self.assertTrue(self.host.encode() in self.buf,
"missing hostname in SSL handshake")
class TestSocketClosing(SocketDummyServerTestCase):
def test_recovery_when_server_closes_connection(self):
# Does the pool work seamlessly if an open connection in the
# connection pool gets hung up on by the server, then reaches
# the front of the queue again?
done_closing = Event()
def socket_handler(listener):
for i in 0, 1:
sock = listener.accept()[0]
buf = b''
while not buf.endswith(b'\r\n\r\n'):
buf = sock.recv(65536)
body = 'Response %d' % i
sock.send(('HTTP/1.1 200 OK\r\n'
'Content-Type: text/plain\r\n'
'Content-Length: %d\r\n'
'\r\n'
'%s' % (len(body), body)).encode('utf-8'))
sock.close() # simulate a server timing out, closing socket
done_closing.set() # let the test know it can proceed
self._start_server(socket_handler)
pool = HTTPConnectionPool(self.host, self.port)
response = pool.request('GET', '/', retries=0)
self.assertEqual(response.status, 200)
self.assertEqual(response.data, b'Response 0')
done_closing.wait() # wait until the socket in our pool gets closed
response = pool.request('GET', '/', retries=0)
self.assertEqual(response.status, 200)
self.assertEqual(response.data, b'Response 1')
def test_connection_refused(self):
# Does the pool retry if there is no listener on the port?
# Note: Socket server is not started until after the test.
pool = HTTPConnectionPool(self.host, self.port)
self.assertRaises(MaxRetryError, pool.request, 'GET', '/', retries=0)
self._start_server(lambda x: None)
def test_connection_timeout(self):
timed_out = Event()
def socket_handler(listener):
timed_out.wait()
sock = listener.accept()[0]
sock.close()
self._start_server(socket_handler)
pool = HTTPConnectionPool(self.host, self.port, timeout=0.001)
self.assertRaises(TimeoutError, pool.request, 'GET', '/', retries=0)
timed_out.set()
class TestProxyManager(SocketDummyServerTestCase):
def test_simple(self):
base_url = 'http://%s:%d' % (self.host, self.port)
proxy = proxy_from_url(base_url)
def echo_socket_handler(listener):
sock = listener.accept()[0]
buf = b''
while not buf.endswith(b'\r\n\r\n'):
buf += sock.recv(65536)
sock.send(('HTTP/1.1 200 OK\r\n'
'Content-Type: text/plain\r\n'
'Content-Length: %d\r\n'
'\r\n'
'%s' % (len(buf), buf.decode('utf-8'))).encode('utf-8'))
self._start_server(echo_socket_handler)
r = proxy.request('GET', 'http://google.com/')
self.assertEqual(r.status, 200)
# FIXME: The order of the headers is not predictable right now. We
# should fix that someday (maybe when we migrate to
# OrderedDict/MultiDict).
self.assertEqual(sorted(r.data.split(b'\r\n')),
sorted([
b'GET http://google.com/ HTTP/1.1',
b'Host: google.com',
b'Accept-Encoding: identity',
b'Accept: */*',
b'',
b'',
]))