示例#1
0
 def replace_boundary(req: Request):
     fixed_boundary = 'fixed_boundary'
     content_type_header, old_boundary = req.headers['Content-Type'].split(
         'boundary=')
     req.headers['Content-Type'] = 'boundary='.join(
         [content_type_header, fixed_boundary])
     req.content = req.content.replace(old_boundary.encode(),
                                       fixed_boundary.encode())
示例#2
0
    def clean_multipart_form(self, req: Request) -> None:
        """Replace any problematic values of multipart form keys with constant data

        Args:
            req (Request): The request to modify
        """
        if req.multipart_form and self.form_keys:
            updated_multipart_form_data = []
            for key, val in req.multipart_form.items(multi=True):
                if key in self.form_keys:
                    updated_multipart_form_data.append((key, self.constant))
                else:
                    updated_multipart_form_data.append((key, val))
            req._set_multipart_form(updated_multipart_form_data)
示例#3
0
 def test_no_data_on_closed_stream(self, tctx):
     frame_factory = FrameFactory()
     req = Request.make("GET", "http://example.com/")
     resp = {":status": 200}
     assert (
         Playbook(Http2Client(tctx)) << SendData(
             tctx.server,
             Placeholder(bytes))  # preamble + initial settings frame
         >> DataReceived(
             tctx.server,
             frame_factory.build_settings_frame({}, ack=True).serialize())
         >> http.RequestHeaders(1, req, end_stream=True) << SendData(
             tctx.server,
             b"\x00\x00\x06\x01\x05\x00\x00\x00\x01\x82\x86\x84\\\x81\x07")
         >> http.RequestEndOfMessage(1) >> DataReceived(
             tctx.server,
             frame_factory.build_headers_frame(resp).serialize()) <<
         http.ReceiveHttp(Placeholder(
             http.ResponseHeaders)) >> http.RequestProtocolError(
                 1, "cancelled", code=status_codes.CLIENT_CLOSED_REQUEST) <<
         SendData(
             tctx.server,
             frame_factory.build_rst_stream_frame(
                 1, ErrorCodes.CANCEL).serialize()) >> DataReceived(
                     tctx.server,
                     frame_factory.build_data_frame(b"foo").serialize()) <<
         SendData(
             tctx.server,
             frame_factory.build_rst_stream_frame(
                 1, ErrorCodes.STREAM_CLOSED).serialize())
     )  # important: no ResponseData event here!
示例#4
0
def read_request_head(lines: List[bytes]) -> Request:
    """
    Parse an HTTP request head (request line + headers) from an iterable of lines

    Args:
        lines: The input lines

    Returns:
        The HTTP request object (without body)

    Raises:
        ValueError: The input is malformed.
    """
    host, port, method, scheme, authority, path, http_version = _read_request_line(lines[0])
    headers = _read_headers(lines[1:])

    return Request(
        host=host,
        port=port,
        method=method,
        scheme=scheme,
        authority=authority,
        path=path,
        http_version=http_version,
        headers=headers,
        content=None,
        trailers=None,
        timestamp_start=time.time(),
        timestamp_end=None
    )
示例#5
0
    def modify_json_body(self, req: Request, json_body: dict) -> None:
        """Modify the json body of a request by replacing any timestamp data with constant data

        Args:
            req (Request): The request whose json body will be modified.
            json_body (dict): The request body to modify.
        """
        original_content = deepcopy(json_body)
        modified = False
        keys_to_replace = self.json_keys
        logging.info('{}'.format(keys_to_replace))
        for key_path in keys_to_replace:
            body = json_body
            keys = key_path.split('.')
            logging.info('keypath parts: {}'.format(keys))
            lastkey = keys[-1]
            logging.info('lastkey: {}'.format(lastkey))
            skip_key = False
            for k in keys[:-1]:
                if k in body:
                    body = body[k]
                elif isinstance(body, list) and k.isdigit():
                    if int(k) > len(body) - 1:
                        skip_key = True
                        break
                    body = body[int(k)]
                else:
                    skip_key = True
                    break
            if not skip_key:
                if lastkey in body:
                    logging.info('modifying request to "{}"'.format(
                        req.pretty_url))
                    body[lastkey] = self.constant
                    modified = True
                elif isinstance(body, list) and lastkey.isdigit(
                ) and int(lastkey) <= len(body) - 1:
                    logging.info('modifying request to "{}"'.format(
                        req.pretty_url))
                    body[int(lastkey)] = self.constant
                    modified = True
        if modified:
            logging.info('original request body:\n{}'.format(
                json.dumps(original_content, indent=4)))
            logging.info('modified request body:\n{}'.format(
                json.dumps(json_body, indent=4)))
            req.set_content(json.dumps(json_body).encode())
示例#6
0
 def handle_url_query(self, req: Request) -> None:
     query_data = req._get_query()
     logging.info('query_data: {}'.format(query_data))
     for key, val in query_data:
         # don't bother trying to interpret an argument less than 4 characters as some type of timestamp
         if len(val) > 4:
             if self.safely_parse(val):
                 self.query_keys.add(key)
示例#7
0
    def clean_url_query(self, req: Request) -> None:
        """Replace any problematic values of query parameters with constant data

        Args:
            req (Request): The request to modify
        """
        query_data = sorted(req._get_query())
        logging.info('fetched query_data: {}'.format(query_data))
        updated_query_data = []
        if query_data and self.query_keys:
            for key, val in query_data:
                if key in self.query_keys:
                    updated_query_data.append((key, self.constant))
                else:
                    updated_query_data.append((key, val))
        req._set_query(updated_query_data or query_data)
        logging.info(f'updated query_data: {req._get_query()}')
示例#8
0
def request_content_for_console(request: http.Request) -> str:
    try:
        text = request.get_text(strict=True)
        assert text
    except ValueError:
        # shlex.quote doesn't support a bytes object
        # see https://github.com/python/cpython/pull/10871
        raise exceptions.CommandError("Request content must be valid unicode")
    escape_control_chars = {chr(i): f"\\x{i:02x}" for i in range(32)}
    return "".join(escape_control_chars.get(x, x) for x in text)
示例#9
0
 def test_init_conv(self):
     assert Request(
         b"example.com",
         80,
         "GET",
         "http",
         "example.com",
         "/",
         "HTTP/1.1",
         (),
         None,
         (),
         0,
         0,
     )  # type: ignore
def flow():
    request = Request(host=b'localhost',
                      path=b'/test/',
                      http_version=b'1.1',
                      port=1234,
                      method=b'',
                      scheme=b'',
                      headers=Headers([(b"Host", b"example.com")]),
                      content=None,
                      timestamp_start=111.1,
                      timestamp_end=111.2,
                      authority=b'',
                      trailers='')
    flow = HTTPFlow(client_conn=MagicMock(), server_conn=MagicMock())
    flow.request = request
    return flow
示例#11
0
def ws_testdata(tctx):
    tctx.server.address = ("example.com", 80)
    tctx.server.state = ConnectionState.OPEN
    flow = HTTPFlow(
        tctx.client,
        tctx.server
    )
    flow.request = Request.make("GET", "http://example.com/", headers={
        "Connection": "upgrade",
        "Upgrade": "websocket",
        "Sec-WebSocket-Version": "13",
    })
    flow.response = Response.make(101, headers={
        "Connection": "upgrade",
        "Upgrade": "websocket",
    })
    return tctx, Playbook(websocket.WebsocketLayer(tctx, flow))
示例#12
0
    def test_make(self):
        r = Request.make("GET", "https://example.com/")
        assert r.method == "GET"
        assert r.scheme == "https"
        assert r.host == "example.com"
        assert r.port == 443
        assert r.path == "/"

        r = Request.make("GET", "https://example.com/", "content",
                         {"Foo": "bar"})
        assert r.content == b"content"
        assert r.headers["content-length"] == "7"
        assert r.headers["Foo"] == "bar"

        Request.make("GET", "https://example.com/", content=b"content")
        with pytest.raises(TypeError):
            Request.make("GET", "https://example.com/", content=42)

        r = Request.make("GET",
                         "https://example.com/",
                         headers=[(b"foo", b"bar")])
        assert r.headers["foo"] == "bar"

        r = Request.make("GET",
                         "https://example.com/",
                         headers=({
                             "foo": "baz"
                         }))
        assert r.headers["foo"] == "baz"

        r = Request.make("GET",
                         "https://example.com/",
                         headers=Headers(foo="qux"))
        assert r.headers["foo"] == "qux"

        with pytest.raises(TypeError):
            Request.make("GET", "https://example.com/", headers=42)