def connect(self): """Connect self.sock to self.ip:self.port""" try: self.sock.connect((self.ip, self.port)) except OSError as e: self.sock.close() raise ProtocolError(e)
def connect(self): """Connect self._sock to self.ip:self.port""" start_time = time.monotonic() try: self._sock.connect((self.ip, self.port)) except OSError as e: self._sock.close() raise ProtocolError('{} {} during socket.connect()' .format(e.__class__.__name__, e)) self._decrease_timeout(time.monotonic() - start_time)
def sendall(self, b): """sendall bytes to connected self.sock https://docs.python.org/3.4/library/socket.html#socket.socket.sendall args: b, bytes, bytes to send """ try: self.sock.sendall(b) except OSError as e: self.sock.close() raise ProtocolError(e)
def receive(self): """Receive response ONCE from connected self.sock up to RECV_BUFF_SIZE returns: bytes() received """ try: received = self.sock.recv(RECV_BUFF_SIZE) except OSError as e: self.sock.close() raise ProtocolError(e) return received
def sendall(self, b): """sendall bytes to connected self._sock https://docs.python.org/3.4/library/socket.html#socket.socket.sendall args: b, bytes, bytes to send """ start_time = time.monotonic() try: self._sock.sendall(b) except OSError as e: self._sock.close() raise ProtocolError('{} {} during socket.sendall()' .format(e.__class__.__name__, e)) self._decrease_timeout(time.monotonic() - start_time)
def _parse_status(self): """Search for HTTP Status-Line in self.raw, parse out status_code and status_reason """ # search for HTTP Status-Line in the beginning of the response m = self._STATUS_LINE_RE.search(self.raw[:512]) # if there is no match, we got a none-http response? if not m: raise ProtocolError( 'Unable to find HTTP Status-Line in the response') # convert status to integer # as the _STATUS_LINE_RE regexp is matching \d+ # no need to trap ValueError here self.status_code = int(m.group(1)) self.status_reason = m.group(2)
def recv(self): """Read response ONCE from connected self._sock up to RECV_BUFF_SIZE bytes returns: bytes() received """ start_time = time.monotonic() try: received = self._sock.recv(RECV_BUFF_SIZE) except OSError as e: self._sock.close() raise ProtocolError('{} {} during socket.recv()' .format(e.__class__.__name__, e)) self._decrease_timeout(time.monotonic() - start_time) return received
def _make(self, method='GET'): """Make HTTP request args: method: string, one of GET, POST, PUT returns: Response() object """ # construct request string host_header = '' if self.hostname: host_header = 'Host: {}\r\n'.format(self.hostname) # "Host:" header must be provided when using SNI req_str = ('{} {} HTTP/1.0\r\n{}Connection: close\r\n\r\n'. format(method, self.url_path, host_header)) # create a socket tcp_sock = tcp.TCPSocket(ip=self.ip, port=self.port, timeout=self.timeout) # if using SSL wrap the socket if self.use_ssl: tcp_sock._sock = UNVERIFIED_SSL_CONTEXT.wrap_socket( tcp_sock._sock, server_hostname=self.hostname) # connect tcp_sock.connect() # send request tcp_sock.sendall(req_str.encode()) # continuously read from the socket until either Status-Line is found, # a timeout occurred or remote end closed the conection response_string = '' while True: try: recv_bytes = tcp_sock.recv() except ProtocolError as e: if response_string == '': log_msg = ('got {error}, no data received from the peer' .format(error=e)) else: log_msg = ('failed to find Status-Line within the timeout, ' 'got {error}, ' 'response(up to 512 chars): {response_string}' .format(error=e, response_string=response_string[:512])) raise ProtocolError(log_msg) # remote side closed connection, no need to call sock.close() if recv_bytes == b'': if response_string == '': log_msg = ('remote closed the connection, ' 'no data received from the peer') else: log_msg = ('remote closed the connection, ' 'failed to find Status-Line in the ' 'response(up to 512 chars): {}' .format(response_string[:512])) raise ProtocolError(log_msg) else: # match in the data received so far response_string += recv_bytes.decode(errors='ignore') if HTTPResponse._STATUS_LINE_RE.search(response_string[:128]): # found Status-Line tcp_sock.close() return HTTPResponse(response_string)