diff --git a/netlib/http_cookies.py b/netlib/http_cookies.py index dab95ed05..8e2458919 100644 --- a/netlib/http_cookies.py +++ b/netlib/http_cookies.py @@ -1,18 +1,18 @@ """ A flexible module for cookie parsing and manipulation. -This module differs from usual standards-compliant cookie modules in a number of -ways. We try to be as permissive as possible, and to retain even mal-formed +This module differs from usual standards-compliant cookie modules in a number +of ways. We try to be as permissive as possible, and to retain even mal-formed information. Duplicate cookies are preserved in parsing, and can be set in formatting. We do attempt to escape and quote values where needed, but will not reject data that violate the specs. Parsing accepts the formats in RFC6265 and partially RFC2109 and RFC2965. We do -not parse the comma-separated variant of Set-Cookie that allows multiple cookies -to be set in a single header. Technically this should be feasible, but it turns -out that violations of RFC6265 that makes the parsing problem indeterminate are -much more common than genuine occurences of the multi-cookie variants. -Serialization follows RFC6265. +not parse the comma-separated variant of Set-Cookie that allows multiple +cookies to be set in a single header. Technically this should be feasible, but +it turns out that violations of RFC6265 that makes the parsing problem +indeterminate are much more common than genuine occurences of the multi-cookie +variants. Serialization follows RFC6265. http://tools.ietf.org/html/rfc6265 http://tools.ietf.org/html/rfc2109 @@ -32,11 +32,11 @@ def _read_until(s, start, term): Read until one of the characters in term is reached. """ if start == len(s): - return "", start+1 + return "", start + 1 for i in range(start, len(s)): if s[i] in term: return s[start:i], i - return s[start:i+1], i+1 + return s[start:i + 1], i + 1 def _read_token(s, start): @@ -59,7 +59,7 @@ def _read_quoted_string(s, start): escaping = False ret = [] # Skip the first quote - for i in range(start+1, len(s)): + for i in range(start + 1, len(s)): if escaping: ret.append(s[i]) escaping = False @@ -70,7 +70,7 @@ def _read_quoted_string(s, start): pass else: ret.append(s[i]) - return "".join(ret), i+1 + return "".join(ret), i + 1 def _read_value(s, start, delims): @@ -103,7 +103,7 @@ def _read_pairs(s, off=0, specials=()): rhs = None if off < len(s): if s[off] == "=": - rhs, off = _read_value(s, off+1, ";") + rhs, off = _read_value(s, off + 1, ";") vals.append([lhs, rhs]) off += 1 if not off < len(s): diff --git a/netlib/websockets.py b/netlib/websockets.py index 5b9d8fbd3..f2d467a56 100644 --- a/netlib/websockets.py +++ b/netlib/websockets.py @@ -67,23 +67,23 @@ class Frame(object): mask_bit, # decimal integer 1 or 0 payload_length_code, # decimal integer 1 - 127 decoded_payload, # bytestring - rsv1 = 0, # decimal integer 1 or 0 - rsv2 = 0, # decimal integer 1 or 0 - rsv3 = 0, # decimal integer 1 or 0 - payload = None, # bytestring - masking_key = None, # 32 bit byte string + rsv1 = 0, # decimal integer 1 or 0 + rsv2 = 0, # decimal integer 1 or 0 + rsv3 = 0, # decimal integer 1 or 0 + payload = None, # bytestring + masking_key = None, # 32 bit byte string actual_payload_length = None, # any decimal integer ): - self.fin = fin - self.rsv1 = rsv1 - self.rsv2 = rsv2 - self.rsv3 = rsv3 - self.opcode = opcode - self.mask_bit = mask_bit - self.payload_length_code = payload_length_code - self.masking_key = masking_key - self.payload = payload - self.decoded_payload = decoded_payload + self.fin = fin + self.rsv1 = rsv1 + self.rsv2 = rsv2 + self.rsv3 = rsv3 + self.opcode = opcode + self.mask_bit = mask_bit + self.payload_length_code = payload_length_code + self.masking_key = masking_key + self.payload = payload + self.decoded_payload = decoded_payload self.actual_payload_length = actual_payload_length @classmethod @@ -162,7 +162,7 @@ class Frame(object): """ Construct a websocket frame from an in-memory bytestring to construct a frame from a stream of bytes, use from_file() directly - """ + """ return cls.from_file(io.BytesIO(bytestring)) def safe_to_bytes(self): @@ -206,7 +206,7 @@ class Frame(object): # '!H' pack as 16 bit unsigned short # add 2 byte extended payload length bytes += struct.pack('!H', self.actual_payload_length) - elif self.actual_payload_length < CONST.MAX_64_BIT_INT: + elif self.actual_payload_length < CONST.MAX_64_BIT_INT: # '!Q' = pack as 64 bit unsigned long long # add 8 bytes extended payload length bytes += struct.pack('!Q', self.actual_payload_length) @@ -225,10 +225,10 @@ class Frame(object): def from_file(cls, reader): """ read a websockets frame sent by a server or client - - reader is a "file like" object that could be backed by a network stream or a disk - or an in memory stream reader - """ + + reader is a "file like" object that could be backed by a network + stream or a disk or an in memory stream reader + """ first_byte = utils.bytes_to_int(reader.read(1)) second_byte = utils.bytes_to_int(reader.read(1)) @@ -336,7 +336,7 @@ def create_server_handshake(key): headers = [ ('Connection', 'Upgrade'), ('Upgrade', 'websocket'), - ('Sec-WebSocket-Accept', create_server_nounce(key)) + ('Sec-WebSocket-Accept', create_server_nonce(key)) ] request = "HTTP/1.1 101 Switching Protocols" return build_handshake(headers, request) @@ -406,11 +406,11 @@ def headers_from_http_message(http_message): ) -def create_server_nounce(client_nounce): +def create_server_nonce(client_nonce): return base64.b64encode( - hashlib.sha1(client_nounce + websockets_magic).hexdigest().decode('hex') + hashlib.sha1(client_nonce + websockets_magic).hexdigest().decode('hex') ) -def create_client_nounce(): +def create_client_nonce(): return base64.b64encode(os.urandom(16)).decode('utf-8') diff --git a/test/test_websockets.py b/test/test_websockets.py index 035f9e17c..1f2025bfb 100644 --- a/test/test_websockets.py +++ b/test/test_websockets.py @@ -27,7 +27,7 @@ class WebSocketsEchoHandler(tcp.BaseHandler): def send_message(self, message): frame = websockets.Frame.default(message, from_client = False) frame.to_file(self.wfile) - + def handshake(self): client_hs = websockets.read_handshake(self.rfile, 1) key = websockets.process_handshake_from_client(client_hs) @@ -45,7 +45,7 @@ class WebSocketsClient(tcp.TCPClient): def __init__(self, address, source_address=None): super(WebSocketsClient, self).__init__(address, source_address) self.version = "13" - self.client_nounce = websockets.create_client_nounce() + self.client_nonce = websockets.create_client_nonce() self.resource = "/" def connect(self): @@ -54,7 +54,7 @@ class WebSocketsClient(tcp.TCPClient): handshake = websockets.create_client_handshake( self.address.host, self.address.port, - self.client_nounce, + self.client_nonce, self.version, self.resource ) @@ -63,9 +63,11 @@ class WebSocketsClient(tcp.TCPClient): self.wfile.flush() server_handshake = websockets.read_handshake(self.rfile, 1) - server_nounce = websockets.process_handshake_from_server(server_handshake) + server_nonce = websockets.process_handshake_from_server( + server_handshake + ) - if not server_nounce == websockets.create_server_nounce(self.client_nounce): + if not server_nonce == websockets.create_server_nonce(self.client_nonce): self.close() def read_next_message(self): @@ -75,6 +77,7 @@ class WebSocketsClient(tcp.TCPClient): frame = websockets.Frame.default(message, from_client = True) frame.to_file(self.wfile) + class TestWebSockets(test.ServerTestBase): handler = WebSocketsEchoHandler @@ -124,7 +127,9 @@ class TestWebSockets(test.ServerTestBase): frame = websockets.Frame.default( self.random_bytes(num_bytes), is_client ) - assert frame == websockets.Frame.from_bytes(frame.safe_to_bytes()) + assert frame == websockets.Frame.from_bytes( + frame.safe_to_bytes() + ) bytes = b'\x81\x03cba' assert websockets.Frame.from_bytes(bytes).safe_to_bytes() == bytes @@ -136,36 +141,44 @@ class TestWebSockets(test.ServerTestBase): frame.safe_to_bytes() def test_handshake(self): - bad_upgrade = "not_websockets" - bad_header_handshake = websockets.build_handshake([ - ('Host', '%s:%s' % ("a", "b")), - ('Connection', "c"), - ('Upgrade', bad_upgrade), - ('Sec-WebSocket-Key', "d"), - ('Sec-WebSocket-Version', "e") - ], "f") + bad_upgrade = "not_websockets" + bad_header_handshake = websockets.build_handshake([ + ('Host', '%s:%s' % ("a", "b")), + ('Connection', "c"), + ('Upgrade', bad_upgrade), + ('Sec-WebSocket-Key', "d"), + ('Sec-WebSocket-Version', "e") + ], "f") - # check behavior when required header values are missing - assert None == websockets.process_handshake_from_server(bad_header_handshake) - assert None == websockets.process_handshake_from_client(bad_header_handshake) + # check behavior when required header values are missing + assert None is websockets.process_handshake_from_server( + bad_header_handshake + ) + assert None is websockets.process_handshake_from_client( + bad_header_handshake + ) - key = "test_key" + key = "test_key" - client_handshake = websockets.create_client_handshake("a","b",key,"d","e") - assert key == websockets.process_handshake_from_client(client_handshake) + client_handshake = websockets.create_client_handshake( + "a", "b", key, "d", "e" + ) + assert key == websockets.process_handshake_from_client( + client_handshake + ) - server_handshake = websockets.create_server_handshake(key) - assert websockets.create_server_nounce(key) == websockets.process_handshake_from_server(server_handshake) + server_handshake = websockets.create_server_handshake(key) + assert websockets.create_server_nonce(key) == websockets.process_handshake_from_server(server_handshake) - handshake = websockets.create_client_handshake("a","b","c","d","e") - stream = io.BytesIO(handshake) - assert handshake == websockets.read_handshake(stream, 1) + handshake = websockets.create_client_handshake("a", "b", "c", "d", "e") + stream = io.BytesIO(handshake) + assert handshake == websockets.read_handshake(stream, 1) + + # ensure readhandshake doesn't loop forever on empty stream + empty_stream = io.BytesIO("") + assert "" == websockets.read_handshake(empty_stream, 1) - # ensure readhandshake doesn't loop forever on empty stream - empty_stream = io.BytesIO("") - assert "" == websockets.read_handshake(empty_stream, 1) - class BadHandshakeHandler(WebSocketsEchoHandler): def handshake(self): client_hs = websockets.read_handshake(self.rfile, 1)