def parse_headers(self): print('************* function parse_headers *************') self.num_headers[0] = 10 result = lib.phr_parse_request( ffi.from_buffer(self.buffer), len(self.buffer), self.c_method, self.method_len, self.c_path, self.path_len, self.minor_version, self.c_headers, self.num_headers, 0) """ const char *buf, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len """ print('parse_headers-result: {}'.format(result)) if result == -2: return result elif result == -1: self.on_error('malformed_headers') self._reset_state() self.buffer = bytearray() return result else: self._reset_state() method = ffi.string(self.c_method[0], self.method_len[0]).decode('ascii') path = ffi.string(self.c_path[0], self.path_len[0]).decode('ascii') version = "1." + str(self.minor_version[0]) headers = {} for idx in range(self.num_headers[0]): header = self.c_headers[idx] name = ffi.string(header.name, header.name_len).decode('ascii').title() value = ffi.string(header.value, header.value_len).decode('latin1') headers[name] = value self.buffer = self.buffer[result:] print('len(self.buffer): {}'.format(len(self.buffer))) print('self.buffer: {}'.format(self.buffer)) self.request = HttpRequest(method, path, version, headers) self.on_headers(self.request) return result
def _parse_body(self): if self.content_length is None and self.request.method in NO_SEMANTICS: self.on_body(self.request) return 0 elif self.content_length == 0: self.request.body = b"" self.on_body(self.request) return 0 elif self.content_length is not None: if self.content_length > len(self.buffer): return -2 self.request.body = bytes(self.buffer[:self.content_length]) self.on_body(self.request) self.buffer = self.buffer[self.content_length:] result = self.content_length return result elif self.transfer == 'identity': return -2 elif self.transfer == 'chunked': if not self.chunked_decoder: self.chunked_decoder = ffi.new('struct phr_chunked_decoder*') self.chunked_decoder.consume_trailer = b'\x01' chunked_offset_start = self.chunked_offset[0] self.chunked_offset[0] = len(self.buffer) - self.chunked_offset[0] result = lib.phr_decode_chunked( self.chunked_decoder, ffi.from_buffer(self.buffer) + chunked_offset_start, self.chunked_offset) self.chunked_offset[ 0] = self.chunked_offset[0] + chunked_offset_start if result == -2: self.buffer = self.buffer[:self.chunked_offset[0]] return result elif result == -1: self.on_error('malformed_body') self._reset_state() self.buffer = bytearray() return result self.request.body = bytes(self.buffer[:self.chunked_offset[0]]) self.on_body(self.request) self.buffer = self.buffer[self.chunked_offset[0]:self. chunked_offset[0] + result] self._reset_state() return result
def parse_headers(self): self.num_headers[0] = 10 result = lib.phr_parse_request( ffi.from_buffer(self.buffer), len(self.buffer), self.c_method, self.method_len, self.c_path, self.path_len, self.minor_version, self.c_headers, self.num_headers, 0) if result == -2: return result elif result == -1: self.on_error('malformed_headers') self._reset_state() self.buffer = bytearray() return result else: self._reset_state() method = ffi.string(self.c_method[0], self.method_len[0]).decode('ascii') path = ffi.string(self.c_path[0], self.path_len[0]).decode('ascii') version = "1." + str(self.minor_version[0]) headers = {} for idx in range(self.num_headers[0]): header = self.c_headers[idx] name = ffi.string(header.name, header.name_len).decode('ascii').title() value = ffi.string(header.value, header.value_len).decode('latin1') headers[name] = value self.buffer = self.buffer[result:] self.request = HttpRequest(method, path, version, headers) self.on_headers(self.request) return result
def _parse_headers(self): self.num_headers[0] = 10 # FIXME: More than 10 headers result = lib.phr_parse_request(ffi.from_buffer(self.buffer), len(self.buffer), self.c_method, self.method_len, self.c_path, self.path_len, self.minor_version, self.c_headers, self.num_headers, 0) if result == -2: return result elif result == -1: self.on_error('malformed_headers') self._reset_state() self.buffer = bytearray() return result else: self._reset_state() method = ffi.string(self.c_method[0], self.method_len[0]).decode('ascii') path = ffi.string(self.c_path[0], self.path_len[0]).decode('ascii') version = "1." + str(self.minor_version[0]) headers = {} for idx in range(self.num_headers[0]): header = self.c_headers[idx] name = ffi.string(header.name, header.name_len).decode('ascii').title() value = ffi.string(header.value, header.value_len).decode('latin1') headers[name] = value self.buffer = self.buffer[result:] if self.minor_version[0] == 0: self.connection = headers.get('Connection', 'close') self.transfer = 'identity' else: self.connection = headers.get('Connection', 'keep-alive') self.transfer = headers.get('Transfer-Encoding', 'chunked') self.content_length = headers.get('Content-Length') if self.content_length is not None: content_length_error = False if not self.content_length: content_length_error = True if not content_length_error and self.content_length[0] in '+-': content_length_error = True if not content_length_error: try: self.content_length = int(self.content_length) except ValueError: content_length_error = True if content_length_error: self.on_error('invalid_headers') self._reset_state() self.buffer = bytearray() return -1 self.request = HttpRequest(method, path, version, headers) self.on_headers(self.request) return result