def test_correct_upgrade_request_76(self): connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(("localhost", self.port)) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U")) result = sock.recv(1024) # The server responds the correct Websocket handshake self.assertEqual( result, six.b( "\r\n".join( [ "HTTP/1.1 101 WebSocket Protocol Handshake", "Upgrade: WebSocket", "Connection: Upgrade", "Sec-WebSocket-Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Location: ws://localhost:%s/echo\r\n\r\n8jKS'y:G*Co,Wxa-" % self.port, ] ) ), )
def test_correct_upgrade_request_75(self): connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "WebSocket-Protocol: ws", ] sock = eventlet.connect(("localhost", self.port)) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n")) result = sock.recv(1024) # The server responds the correct Websocket handshake self.assertEqual( result, six.b( "\r\n".join( [ "HTTP/1.1 101 Web Socket Protocol Handshake", "Upgrade: WebSocket", "Connection: Upgrade", "WebSocket-Origin: http://localhost:%s" % self.port, "WebSocket-Location: ws://localhost:%s/echo\r\n\r\n" % self.port, ] ) ), )
def test_correct_upgrade_request_13(self): for http_connection in ['Upgrade', 'UpGrAdE', 'keep-alive, Upgrade']: connect = [ "GET /echo HTTP/1.1", "Upgrade: websocket", "Connection: %s" % http_connection, "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Version: 13", "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) result = sock.recv(1024) # The server responds the correct Websocket handshake print('Connection string: %r' % http_connection) self.assertEqual( result, six.b('\r\n'.join([ 'HTTP/1.1 101 Switching Protocols', 'Upgrade: websocket', 'Connection: Upgrade', 'Sec-WebSocket-Accept: ywSyWXCPNsDxLrQdQrn5RFNRfBU=\r\n\r\n', ])))
def test_correct_upgrade_request_76(self): connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) result = sock.recv(1024) # The server responds the correct Websocket handshake self.assertEqual( result, six.b('\r\n'.join([ 'HTTP/1.1 101 WebSocket Protocol Handshake', 'Upgrade: WebSocket', 'Connection: Upgrade', 'Sec-WebSocket-Origin: http://%s:%s' % self.server_addr, 'Sec-WebSocket-Protocol: ws', 'Sec-WebSocket-Location: ws://%s:%s/echo\r\n\r\n8jKS\'y:G*Co,Wxa-' % self.server_addr, ])))
def _handle_legacy_request(self, environ): if 'eventlet.input' in environ: sock = environ['eventlet.input'].get_socket() elif 'gunicorn.socket' in environ: sock = environ['gunicorn.socket'] else: raise Exception( 'No eventlet.input or gunicorn.socket present in environ.') if 'HTTP_SEC_WEBSOCKET_KEY1' in environ: self.protocol_version = 76 if 'HTTP_SEC_WEBSOCKET_KEY2' not in environ: raise BadRequest() else: self.protocol_version = 75 if self.protocol_version == 76: key1 = self._extract_number(environ['HTTP_SEC_WEBSOCKET_KEY1']) key2 = self._extract_number(environ['HTTP_SEC_WEBSOCKET_KEY2']) # There's no content-length header in the request, but it has 8 # bytes of data. environ['wsgi.input'].content_length = 8 key3 = environ['wsgi.input'].read(8) key = struct.pack(">II", key1, key2) + key3 response = md5(key).digest() # Start building the response scheme = 'ws' if environ.get('wsgi.url_scheme') == 'https': scheme = 'wss' location = '%s://%s%s%s' % (scheme, environ.get('HTTP_HOST'), environ.get('SCRIPT_NAME'), environ.get('PATH_INFO')) qs = environ.get('QUERY_STRING') if qs is not None: location += '?' + qs if self.protocol_version == 75: handshake_reply = ( b"HTTP/1.1 101 Web Socket Protocol Handshake\r\n" b"Upgrade: WebSocket\r\n" b"Connection: Upgrade\r\n" b"WebSocket-Origin: " + six.b(environ.get('HTTP_ORIGIN')) + b"\r\n" b"WebSocket-Location: " + six.b(location) + b"\r\n\r\n") elif self.protocol_version == 76: handshake_reply = ( b"HTTP/1.1 101 WebSocket Protocol Handshake\r\n" b"Upgrade: WebSocket\r\n" b"Connection: Upgrade\r\n" b"Sec-WebSocket-Origin: " + six.b(environ.get('HTTP_ORIGIN')) + b"\r\n" b"Sec-WebSocket-Protocol: " + six.b(environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL', 'default')) + b"\r\n" b"Sec-WebSocket-Location: " + six.b(location) + b"\r\n" b"\r\n" + response) else: # pragma NO COVER raise ValueError("Unknown WebSocket protocol version.") sock.sendall(handshake_reply) return WebSocket(sock, environ, self.protocol_version)
def test_empty_query_string(self): # verify that a single trailing ? doesn't get nuked connect = [ "GET /echo? HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(("localhost", self.port)) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U")) result = sock.recv(1024) self.assertEqual( result, six.b( "\r\n".join( [ "HTTP/1.1 101 WebSocket Protocol Handshake", "Upgrade: WebSocket", "Connection: Upgrade", "Sec-WebSocket-Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Location: ws://localhost:%s/echo?\r\n\r\n8jKS'y:G*Co,Wxa-" % self.port, ] ) ), )
def test_empty_query_string(self): # verify that a single trailing ? doesn't get nuked connect = [ "GET /echo? HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) result = sock.recv(1024) self.assertEqual( result, six.b('\r\n'.join([ 'HTTP/1.1 101 WebSocket Protocol Handshake', 'Upgrade: WebSocket', 'Connection: Upgrade', 'Sec-WebSocket-Origin: http://%s:%s' % self.server_addr, 'Sec-WebSocket-Protocol: ws', 'Sec-WebSocket-Location: ws://%s:%s/echo?\r\n\r\n8jKS\'y:G*Co,Wxa-' % self.server_addr, ])))
def test_query_string(self): # verify that the query string comes out the other side unscathed connect = [ "GET /echo?query_string HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(('localhost', self.port)) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) result = sock.recv(1024) self.assertEqual( result, six.b('\r\n'.join([ 'HTTP/1.1 101 WebSocket Protocol Handshake', 'Upgrade: WebSocket', 'Connection: Upgrade', 'Sec-WebSocket-Origin: http://localhost:%s' % self.port, 'Sec-WebSocket-Protocol: ws', 'Sec-WebSocket-Location: ' 'ws://localhost:%s/echo?query_string\r\n\r\n8jKS\'y:G*Co,Wxa-' % self.port, ])))
def test_query_string(self): # verify that the query string comes out the other side unscathed connect = [ "GET /echo?query_string HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U")) result = sock.recv(1024) self.assertEqual( result, six.b( "\r\n".join( [ "HTTP/1.1 101 WebSocket Protocol Handshake", "Upgrade: WebSocket", "Connection: Upgrade", "Sec-WebSocket-Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Location: " "ws://%s:%s/echo?query_string\r\n\r\n8jKS'y:G*Co,Wxa-" % self.server_addr, ] ) ), )
def write(data): towrite = [] if not headers_set: raise AssertionError("write() before start_response()") elif not headers_sent: status, response_headers = headers_set headers_sent.append(1) header_list = [ header[0].lower() for header in response_headers ] towrite.append( six.b('%s %s\r\n' % (self.protocol_version, status))) for header in response_headers: towrite.append(six.b('%s: %s\r\n' % header)) # send Date header? if 'date' not in header_list: towrite.append( six.b('Date: %s\r\n' % (format_date_time(time.time()), ))) client_conn = self.headers.get('Connection', '').lower() send_keep_alive = False if self.close_connection == 0 and \ self.server.keepalive and (client_conn == 'keep-alive' or (self.request_version == 'HTTP/1.1' and not client_conn == 'close')): # only send keep-alives back to clients that sent them, # it's redundant for 1.1 connections send_keep_alive = (client_conn == 'keep-alive') self.close_connection = 0 else: self.close_connection = 1 if 'content-length' not in header_list: if self.request_version == 'HTTP/1.1': use_chunked[0] = True towrite.append(b'Transfer-Encoding: chunked\r\n') elif 'content-length' not in header_list: # client is 1.0 and therefore must read to EOF self.close_connection = 1 if self.close_connection: towrite.append(b'Connection: close\r\n') elif send_keep_alive: towrite.append(b'Connection: keep-alive\r\n') towrite.append(b'\r\n') # end of header writing if use_chunked[0]: # Write the chunked encoding towrite.append( six.b("%x" % (len(data), )) + b"\r\n" + data + b"\r\n") else: towrite.append(data) wfile.writelines(towrite) wfile.flush() length[0] = length[0] + sum(map(len, towrite))
def _handle_legacy_request(self, environ): sock = environ['eventlet.input'].get_socket() if 'HTTP_SEC_WEBSOCKET_KEY1' in environ: self.protocol_version = 76 if 'HTTP_SEC_WEBSOCKET_KEY2' not in environ: raise BadRequest() else: self.protocol_version = 75 if self.protocol_version == 76: key1 = self._extract_number(environ['HTTP_SEC_WEBSOCKET_KEY1']) key2 = self._extract_number(environ['HTTP_SEC_WEBSOCKET_KEY2']) # There's no content-length header in the request, but it has 8 # bytes of data. environ['wsgi.input'].content_length = 8 key3 = environ['wsgi.input'].read(8) key = struct.pack(">II", key1, key2) + key3 response = md5(key).digest() # Start building the response scheme = 'ws' if environ.get('wsgi.url_scheme') == 'https': scheme = 'wss' location = '%s://%s%s%s' % ( scheme, environ.get('HTTP_HOST'), environ.get('SCRIPT_NAME'), environ.get('PATH_INFO') ) qs = environ.get('QUERY_STRING') if qs is not None: location += '?' + qs if self.protocol_version == 75: handshake_reply = ( b"HTTP/1.1 101 Web Socket Protocol Handshake\r\n" b"Upgrade: WebSocket\r\n" b"Connection: Upgrade\r\n" b"WebSocket-Origin: " + six.b(environ.get('HTTP_ORIGIN')) + b"\r\n" b"WebSocket-Location: " + six.b(location) + b"\r\n\r\n" ) elif self.protocol_version == 76: handshake_reply = ( b"HTTP/1.1 101 WebSocket Protocol Handshake\r\n" b"Upgrade: WebSocket\r\n" b"Connection: Upgrade\r\n" b"Sec-WebSocket-Origin: " + six.b(environ.get('HTTP_ORIGIN')) + b"\r\n" b"Sec-WebSocket-Protocol: " + six.b(environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL', 'default')) + b"\r\n" b"Sec-WebSocket-Location: " + six.b(location) + b"\r\n" b"\r\n" + response ) else: # pragma NO COVER raise ValueError("Unknown WebSocket protocol version.") sock.sendall(handshake_reply) return WebSocket(sock, environ, self.protocol_version)
def _handle_hybi_request(self, environ): if 'eventlet.input' in environ: sock = environ['eventlet.input'].get_socket() elif 'gunicorn.socket' in environ: sock = environ['gunicorn.socket'] else: raise Exception('No eventlet.input or gunicorn.socket present in environ.') hybi_version = environ['HTTP_SEC_WEBSOCKET_VERSION'] if hybi_version not in ('8', '13', ): raise BadRequest(status='426 Upgrade Required', headers=[('Sec-WebSocket-Version', '8, 13')]) self.protocol_version = int(hybi_version) if 'HTTP_SEC_WEBSOCKET_KEY' not in environ: # That's bad. raise BadRequest() origin = environ.get( 'HTTP_ORIGIN', (environ.get('HTTP_SEC_WEBSOCKET_ORIGIN', '') if self.protocol_version <= 8 else '')) if self.origin_checker is not None: if not self.origin_checker(environ.get('HTTP_HOST'), origin): raise BadRequest(status='403 Forbidden') protocols = environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL', None) negotiated_protocol = None if protocols: for p in (i.strip() for i in protocols.split(',')): if p in self.supported_protocols: negotiated_protocol = p break key = environ['HTTP_SEC_WEBSOCKET_KEY'] response = base64.b64encode(sha1(six.b(key) + PROTOCOL_GUID).digest()) handshake_reply = [b"HTTP/1.1 101 Switching Protocols", b"Upgrade: websocket", b"Connection: Upgrade", b"Sec-WebSocket-Accept: " + response] if negotiated_protocol: handshake_reply.append(b"Sec-WebSocket-Protocol: " + six.b(negotiated_protocol)) parsed_extensions = {} extensions = self._parse_extension_header(environ.get("HTTP_SEC_WEBSOCKET_EXTENSIONS")) deflate = self._negotiate_permessage_deflate(extensions) if deflate is not None: parsed_extensions["permessage-deflate"] = deflate formatted_ext = self._format_extension_header(parsed_extensions) if formatted_ext is not None: handshake_reply.append(b"Sec-WebSocket-Extensions: " + formatted_ext) sock.sendall(b'\r\n'.join(handshake_reply) + b'\r\n\r\n') return RFC6455WebSocket(sock, environ, self.protocol_version, protocol=negotiated_protocol, extensions=parsed_extensions)
def write(data): towrite = [] if not headers_set: raise AssertionError("write() before start_response()") elif not headers_sent: status, response_headers = headers_set headers_sent.append(1) header_list = [header[0].lower() for header in response_headers] towrite.append(six.b('%s %s\r\n' % (self.protocol_version, status))) for header in response_headers: towrite.append(six.b('%s: %s\r\n' % header)) # send Date header? if 'date' not in header_list: towrite.append(six.b('Date: %s\r\n' % (format_date_time(time.time()),))) client_conn = self.headers.get('Connection', '').lower() send_keep_alive = False if self.close_connection == 0 and \ self.server.keepalive and (client_conn == 'keep-alive' or (self.request_version == 'HTTP/1.1' and not client_conn == 'close')): # only send keep-alives back to clients that sent them, # it's redundant for 1.1 connections send_keep_alive = (client_conn == 'keep-alive') self.close_connection = 0 else: self.close_connection = 1 if 'content-length' not in header_list: if self.request_version == 'HTTP/1.1': use_chunked[0] = True towrite.append(b'Transfer-Encoding: chunked\r\n') elif 'content-length' not in header_list: # client is 1.0 and therefore must read to EOF self.close_connection = 1 if self.close_connection: towrite.append(b'Connection: close\r\n') elif send_keep_alive: towrite.append(b'Connection: keep-alive\r\n') towrite.append(b'\r\n') # end of header writing if use_chunked[0]: # Write the chunked encoding towrite.append(six.b("%x" % (len(data),)) + b"\r\n" + data + b"\r\n") else: towrite.append(data) wfile.writelines(towrite) wfile.flush() length[0] = length[0] + sum(map(len, towrite))
def _format_extension_header(self, parsed_extensions): if not parsed_extensions: return None parts = [] for name, config in parsed_extensions.items(): ext_parts = [six.b(name)] for key, value in config.items(): if value is False: pass elif value is True: ext_parts.append(six.b(key)) else: ext_parts.append(six.b("%s=%s" % (key, str(value)))) parts.append(b"; ".join(ext_parts)) return b", ".join(parts)
def test_sending_messages_to_websocket_76(self): connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) sock.recv(1024) sock.sendall(b'\x00hello\xFF') result = sock.recv(1024) self.assertEqual(result, b'\x00hello\xff') sock.sendall(b'\x00start') eventlet.sleep(0.001) sock.sendall(b' end\xff') result = sock.recv(1024) self.assertEqual(result, b'\x00start end\xff') sock.shutdown(socket.SHUT_RDWR) sock.close() eventlet.sleep(0.01)
def test_app_socket_errors_75(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /error HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "WebSocket-Protocol: ws", ] sock = eventlet.connect(('localhost', self.port)) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) sock.recv(1024) done_with_request.wait() assert error_detected[0]
def test_client_invalid_packet_76(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(('localhost', self.port)) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) sock.recv(1024) # get the headers sock.sendall(b'\xef\x00') # Weird packet. done_with_request.wait() assert error_detected[0]
def test_accept_deflate_ext_window_max_bits_13(self): for extension_string, vals in [ ('permessage-deflate; client_max_window_bits', [15]), ('permessage-deflate; Server_Max_Window_Bits = 11', [11]), ('permessage-deflate; server_max_window_bits; ' 'client_max_window_bits=9', [15, 9]) ]: sock = eventlet.connect(self.server_addr) sock.sendall(six.b(self.connect % extension_string)) result = sock.recv(1024) # The server responds the correct Websocket handshake # print('Extension offer: %r' % extension_string) match = re.match(self.handshake_re, result) assert match is not None assert len(match.groups()) == 1 offered_parts = [ part.strip().lower() for part in extension_string.split(';') ] offered_parts_names = [ part.split('=')[0].strip() for part in offered_parts ] offered_parts_dict = dict(zip(offered_parts_names[1:], vals)) accepted_ext_parts = match.groups()[0].decode().split('; ') assert accepted_ext_parts[0] == 'permessage-deflate' for param, val in (part.split('=') for part in accepted_ext_parts[1:]): assert int(val) == offered_parts_dict[param]
def test_server_compress_with_context_takeover_13(self): extensions_string = 'permessage-deflate; client_no_context_takeover;' extensions = { 'permessage-deflate': { 'client_no_context_takeover': True, 'server_no_context_takeover': False } } sock = eventlet.connect(self.server_addr) sock.sendall(six.b(self.connect % extensions_string)) sock.recv(1024) ws = websocket.RFC6455WebSocket(sock, {}, client=True, extensions=extensions) # Deflated values taken from Section 7.2.3 of RFC 7692 # https://tools.ietf.org/html/rfc7692#section-7.2.3 ws.send(b'Hello') msg1 = self.get_deflated_reply(ws) assert msg1 == b'\xf2\x48\xcd\xc9\xc9\x07\x00' ws.send(b'Hello') msg2 = self.get_deflated_reply(ws) assert msg2 == b'\xf2\x00\x11\x00\x00' ws.close() eventlet.sleep(0.01)
def test_server_compress_no_context_takeover_13(self): extensions_string = 'permessage-deflate; server_no_context_takeover;' extensions = { 'permessage-deflate': { 'client_no_context_takeover': False, 'server_no_context_takeover': True } } sock = eventlet.connect(self.server_addr) sock.sendall(six.b(self.connect % extensions_string)) sock.recv(1024) ws = websocket.RFC6455WebSocket(sock, {}, client=True, extensions=extensions) masked_msg1 = ws._pack_message(b'Hello', masked=True) ws._send(masked_msg1) masked_msg2 = ws._pack_message(b'Hello', masked=True) ws._send(masked_msg2) # Verify that client uses context takeover by checking # that the second message assert len(masked_msg2) < len(masked_msg1) # Verify that server drops context between messages # Deflated values taken from Section 7.2.3 of RFC 7692 # https://tools.ietf.org/html/rfc7692#section-7.2.3 reply_msg1 = self.get_deflated_reply(ws) assert reply_msg1 == b'\xf2\x48\xcd\xc9\xc9\x07\x00' reply_msg2 = self.get_deflated_reply(ws) assert reply_msg2 == b'\xf2\x48\xcd\xc9\xc9\x07\x00'
def test_breaking_the_connection_76(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /range HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U")) sock.recv(1024) # get the headers sock.close() # close while the app is running done_with_request.wait() assert not error_detected[0]
def test_compressed_send_recv_both_no_context_13(self): extensions_string = ( 'permessage-deflate;' ' server_no_context_takeover; client_no_context_takeover') extensions = { 'permessage-deflate': { 'client_no_context_takeover': True, 'server_no_context_takeover': True } } sock = eventlet.connect(self.server_addr) sock.sendall(six.b(self.connect % extensions_string)) sock.recv(1024) ws = websocket.RFC6455WebSocket(sock, {}, client=True, extensions=extensions) ws.send(b'hello') assert ws.wait() == b'hello' ws.send(b'hello world!') ws.send(u'hello world again!') assert ws.wait() == b'hello world!' assert ws.wait() == u'hello world again!' ws.close() eventlet.sleep(0.01)
def test_breaking_the_connection_75(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /range HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "WebSocket-Protocol: ws", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) sock.recv(1024) # get the headers sock.close() # close while the app is running done_with_request.wait() assert not error_detected[0]
def test_sending_messages_to_websocket_76(self): connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U")) sock.recv(1024) sock.sendall(b"\x00hello\xFF") result = sock.recv(1024) self.assertEqual(result, b"\x00hello\xff") sock.sendall(b"\x00start") eventlet.sleep(0.001) sock.sendall(b" end\xff") result = sock.recv(1024) self.assertEqual(result, b"\x00start end\xff") sock.shutdown(socket.SHUT_RDWR) sock.close() eventlet.sleep(0.01)
def test_app_socket_errors_76(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /error HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) sock.recv(1024) done_with_request.wait() assert error_detected[0]
def test_client_closing_connection_13(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /echo HTTP/1.1", "Upgrade: websocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Version: 13", "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) sock.recv(1024) # get the headers closeframe = struct.pack('!BBIH', 1 << 7 | 8, 1 << 7 | 2, 0, 1000) sock.sendall(closeframe) # "Close the connection" packet. done_with_request.wait() assert not error_detected[0]
def test_client_closing_connection_13(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /echo HTTP/1.1", "Upgrade: websocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Version: 13", "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==", ] sock = eventlet.connect(('localhost', self.port)) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) sock.recv(1024) # get the headers closeframe = struct.pack('!BBIH', 1 << 7 | 8, 1 << 7 | 2, 0, 1000) sock.sendall(closeframe) # "Close the connection" packet. done_with_request.wait() assert not error_detected[0]
def test_breaking_the_connection_75(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /range HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "WebSocket-Protocol: ws", ] sock = eventlet.connect( ('localhost', self.port)) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) sock.recv(1024) # get the headers sock.close() # close while the app is running done_with_request.wait() assert not error_detected[0]
def test_client_invalid_packet_76(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(("localhost", self.port)) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U")) sock.recv(1024) # get the headers sock.sendall(b"\xef\x00") # Weird packet. done_with_request.wait() assert error_detected[0]
def test_query_string(self): # verify that the query string comes out the other side unscathed connect = [ "GET /echo?query_string HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect( ('localhost', self.port)) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) result = sock.recv(1024) self.assertEqual(result, '\r\n'.join([ 'HTTP/1.1 101 WebSocket Protocol Handshake', 'Upgrade: WebSocket', 'Connection: Upgrade', 'Sec-WebSocket-Origin: http://localhost:%s' % self.port, 'Sec-WebSocket-Protocol: ws', 'Sec-WebSocket-Location: ' 'ws://localhost:%s/echo?query_string\r\n\r\n8jKS\'y:G*Co,Wxa-' % self.port, ]))
def test_client_invalid_packet_13(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /echo HTTP/1.1", "Upgrade: websocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Version: 13", "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==", ] sock = eventlet.connect( ('localhost', self.port)) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) sock.recv(1024) # get the headers sock.sendall(b'\x07\xff') # Weird packet. done_with_request.wait() assert not error_detected[0]
def test_app_socket_errors_76(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /error HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect( ('localhost', self.port)) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) sock.recv(1024) done_with_request.wait() assert error_detected[0]
def test_breaking_the_connection_13(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /echo HTTP/1.1", "Upgrade: websocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Version: 13", "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) sock.recv(1024) # get the headers sock.close() # close while the app is running done_with_request.wait() assert not error_detected[0]
def test_client_invalid_packet_13(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /echo HTTP/1.1", "Upgrade: websocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Version: 13", "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) sock.recv(1024) # get the headers sock.sendall(b'\x07\xff') # Weird packet. done_with_request.wait() assert not error_detected[0]
def test_app_socket_errors_75(self): error_detected = [False] done_with_request = event.Event() site = self.site def error_detector(environ, start_response): try: try: return site(environ, start_response) except: error_detected[0] = True raise finally: done_with_request.send(True) self.site = error_detector self.spawn_server() connect = [ "GET /error HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "WebSocket-Protocol: ws", ] sock = eventlet.connect(("localhost", self.port)) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n")) sock.recv(1024) done_with_request.wait() assert error_detected[0]
def test_sending_messages_to_websocket_76(self): connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect( ('localhost', self.port)) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) sock.recv(1024) sock.sendall(b'\x00hello\xFF') result = sock.recv(1024) self.assertEqual(result, b'\x00hello\xff') sock.sendall(b'\x00start') eventlet.sleep(0.001) sock.sendall(b' end\xff') result = sock.recv(1024) self.assertEqual(result, b'\x00start end\xff') sock.shutdown(socket.SHUT_RDWR) sock.close() eventlet.sleep(0.01)
def _handle_hybi_request(self, environ): if 'eventlet.input' in environ: sock = environ['eventlet.input'].get_socket() elif 'gunicorn.socket' in environ: sock = environ["gunicorn.socket"] else: raise Exception("No eventlet.input or gunicorn.socket present in environ. No where from to take socket.") hybi_version = environ['HTTP_SEC_WEBSOCKET_VERSION'] if hybi_version not in ('8', '13', ): raise BadRequest(status='426 Upgrade Required', headers=[('Sec-WebSocket-Version', '8, 13')]) self.protocol_version = int(hybi_version) if 'HTTP_SEC_WEBSOCKET_KEY' not in environ: # That's bad. raise BadRequest() origin = environ.get( 'HTTP_ORIGIN', (environ.get('HTTP_SEC_WEBSOCKET_ORIGIN', '') if self.protocol_version <= 8 else '')) if self.origin_checker is not None: if not self.origin_checker(environ.get('HTTP_HOST'), origin): raise BadRequest(status='403 Forbidden') protocols = environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL', None) negotiated_protocol = None if protocols: for p in (i.strip() for i in protocols.split(',')): if p in self.supported_protocols: negotiated_protocol = p break # extensions = environ.get('HTTP_SEC_WEBSOCKET_EXTENSIONS', None) # if extensions: # extensions = [i.strip() for i in extensions.split(',')] key = environ['HTTP_SEC_WEBSOCKET_KEY'] response = base64.b64encode(sha1(six.b(key) + PROTOCOL_GUID).digest()) handshake_reply = [b"HTTP/1.1 101 Switching Protocols", b"Upgrade: websocket", b"Connection: Upgrade", b"Sec-WebSocket-Accept: " + response] if negotiated_protocol: handshake_reply.append(b"Sec-WebSocket-Protocol: " + six.b(negotiated_protocol)) sock.sendall(b'\r\n'.join(handshake_reply) + b'\r\n\r\n') return RFC6455WebSocket(sock, environ, self.protocol_version, protocol=negotiated_protocol)
def _handle_hybi_request(self, environ): sock = environ['eventlet.input'].get_socket() hybi_version = environ['HTTP_SEC_WEBSOCKET_VERSION'] if hybi_version not in ( '8', '13', ): raise BadRequest(status='426 Upgrade Required', headers=[('Sec-WebSocket-Version', '8, 13')]) self.protocol_version = int(hybi_version) if 'HTTP_SEC_WEBSOCKET_KEY' not in environ: # That's bad. raise BadRequest() origin = environ.get('HTTP_ORIGIN', (environ.get('HTTP_SEC_WEBSOCKET_ORIGIN', '') if self.protocol_version <= 8 else '')) if self.origin_checker is not None: if not self.origin_checker(environ.get('HTTP_HOST'), origin): raise BadRequest(status='403 Forbidden') protocols = environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL', None) negotiated_protocol = None if protocols: for p in (i.strip() for i in protocols.split(',')): if p in self.supported_protocols: negotiated_protocol = p break # extensions = environ.get('HTTP_SEC_WEBSOCKET_EXTENSIONS', None) # if extensions: # extensions = [i.strip() for i in extensions.split(',')] key = environ['HTTP_SEC_WEBSOCKET_KEY'] response = base64.b64encode(sha1(six.b(key) + PROTOCOL_GUID).digest()) handshake_reply = [ b"HTTP/1.1 101 Switching Protocols", b"Upgrade: websocket", b"Connection: Upgrade", b"Sec-WebSocket-Accept: " + response ] if negotiated_protocol: handshake_reply.append(b"Sec-WebSocket-Protocol: " + six.b(negotiated_protocol)) sock.sendall(b'\r\n'.join(handshake_reply) + b'\r\n\r\n') return RFC6455WebSocket(sock, environ, self.protocol_version, protocol=negotiated_protocol)
def _pack_message(message): """Pack the message inside ``00`` and ``FF`` As per the dataframing section (5.3) for the websocket spec """ if isinstance(message, six.text_type): message = message.encode('utf-8') elif not isinstance(message, six.binary_type): message = six.b(str(message)) packed = b"\x00" + message + b"\xFF" return packed
def test_getting_messages_from_websocket_75(self): connect = [ "GET /range HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "WebSocket-Protocol: ws", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) resp = sock.recv(1024) headers, result = resp.split(b'\r\n\r\n') msgs = [result.strip(b'\x00\xff')] cnt = 10 while cnt: msgs.append(sock.recv(20).strip(b'\x00\xff')) cnt -= 1 # Last item in msgs is an empty string self.assertEqual(msgs[:-1], [six.b('msg %d' % i) for i in range(10)])
def test_getting_messages_from_websocket_75(self): connect = [ "GET /range HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "WebSocket-Protocol: ws", ] sock = eventlet.connect(("localhost", self.port)) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n")) resp = sock.recv(1024) headers, result = resp.split(b"\r\n\r\n") msgs = [result.strip(b"\x00\xff")] cnt = 10 while cnt: msgs.append(sock.recv(20).strip(b"\x00\xff")) cnt -= 1 # Last item in msgs is an empty string self.assertEqual(msgs[:-1], [six.b("msg %d" % i) for i in range(10)])
def test_getting_messages_from_websocket_76(self): connect = [ "GET /range HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U")) resp = sock.recv(1024) headers, result = resp.split(b"\r\n\r\n") msgs = [result[16:].strip(b"\x00\xff")] cnt = 10 while cnt: msgs.append(sock.recv(20).strip(b"\x00\xff")) cnt -= 1 # Last item in msgs is an empty string self.assertEqual(msgs[:-1], [six.b("msg %d" % i) for i in range(10)])
def test_correct_upgrade_request_13(self): for http_connection in ['Upgrade', 'UpGrAdE', 'keep-alive, Upgrade']: connect = [ "GET /echo HTTP/1.1", "Upgrade: websocket", "Connection: %s" % http_connection, "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Version: 13", "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==", ] sock = eventlet.connect(('localhost', self.port)) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) result = sock.recv(1024) # The server responds the correct Websocket handshake print('Connection string: %r' % http_connection) self.assertEqual(result, six.b('\r\n'.join([ 'HTTP/1.1 101 Switching Protocols', 'Upgrade: websocket', 'Connection: Upgrade', 'Sec-WebSocket-Accept: ywSyWXCPNsDxLrQdQrn5RFNRfBU=\r\n\r\n', ])))
def test_getting_messages_from_websocket_76(self): connect = [ "GET /range HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(('localhost', self.port)) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) resp = sock.recv(1024) headers, result = resp.split(b'\r\n\r\n') msgs = [result[16:].strip(b'\x00\xff')] cnt = 10 while cnt: msgs.append(sock.recv(20).strip(b'\x00\xff')) cnt -= 1 # Last item in msgs is an empty string self.assertEqual(msgs[:-1], [six.b('msg %d' % i) for i in range(10)])
def test_accept_basic_deflate_ext_13(self): for extension in [ 'permessage-deflate', 'PeRMessAGe-dEFlaTe', ]: sock = eventlet.connect(self.server_addr) sock.sendall(six.b(self.connect % extension)) result = sock.recv(1024) # The server responds the correct Websocket handshake # print('Extension offer: %r' % extension) match = re.match(self.handshake_re, result) assert match is not None assert len(match.groups()) == 1
def test_reject_max_window_bits_out_of_range_13(self): extension_string = ('permessage-deflate; client_max_window_bits=7,' 'permessage-deflate; server_max_window_bits=16, ' 'permessage-deflate; client_max_window_bits=16; ' 'server_max_window_bits=7, ' 'permessage-deflate') sock = eventlet.connect(self.server_addr) sock.sendall(six.b(self.connect % extension_string)) result = sock.recv(1024) # The server responds the correct Websocket handshake # print('Extension offer: %r' % extension_string) match = re.match(self.handshake_re, result) assert match.groups()[0] == b'permessage-deflate'
def test_correct_upgrade_request_75(self): connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "WebSocket-Protocol: ws", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) result = sock.recv(1024) # The server responds the correct Websocket handshake self.assertEqual( result, six.b('\r\n'.join([ 'HTTP/1.1 101 Web Socket Protocol Handshake', 'Upgrade: WebSocket', 'Connection: Upgrade', 'WebSocket-Origin: http://%s:%s' % self.server_addr, 'WebSocket-Location: ws://%s:%s/echo\r\n\r\n' % self.server_addr, ])))
def test_server_closing_connect_76(self): connect = [ "GET / HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U")) resp = sock.recv(1024) headers, result = resp.split(b"\r\n\r\n") # The remote server should have immediately closed the connection. self.assertEqual(result[16:], b"\xff\x00")
def test_server_closing_connect_76(self): connect = [ "GET / HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) resp = sock.recv(1024) headers, result = resp.split(b'\r\n\r\n') # The remote server should have immediately closed the connection. self.assertEqual(result[16:], b'\xff\x00')
def _send_hundred_continue_response(self): towrite = [] # 100 Continue status line towrite.append(self.wfile_line) # Optional headers if self.hundred_continue_headers is not None: # 100 Continue headers for header in self.hundred_continue_headers: towrite.append(six.b('%s: %s\r\n' % header)) # Blank line towrite.append(b'\r\n') self.wfile.writelines(towrite) self.wfile = None self.wfile_line = None
def send_hundred_continue_response(self): towrite = [] # 100 Continue status line towrite.append(self.wfile_line) # Optional headers if self.hundred_continue_headers is not None: # 100 Continue headers for header in self.hundred_continue_headers: towrite.append(six.b('%s: %s\r\n' % header)) # Blank line towrite.append(b'\r\n') self.wfile.writelines(towrite) # Reinitialize chunk_length (expect more data) self.chunk_length = -1
def test_ssl_sending_messages(self): s = eventlet.wrap_ssl(eventlet.listen(('localhost', 0)), certfile=tests.certificate_file, keyfile=tests.private_key_file, server_side=True) self.spawn_server(sock=s) connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.wrap_ssl(eventlet.connect(self.server_addr)) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) first_resp = b'' while b'\r\n\r\n' not in first_resp: first_resp += sock.recv() print('resp now:') print(first_resp) # make sure it sets the wss: protocol on the location header loc_line = [ x for x in first_resp.split(b"\r\n") if x.lower().startswith(b'sec-websocket-location') ][0] expect_wss = ('wss://%s:%s' % self.server_addr).encode() assert expect_wss in loc_line, "Expecting wss protocol in location: %s" % loc_line sock.sendall(b'\x00hello\xFF') result = sock.recv(1024) self.assertEqual(result, b'\x00hello\xff') sock.sendall(b'\x00start') eventlet.sleep(0.001) sock.sendall(b' end\xff') result = sock.recv(1024) self.assertEqual(result, b'\x00start end\xff') greenio.shutdown_safe(sock) sock.close() eventlet.sleep(0.01)
def test_ssl_sending_messages(self): s = eventlet.wrap_ssl( eventlet.listen(("localhost", 0)), certfile=tests.certificate_file, keyfile=tests.private_key_file, server_side=True, ) self.spawn_server(sock=s) connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.wrap_ssl(eventlet.connect(self.server_addr)) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U")) first_resp = b"" while b"\r\n\r\n" not in first_resp: first_resp += sock.recv() print("resp now:") print(first_resp) # make sure it sets the wss: protocol on the location header loc_line = [x for x in first_resp.split(b"\r\n") if x.lower().startswith(b"sec-websocket-location")][0] expect_wss = ("wss://%s:%s" % self.server_addr).encode() assert expect_wss in loc_line, "Expecting wss protocol in location: %s" % loc_line sock.sendall(b"\x00hello\xFF") result = sock.recv(1024) self.assertEqual(result, b"\x00hello\xff") sock.sendall(b"\x00start") eventlet.sleep(0.001) sock.sendall(b" end\xff") result = sock.recv(1024) self.assertEqual(result, b"\x00start end\xff") greenio.shutdown_safe(sock) sock.close() eventlet.sleep(0.01)
def test_ssl_sending_messages(self): s = eventlet.wrap_ssl(eventlet.listen(('localhost', 0)), certfile=certificate_file, keyfile=private_key_file, server_side=True) self.spawn_server(sock=s) connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "Sec-WebSocket-Protocol: ws", "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5", "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00", ] sock = eventlet.wrap_ssl(eventlet.connect( ('localhost', self.port))) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U')) first_resp = b'' while b'\r\n\r\n' not in first_resp: first_resp += sock.recv() print('resp now:') print(first_resp) # make sure it sets the wss: protocol on the location header loc_line = [x for x in first_resp.split(b"\r\n") if x.lower().startswith(b'sec-websocket-location')][0] self.assert_(b"wss://localhost" in loc_line, "Expecting wss protocol in location: %s" % loc_line) sock.sendall(b'\x00hello\xFF') result = sock.recv(1024) self.assertEqual(result, b'\x00hello\xff') sock.sendall(b'\x00start') eventlet.sleep(0.001) sock.sendall(b' end\xff') result = sock.recv(1024) self.assertEqual(result, b'\x00start end\xff') greenio.shutdown_safe(sock) sock.close() eventlet.sleep(0.01)
def test_send_recv_13(self): connect = [ "GET /echo HTTP/1.1", "Upgrade: websocket", "Connection: Upgrade", "Host: %s:%s" % self.server_addr, "Origin: http://%s:%s" % self.server_addr, "Sec-WebSocket-Version: 13", "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==", ] sock = eventlet.connect(self.server_addr) sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n')) sock.recv(1024) ws = websocket.RFC6455WebSocket(sock, {}, client=True) ws.send(b'hello') assert ws.wait() == b'hello' ws.send(b'hello world!\x01') ws.send(u'hello world again!') assert ws.wait() == b'hello world!\x01' assert ws.wait() == u'hello world again!' ws.close() eventlet.sleep(0.01)
def test_sending_messages_to_websocket_75(self): connect = [ "GET /echo HTTP/1.1", "Upgrade: WebSocket", "Connection: Upgrade", "Host: localhost:%s" % self.port, "Origin: http://localhost:%s" % self.port, "WebSocket-Protocol: ws", ] sock = eventlet.connect(("localhost", self.port)) sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n")) sock.recv(1024) sock.sendall(b"\x00hello\xFF") result = sock.recv(1024) self.assertEqual(result, b"\x00hello\xff") sock.sendall(b"\x00start") eventlet.sleep(0.001) sock.sendall(b" end\xff") result = sock.recv(1024) self.assertEqual(result, b"\x00start end\xff") sock.shutdown(socket.SHUT_RDWR) sock.close() eventlet.sleep(0.01)
def handle_one_response(self): start = time.time() headers_set = [] headers_sent = [] wfile = self.wfile result = None use_chunked = [False] length = [0] status_code = [200] def write(data, _writelines=wfile.writelines): towrite = [] if not headers_set: raise AssertionError("write() before start_response()") elif not headers_sent: status, response_headers = headers_set headers_sent.append(1) header_list = [header[0].lower() for header in response_headers] towrite.append(six.b('%s %s\r\n' % (self.protocol_version, status))) for header in response_headers: towrite.append(six.b('%s: %s\r\n' % header)) # send Date header? if 'date' not in header_list: towrite.append(six.b('Date: %s\r\n' % (format_date_time(time.time()),))) client_conn = self.headers.get('Connection', '').lower() send_keep_alive = False if self.close_connection == 0 and \ self.server.keepalive and (client_conn == 'keep-alive' or (self.request_version == 'HTTP/1.1' and not client_conn == 'close')): # only send keep-alives back to clients that sent them, # it's redundant for 1.1 connections send_keep_alive = (client_conn == 'keep-alive') self.close_connection = 0 else: self.close_connection = 1 if 'content-length' not in header_list: if self.request_version == 'HTTP/1.1': use_chunked[0] = True towrite.append(b'Transfer-Encoding: chunked\r\n') elif 'content-length' not in header_list: # client is 1.0 and therefore must read to EOF self.close_connection = 1 if self.close_connection: towrite.append(b'Connection: close\r\n') elif send_keep_alive: towrite.append(b'Connection: keep-alive\r\n') towrite.append(b'\r\n') # end of header writing if use_chunked[0]: # Write the chunked encoding towrite.append(six.b("%x" % (len(data),)) + b"\r\n" + data + b"\r\n") else: towrite.append(data) _writelines(towrite) length[0] = length[0] + sum(map(len, towrite)) def start_response(status, response_headers, exc_info=None): status_code[0] = status.split()[0] if exc_info: try: if headers_sent: # Re-raise original exception if headers sent six.reraise(exc_info[0], exc_info[1], exc_info[2]) finally: # Avoid dangling circular ref exc_info = None # Response headers capitalization # CONTent-TYpe: TExt/PlaiN -> Content-Type: TExt/PlaiN # Per HTTP RFC standard, header name is case-insensitive. # Please, fix your client to ignore header case if possible. if self.capitalize_response_headers: response_headers = [ ('-'.join([x.capitalize() for x in key.split('-')]), value) for key, value in response_headers] headers_set[:] = [status, response_headers] return write try: try: result = self.application(self.environ, start_response) if (isinstance(result, _AlreadyHandled) or isinstance(getattr(result, '_obj', None), _AlreadyHandled)): self.close_connection = 1 return # Set content-length if possible if not headers_sent and hasattr(result, '__len__') and \ 'Content-Length' not in [h for h, _v in headers_set[1]]: headers_set[1].append(('Content-Length', str(sum(map(len, result))))) towrite = [] towrite_size = 0 just_written_size = 0 minimum_write_chunk_size = int(self.environ.get( 'eventlet.minimum_write_chunk_size', self.minimum_chunk_size)) for data in result: if isinstance(data, six.text_type): data = data.encode('ascii') towrite.append(data) towrite_size += len(data) if towrite_size >= minimum_write_chunk_size: write(b''.join(towrite)) towrite = [] just_written_size = towrite_size towrite_size = 0 if towrite: just_written_size = towrite_size write(b''.join(towrite)) if not headers_sent or (use_chunked[0] and just_written_size): write(b'') except Exception: self.close_connection = 1 tb = traceback.format_exc() self.server.log.info(tb) if not headers_sent: err_body = six.b(tb) if self.server.debug else b'' start_response("500 Internal Server Error", [('Content-type', 'text/plain'), ('Content-length', len(err_body))]) write(err_body) finally: if hasattr(result, 'close'): result.close() if (self.environ['eventlet.input'].chunked_input or self.environ['eventlet.input'].position < (self.environ['eventlet.input'].content_length or 0)): # Read and discard body if there was no pending 100-continue if not self.environ['eventlet.input'].wfile: # NOTE: MINIMUM_CHUNK_SIZE is used here for purpose different than chunking. # We use it only cause it's at hand and has reasonable value in terms of # emptying the buffer. while self.environ['eventlet.input'].read(MINIMUM_CHUNK_SIZE): pass finish = time.time() for hook, args, kwargs in self.environ['eventlet.posthooks']: hook(self.environ, *args, **kwargs) if self.server.log_output: self.server.log.info(self.server.log_format % { 'client_ip': self.get_client_ip(), 'client_port': self.client_address[1], 'date_time': self.log_date_time_string(), 'request_line': self.requestline, 'status_code': status_code[0], 'body_length': length[0], 'wall_seconds': finish - start, })