Beispiel #1
0
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'
Beispiel #2
0
 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
Beispiel #3
0
 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
Beispiel #4
0
    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)
Beispiel #6
0
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
Beispiel #7
0
 def http_request(self) -> HTTPRequest:
     headers = HTTPMessage()
     headers.add_header("Sec-WebSocket-Key", self.client_key)
     _request = HTTPRequest()
     _request.headers = headers
     return _request
Beispiel #8
0
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()
Beispiel #9
0
 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