381d51cb3d6969f60eb8ae9544935ec46cb05886
[packages/trusty/python-eventlet.git] / python-eventlet / tests / websocket_new_test.py
1 import errno
2 import struct
3
4 import eventlet
5 from eventlet import event
6 from eventlet import websocket
7 from eventlet.green import httplib
8 from eventlet.green import socket
9 from eventlet.support import six
10
11 from tests.wsgi_test import _TestBase
12
13
14 # demo app
15 def handle(ws):
16     if ws.path == '/echo':
17         while True:
18             m = ws.wait()
19             if m is None:
20                 break
21             ws.send(m)
22     elif ws.path == '/range':
23         for i in range(10):
24             ws.send("msg %d" % i)
25             eventlet.sleep(0.01)
26     elif ws.path == '/error':
27         # some random socket error that we shouldn't normally get
28         raise socket.error(errno.ENOTSOCK)
29     else:
30         ws.close()
31
32 wsapp = websocket.WebSocketWSGI(handle)
33
34
35 class TestWebSocket(_TestBase):
36     TEST_TIMEOUT = 5
37
38     def set_site(self):
39         self.site = wsapp
40
41     def test_incomplete_headers_13(self):
42         headers = dict(kv.split(': ') for kv in [
43             "Upgrade: websocket",
44             # NOTE: intentionally no connection header
45             "Host: localhost:%s" % self.port,
46             "Origin: http://localhost:%s" % self.port,
47             "Sec-WebSocket-Version: 13",
48         ])
49         http = httplib.HTTPConnection('localhost', self.port)
50         http.request("GET", "/echo", headers=headers)
51         resp = http.getresponse()
52
53         self.assertEqual(resp.status, 400)
54         self.assertEqual(resp.getheader('connection'), 'close')
55         self.assertEqual(resp.read(), b'')
56
57         # Now, miss off key
58         headers = dict(kv.split(': ') for kv in [
59             "Upgrade: websocket",
60             "Connection: Upgrade",
61             "Host: localhost:%s" % self.port,
62             "Origin: http://localhost:%s" % self.port,
63             "Sec-WebSocket-Version: 13",
64         ])
65         http = httplib.HTTPConnection('localhost', self.port)
66         http.request("GET", "/echo", headers=headers)
67         resp = http.getresponse()
68
69         self.assertEqual(resp.status, 400)
70         self.assertEqual(resp.getheader('connection'), 'close')
71         self.assertEqual(resp.read(), b'')
72
73         # No Upgrade now
74         headers = dict(kv.split(': ') for kv in [
75             "Connection: Upgrade",
76             "Host: localhost:%s" % self.port,
77             "Origin: http://localhost:%s" % self.port,
78             "Sec-WebSocket-Version: 13",
79         ])
80         http = httplib.HTTPConnection('localhost', self.port)
81         http.request("GET", "/echo", headers=headers)
82         resp = http.getresponse()
83
84         self.assertEqual(resp.status, 400)
85         self.assertEqual(resp.getheader('connection'), 'close')
86         self.assertEqual(resp.read(), b'')
87
88     def test_correct_upgrade_request_13(self):
89         for http_connection in ['Upgrade', 'UpGrAdE', 'keep-alive, Upgrade']:
90             connect = [
91                 "GET /echo HTTP/1.1",
92                 "Upgrade: websocket",
93                 "Connection: %s" % http_connection,
94                 "Host: localhost:%s" % self.port,
95                 "Origin: http://localhost:%s" % self.port,
96                 "Sec-WebSocket-Version: 13",
97                 "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
98             ]
99             sock = eventlet.connect(('localhost', self.port))
100
101             sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
102             result = sock.recv(1024)
103             # The server responds the correct Websocket handshake
104             print('Connection string: %r' % http_connection)
105             self.assertEqual(result, six.b('\r\n'.join([
106                 'HTTP/1.1 101 Switching Protocols',
107                 'Upgrade: websocket',
108                 'Connection: Upgrade',
109                 'Sec-WebSocket-Accept: ywSyWXCPNsDxLrQdQrn5RFNRfBU=\r\n\r\n',
110             ])))
111
112     def test_send_recv_13(self):
113         connect = [
114             "GET /echo HTTP/1.1",
115             "Upgrade: websocket",
116             "Connection: Upgrade",
117             "Host: localhost:%s" % self.port,
118             "Origin: http://localhost:%s" % self.port,
119             "Sec-WebSocket-Version: 13",
120             "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
121         ]
122         sock = eventlet.connect(
123             ('localhost', self.port))
124
125         sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
126         sock.recv(1024)
127         ws = websocket.RFC6455WebSocket(sock, {}, client=True)
128         ws.send(b'hello')
129         assert ws.wait() == b'hello'
130         ws.send(b'hello world!\x01')
131         ws.send(u'hello world again!')
132         assert ws.wait() == b'hello world!\x01'
133         assert ws.wait() == u'hello world again!'
134         ws.close()
135         eventlet.sleep(0.01)
136
137     def test_breaking_the_connection_13(self):
138         error_detected = [False]
139         done_with_request = event.Event()
140         site = self.site
141
142         def error_detector(environ, start_response):
143             try:
144                 try:
145                     return site(environ, start_response)
146                 except:
147                     error_detected[0] = True
148                     raise
149             finally:
150                 done_with_request.send(True)
151         self.site = error_detector
152         self.spawn_server()
153         connect = [
154             "GET /echo HTTP/1.1",
155             "Upgrade: websocket",
156             "Connection: Upgrade",
157             "Host: localhost:%s" % self.port,
158             "Origin: http://localhost:%s" % self.port,
159             "Sec-WebSocket-Version: 13",
160             "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
161         ]
162         sock = eventlet.connect(
163             ('localhost', self.port))
164         sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
165         sock.recv(1024)  # get the headers
166         sock.close()  # close while the app is running
167         done_with_request.wait()
168         assert not error_detected[0]
169
170     def test_client_closing_connection_13(self):
171         error_detected = [False]
172         done_with_request = event.Event()
173         site = self.site
174
175         def error_detector(environ, start_response):
176             try:
177                 try:
178                     return site(environ, start_response)
179                 except:
180                     error_detected[0] = True
181                     raise
182             finally:
183                 done_with_request.send(True)
184         self.site = error_detector
185         self.spawn_server()
186         connect = [
187             "GET /echo HTTP/1.1",
188             "Upgrade: websocket",
189             "Connection: Upgrade",
190             "Host: localhost:%s" % self.port,
191             "Origin: http://localhost:%s" % self.port,
192             "Sec-WebSocket-Version: 13",
193             "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
194         ]
195         sock = eventlet.connect(
196             ('localhost', self.port))
197         sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
198         sock.recv(1024)  # get the headers
199         closeframe = struct.pack('!BBIH', 1 << 7 | 8, 1 << 7 | 2, 0, 1000)
200         sock.sendall(closeframe)  # "Close the connection" packet.
201         done_with_request.wait()
202         assert not error_detected[0]
203
204     def test_client_invalid_packet_13(self):
205         error_detected = [False]
206         done_with_request = event.Event()
207         site = self.site
208
209         def error_detector(environ, start_response):
210             try:
211                 try:
212                     return site(environ, start_response)
213                 except:
214                     error_detected[0] = True
215                     raise
216             finally:
217                 done_with_request.send(True)
218         self.site = error_detector
219         self.spawn_server()
220         connect = [
221             "GET /echo HTTP/1.1",
222             "Upgrade: websocket",
223             "Connection: Upgrade",
224             "Host: localhost:%s" % self.port,
225             "Origin: http://localhost:%s" % self.port,
226             "Sec-WebSocket-Version: 13",
227             "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
228         ]
229         sock = eventlet.connect(
230             ('localhost', self.port))
231         sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
232         sock.recv(1024)  # get the headers
233         sock.sendall(b'\x07\xff')  # Weird packet.
234         done_with_request.wait()
235         assert not error_detected[0]