def test_normalize_headers_message_dupes(): headers = HTTPMessage() headers.add_header('Cookie', 'foo') headers.add_header('Cookie', 'bar') new = normalize_headers(headers) assert len(new) == 1 assert new['cookie'] == 'foo, bar'
def _create_mock_resonse(self): mock_response = Mock() mock_response.status = 200 mock_response.reason = 'OK' headers = HTTPMessage() headers.add_header('Content-Type', 'application/json') headers.add_header('Content-Length', '500') mock_response.headers = headers return mock_response
def _create_mock_request(self, path='http://www.example.com/test/path/'): mock_request = Mock() mock_request.path = path mock_request.command = 'GET' headers = HTTPMessage() headers.add_header('Host', 'www.example.com') headers.add_header('Accept', '*/*') mock_request.headers = headers return mock_request
def _build_transport_with_reply(self, body, status=200, pattern=None, test_request=None): headers = HTTPMessage() headers.add_header('Content-Type', 'text/xml; charset=utf-8') reply = Reply(status, headers, body) transport = HttpTransport() def surrogate(request, *args, **kwargs): if pattern and not re.search(pattern, request.url): return HttpTransport.send(transport, *args, **kwargs) if test_request: test_request(request) return reply transport.send = mock.MagicMock() transport.send.side_effect = surrogate return transport
def extract_cookies_to_jar(jar, request, response): """Extract the cookies from the response into a CookieJar. :param jar: cookielib.CookieJar (not necessarily a RequestsCookieJar) :param request: our own requests.Request object :param response: httpcore.Response object """ msg = HTTPMessage() for k, v in response.headers.raw: msg.add_header(k.decode(), v.decode()) # the _original_response field is the wrapped httplib.HTTPResponse object, req = requests.cookies.MockRequest(request) # pull out the HTTPMessage with the headers and put it in the mock: res = requests.cookies.MockResponse(msg) jar.extract_cookies(res, req)
def _dirport_mock(data, encoding = 'identity'): dirport_mock = Mock() dirport_mock().read.return_value = data if stem.prereq.is_python_3(): headers = HTTPMessage() for line in HEADER.splitlines(): key, value = line.split(': ', 1) headers.add_header(key, encoding if key == 'Content-Encoding' else value) dirport_mock().headers = headers else: dirport_mock().headers = HTTPMessage(io.BytesIO(HEADER % encoding)) return dirport_mock
def http_request(self) -> HTTPRequest: headers = HTTPMessage() headers.add_header("Sec-WebSocket-Key", self.client_key) _request = HTTPRequest() _request.headers = headers return _request
class ConnectionHandler(object): """ Handler class for the connection to be proxied. """ server_version = "SCION HTTP Proxy/" + VERSION def __init__(self, connection, address, conn_id): """ Create a ConnectionHandler class to handle the incoming HTTP(S) request. :param connection: Socket belonging to the incoming connection. :type connection: socket :param address: Address of the connecting party. :type address: host, port """ self.conn_id = conn_id self.connection = connection self.method = self.path = self.protocol = None self.headers = HTTPMessage() cur_thread = threading.current_thread() cur_thread.name = self.conn_id try: if not self.parse_request(): # FIXME(kormat): need error reporting return self.handle_request() finally: cleanup(self.connection) def parse_request(self): """ Extracts the request line of an incoming HTTP(S) request. :returns: HTTP(S) Method, Path, HTTP(S) Protocol Version :rtype: triple """ data = [] lf_count = 0 while lf_count < 2: b = self.connection.recv(1) if not b: logging.info("Client closed the connection.") return False if b == b"\r": # Drop \r's, as recommended by rfc2616 19.3 continue data.append(b) if b == b"\n": lf_count += 1 else: lf_count = 0 lines = b"".join(data).decode("ascii").split("\n") self.method, self.path, self.protocol = lines.pop(0).split(" ") for line in lines: if not line: break self.headers.add_header(*line.split(": ", 1)) logging.info("Request: %s %s %s", self.method, self.path, self.protocol) logging.debug("Request headers:\n%s", self.headers) return True def handle_request(self): if self.method == 'CONNECT': self.do_CONNECT() elif self.method in ('GET', 'HEAD', 'POST', 'PUT', 'DELETE'): self.handle_others() else: # FIXME(kormat): need error reporting logging.warning("Invalid HTTP(S) request") def do_CONNECT(self): """ Handles the CONNECT method: Connects to the target address, and responds to the client (i.e. browser) with a 200 Connection established response and starts proxying. """ soc = self._connect_to(self.path) if not soc: # FIXME(kormat): needs error handling return reply = "\r\n".join([ "HTTP/1.1 200 Connection established", "Proxy-agent: %s" % self.server_version ]) + "\r\n\r\n" try: self.connection.send(reply.encode("ascii")) self._read_write(soc) finally: cleanup(soc) def handle_others(self): """ Handles the rest of the supported HTTP methods: Parses the path, connects to the target address, sends the complete request to the target and starts proxying. """ (scm, netloc, path, params, query, _) = urlparse(self.path, 'http') if scm != 'http' or not netloc: logging.error("Bad URL %s" % self.path) return conn_hdr = self.headers["Connection"] if conn_hdr: del self.headers[conn_hdr] self.headers.replace_header("Connection", "close") soc = self._connect_to(netloc) if not soc: # FIXME(kormat): needs error handling return try: # Normal mode proxy strips out scm and netloc self._send_request(soc, '', '', path, params, query) self._read_write(soc) finally: cleanup(soc) logging.debug("Done") def _connect_to(self, netloc): """ Establishes a connection to the target host. :param netloc: The hostname (and port) of the target to be connected to. :type netloc: string :returns: The socket that is used to connect. :rtype: socket """ soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if ':' in netloc: host, port = netloc.split(':') else: host, port = netloc, 80 logging.debug("Connecting to %s:%s" % (host, port)) try: soc.connect((host, int(port))) except OSError: log_exception("Error while connecting to %s:%s" % (host, port)) return False logging.debug("Connected to %s:%s" % (host, port)) return soc def _send_request(self, soc, scm, netloc, path, params, query): """ Helper function that prepares and sends the request on the given socket. :param soc: The socket the request is going to be sent on. :type soc: socket :param path: The path of the HTTP request. :type path: String :param params: Parameters of the request (if any). :type params: String :param query: Query section of the HTTP request (if any). :type query: String """ base = "%s %s HTTP/1.0" % (self.method, urlunparse( (scm, netloc, path, params, query, ''))) req = [] req.append(base) for hdr, val in self.headers.items(): req.append("%s: %s" % (hdr, val)) req_bytes = ("\r\n".join(req) + "\r\n\r\n").encode("ascii") logging.debug("Sending a request: %s", req_bytes) # FIXME(kormat): need error handling/reporting soc.send(req_bytes) def _read_write(self, target_sock): """ The main function responsible for the proxying operation. It creates two threads to listen for incoming data on both client (i.e. browser) and server sockets and relays them accordingly between each other. :param target_sock: The socket belonging to the remote target. :type target_sock: socket """ t1 = threading.Thread(target=thread_safety_net, args=(ProxyData, self.connection, target_sock), name="%s-c2s" % self.conn_id) t1.start() t2 = threading.Thread(target=thread_safety_net, args=(ProxyData, target_sock, self.connection), name="%s-s2c" % self.conn_id) t2.start() # Wait until both threads finish. t1.join() t2.join()
def __init__(self, set_cookie_headers): msg = HTTPMessage() for set_cookie_header in set_cookie_headers: msg.add_header("Set-Cookie", set_cookie_header) self._info = msg