Example #1
0
async def test_request_send_push_promise() -> None:
    push_promise: Tuple[str, Headers] = None

    async def _push(path: str, headers: Headers) -> None:
        nonlocal push_promise
        push_promise = (path, headers)

    request = Request(
        'GET',
        'http',
        '/',
        b'a=b&a=c',
        CIMultiDict({
            'host': 'quart.com',
            'Content-Type': 'application/x-www-form-urlencoded',
            "Accept": "*/*",
            "Accept-Encoding": "gzip",
            "User-Agent": "quart",
        }),
        "",
        "2",
        send_push_promise=_push,
    )
    await request.send_push_promise("/")
    assert push_promise[0] == "/"
    valid_headers = {
        "Accept": "*/*",
        "Accept-Encoding": "gzip",
        "User-Agent": "quart",
    }
    assert len(push_promise[1]) == len(valid_headers)
    for name, value in valid_headers.items():
        assert push_promise[1][name] == value
Example #2
0
def test_query_string() -> None:
    base_request_websocket = BaseRequestWebsocket(
        "GET", "http", "/", b"a=b&a=c&f", CIMultiDict({"host": "localhost"}),
        "", "1.1")
    assert base_request_websocket.query_string == b"a=b&a=c&f"
    assert base_request_websocket.args.getlist("a") == ["b", "c"]
    assert base_request_websocket.args["f"] == ""
Example #3
0
def test_basic_authorization() -> None:
    headers = CIMultiDict()
    headers['Authorization'] = "Basic {}".format(b64encode(b'identity:secret').decode('ascii'))
    request = BaseRequestWebsocket('GET', 'http', '/', headers)
    auth = request.authorization
    assert auth.username == 'identity'
    assert auth.password == 'secret'
Example #4
0
def test_access_log_standard_atoms() -> None:
    request_headers = CIMultiDict({
        'Referer': 'stet.io',
        'Remote-Addr': '127.0.0.1',
        'User-Agent': 'quart',
    })
    request = Request('GET', '/?x=y', request_headers)
    response = Response('Hello', 202)
    atoms = AccessLogAtoms(request, response, 'h2', 0.000023)
    assert atoms['h'] == '127.0.0.1'
    assert atoms['l'] == '-'
    assert time.strptime(atoms['t'], '[%d/%b/%Y:%H:%M:%S %z]')
    assert int(atoms['s']) == 202
    assert atoms['m'] == 'GET'
    assert atoms['U'] == '/'
    assert atoms['q'] == 'x=y'
    assert atoms['H'] == 'h2'
    assert int(atoms['b']) == len('Hello')
    assert int(atoms['B']) == len('Hello')
    assert atoms['f'] == 'stet.io'
    assert atoms['a'] == 'quart'
    assert atoms['p'] == f"<{os.getpid()}>"
    assert atoms['not-atom'] == '-'
    assert atoms['T'] == 0
    assert atoms['D'] == 23
    assert atoms['L'] == '0.000023'
Example #5
0
def test_access_log_header_atoms() -> None:
    request_headers = CIMultiDict({
        'Random': 'Request',
        'Remote-Addr': '127.0.0.1',
    })
    request = Request('GET', '/', request_headers)
    response_headers = CIMultiDict({
        'Random': 'Response',
    })
    response = Response('Hello', 200, response_headers)
    atoms = AccessLogAtoms(request, response, 'h2', 0)
    assert atoms['{random}i'] == 'Request'
    assert atoms['{RANDOM}i'] == 'Request'
    assert atoms['{not-atom}i'] == '-'
    assert atoms['{random}o'] == 'Response'
    assert atoms['{RANDOM}o'] == 'Response'
Example #6
0
def test_url_structure(
    method: str,
    scheme: str,
    host: str,
    path: str,
    query_string: bytes,
    expected_path: str,
    expected_full_path: str,
    expected_url: str,
    expected_base_url: str,
    expected_url_root: str,
    expected_host_url: str,
) -> None:
    base_request_websocket = BaseRequestWebsocket(
        method,
        scheme,
        path,
        query_string,
        CIMultiDict({'host': host}),
        "",
        "1.1",
    )

    assert base_request_websocket.path == expected_path
    assert base_request_websocket.query_string == query_string
    assert base_request_websocket.full_path == expected_full_path
    assert base_request_websocket.url == expected_url
    assert base_request_websocket.base_url == expected_base_url
    assert base_request_websocket.url_root == expected_url_root
    assert base_request_websocket.host_url == expected_host_url
    assert base_request_websocket.host == host
    assert base_request_websocket.method == method
    assert base_request_websocket.scheme == scheme
    assert base_request_websocket.is_secure == scheme.endswith('s')
Example #7
0
async def test_after_this_request() -> None:
    async with RequestContext(
            Quart(__name__),
            Request('GET', 'http', '/', CIMultiDict()),
    ) as context:
        after_this_request(lambda: 'hello')
        assert context._after_request_functions[0]() == 'hello'
Example #8
0
def test_multidict_type_conversion(
        dict_class: Union[CIMultiDict, MultiDict]) -> None:
    data = CIMultiDict()
    data['x'] = '2'
    data['y'] = 'b'
    assert data.get('x', type=int) == 2
    assert data.get('y', default=None, type=int) is None
Example #9
0
async def test_has_request_context() -> None:
    async with RequestContext(Quart(__name__),
                              Request('GET', 'http', '/', CIMultiDict())):
        assert has_request_context() is True
        assert has_app_context() is True
    assert has_request_context() is False
    assert has_app_context() is False
Example #10
0
def test_bad_request_if_websocket_route() -> None:
    app = Quart(__name__)
    url_adapter = Mock()
    url_adapter.match.return_value = Rule('/', {'GET'}, 'index', is_websocket=True), {}
    app.create_url_adapter = lambda *_: url_adapter  # type: ignore
    request = Request('GET', 'http', '/', b'', CIMultiDict())
    RequestContext(app, request)
    assert isinstance(request.routing_exception, BadRequest)
Example #11
0
def test_basic_authorization() -> None:
    headers = CIMultiDict()
    headers["Authorization"] = "Basic {}".format(
        b64encode(b"identity:secret").decode("ascii"))
    request = BaseRequestWebsocket("GET", "http", "/", b"", headers, "", "1.1")
    auth = request.authorization
    assert auth.username == "identity"
    assert auth.password == "secret"
Example #12
0
def test_access_log_environ_atoms() -> None:
    os.environ['Random'] = 'Environ'
    request_headers = CIMultiDict({
        'Remote-Addr': '127.0.0.1',
    })
    request = Request('GET', '/', request_headers)
    response = Response('Hello', 200)
    atoms = AccessLogAtoms(request, response, 'h2', 0)
    assert atoms['{random}e'] == 'Environ'
Example #13
0
def test_request_context_match() -> None:
    app = Quart(__name__)
    url_adapter = Mock()
    url_adapter.match.return_value = ('Rule', {'arg': 'value'})
    app.create_url_adapter = lambda *_: url_adapter  # type: ignore
    request = Request('GET', '/', CIMultiDict(), None)
    RequestContext(app, request)
    assert request.url_rule == 'Rule'
    assert request.view_args == {'arg': 'value'}
Example #14
0
def test_bad_request_if_websocket_route() -> None:
    app = Quart(__name__)
    url_adapter = Mock()
    url_adapter.match.side_effect = BadRequest()
    app.create_url_adapter = lambda *_: url_adapter  # type: ignore
    request = Request(
        "GET", "http", "/", b"", CIMultiDict(), "", "1.1", send_push_promise=no_op_push
    )
    RequestContext(app, request)
    assert isinstance(request.routing_exception, BadRequest)
Example #15
0
def test_request_exceeds_max_content_length() -> None:
    max_content_length = 5
    headers = CIMultiDict()
    headers['Content-Length'] = str(max_content_length + 1)
    with pytest.raises(RequestEntityTooLarge):
        Request('POST',
                'http',
                '/',
                headers,
                max_content_length=max_content_length)
Example #16
0
def test_request_context_match() -> None:
    app = Quart(__name__)
    url_adapter = Mock()
    rule = Rule('/', ['GET'], 'index')
    url_adapter.match.return_value = (rule, {'arg': 'value'})
    app.create_url_adapter = lambda *_: url_adapter  # type: ignore
    request = Request('GET', 'http', '/', CIMultiDict())
    RequestContext(app, request)
    assert request.url_rule == rule
    assert request.view_args == {'arg': 'value'}
Example #17
0
def test_bad_request_if_websocket_missmatch(
        request_factory: object, context_class: object, is_websocket: bool,
) -> None:
    app = Quart(__name__)
    url_adapter = Mock()
    url_adapter.match.return_value = Rule('/', {'GET'}, 'index', is_websocket=is_websocket), {}
    app.create_url_adapter = lambda *_: url_adapter  # type: ignore
    request_websocket = request_factory('GET', '/', CIMultiDict())  # type: ignore
    context_class(app, request_websocket)  # type: ignore
    assert isinstance(request_websocket.routing_exception, BadRequest)
Example #18
0
def test_request_context_matching_error(
        exception_type: Exception, exception_instance: Exception,
) -> None:
    app = Quart(__name__)
    url_adapter = Mock()
    url_adapter.match.side_effect = exception_instance
    app.create_url_adapter = lambda *_: url_adapter  # type: ignore
    request = Request('GET', 'http', '/', b'', CIMultiDict())
    RequestContext(app, request)
    assert isinstance(request.routing_exception, exception_type)  # type: ignore
Example #19
0
async def test_overlapping_request_ctx() -> None:
    app = Quart(__name__)

    request = Request('GET', 'http', '/', b'', CIMultiDict())
    ctx1 = app.request_context(request)
    await ctx1.__aenter__()
    ctx2 = app.request_context(request)
    await ctx2.__aenter__()
    await ctx1.__aexit__(None, None, None)
    assert has_app_context()  # Ensure the app context still exists for ctx2
    await ctx2.__aexit__(None, None, None)
Example #20
0
async def test_app_handle_websocket_asyncio_cancelled_error() -> None:
    app = Quart(__name__)

    @app.websocket("/")
    async def index() -> NoReturn:
        raise asyncio.CancelledError()

    websocket = app.websocket_class("/", b"", "wss", CIMultiDict(), "", "1.1",
                                    None, None, None, None)
    with pytest.raises(asyncio.CancelledError):
        await app.handle_websocket(websocket)
Example #21
0
async def test_overlapping_websocket_ctx() -> None:
    app = Quart(__name__)

    websocket = Websocket("/", b"", "ws", CIMultiDict(), "", "1.1", [], None, None, None)
    ctx1 = app.websocket_context(websocket)
    await ctx1.__aenter__()
    ctx2 = app.websocket_context(websocket)
    await ctx2.__aenter__()
    await ctx1.__aexit__(None, None, None)
    assert has_app_context()  # Ensure the app context still exists for ctx2
    await ctx2.__aexit__(None, None, None)
Example #22
0
def test_query_string() -> None:
    base_request_websocket = BaseRequestWebsocket(
        'GET',
        'http',
        '/',
        b'a=b&a=c&f',
        CIMultiDict({'host': 'localhost'}),
    )
    assert base_request_websocket.query_string == b'a=b&a=c&f'
    assert base_request_websocket.args.getlist('a') == ['b', 'c']
    assert base_request_websocket.args['f'] == ''
Example #23
0
def test_secure_cookie_session_interface_open_session() -> None:
    session = SecureCookieSession()
    session['something'] = 'else'
    interface = SecureCookieSessionInterface()
    app = Quart(__name__)
    app.secret_key = 'secret'
    response = Response('')
    interface.save_session(app, session, response)
    request = Request('GET', 'http', '/', b'', CIMultiDict())
    request.headers['Cookie'] = response.headers['Set-Cookie']
    new_session = interface.open_session(app, request)
    assert new_session == session
Example #24
0
async def test_request_get_data_timeout() -> None:
    request = Request(
        'POST',
        'http',
        '/',
        b'',
        CIMultiDict(),
        body_timeout=1,
        send_push_promise=no_op_push,
    )
    with pytest.raises(RequestTimeout):
        await request.get_data()
Example #25
0
def test_request_context_matching_error(
    exception_type: Exception, exception_instance: Exception
) -> None:
    app = Quart(__name__)
    url_adapter = Mock()
    url_adapter.match.side_effect = exception_instance
    app.create_url_adapter = lambda *_: url_adapter  # type: ignore
    request = Request(
        "GET", "http", "/", b"", CIMultiDict(), "", "1.1", send_push_promise=no_op_push
    )
    RequestContext(app, request)
    assert isinstance(request.routing_exception, exception_type)  # type: ignore
Example #26
0
def test_request_context_match() -> None:
    app = Quart(__name__)
    url_adapter = Mock()
    rule = Rule("/", {"GET"}, "index")
    url_adapter.match.return_value = (rule, {"arg": "value"})
    app.create_url_adapter = lambda *_: url_adapter  # type: ignore
    request = Request(
        "GET", "http", "/", b"", CIMultiDict(), "", "1.1", send_push_promise=no_op_push
    )
    RequestContext(app, request)
    assert request.url_rule == rule
    assert request.view_args == {"arg": "value"}
Example #27
0
async def test_overlapping_request_ctx() -> None:
    app = Quart(__name__)

    request = Request(
        "GET", "http", "/", b"", CIMultiDict(), "", "1.1", send_push_promise=no_op_push
    )
    ctx1 = app.request_context(request)
    await ctx1.__aenter__()
    ctx2 = app.request_context(request)
    await ctx2.__aenter__()
    await ctx1.__aexit__(None, None, None)
    assert has_app_context()  # Ensure the app context still exists for ctx2
    await ctx2.__aexit__(None, None, None)
Example #28
0
async def test_request_values() -> None:
    request = Request(
        'GET',
        'http',
        '/?a=b&a=c',
        CIMultiDict({
            'host': 'quart.com',
            'Content-Type': 'application/x-www-form-urlencoded'
        }),
    )
    request.body.append(urlencode({'a': 'd'}).encode())
    request.body.set_complete()
    assert (await request.values).getlist('a') == ['b', 'c', 'd']
Example #29
0
def make_test_headers_path_and_query_string(
    app: Quart,
    path: str,
    headers: Union[dict, CIMultiDict] = None,
    query_string: dict = None,
) -> Tuple[CIMultiDict, str, bytes]:
    """Make the headers and path with defaults for testing.

    Arguments:
        app: The application to test against.
        path: The path to request. If the query_string argument is not
            defined this argument will be partitioned on a '?' with
            the following part being considered the query_string.
        headers: Initial headers to send.
        query_string: To send as a dictionary, alternatively the
            query_string can be determined from the path.
    """
    if headers is None:
        headers = CIMultiDict()
    elif isinstance(headers, CIMultiDict):
        headers = headers
    elif headers is not None:
        headers = CIMultiDict(headers)
    headers.setdefault('Remote-Addr', '127.0.0.1')
    headers.setdefault('User-Agent', 'Quart')
    headers.setdefault('host', app.config['SERVER_NAME'] or 'localhost')
    if '?' in path and query_string is not None:
        raise ValueError(
            'Query string is defined in the path and as an argument')
    if query_string is None:
        path, _, query_string_raw = path.partition('?')
        if query_string_raw:
            query_string_raw = urlencode(parse_qs(query_string_raw),
                                         doseq=True)
    else:
        query_string_raw = urlencode(query_string, doseq=True)
    query_string_bytes = query_string_raw.encode()
    return headers, path, query_string_bytes  # type: ignore
Example #30
0
async def test_request_exceeds_max_content_length() -> None:
    max_content_length = 5
    headers = CIMultiDict()
    headers['Content-Length'] = str(max_content_length + 1)
    request = Request(
        'POST',
        'http',
        '/',
        b'',
        headers,
        max_content_length=max_content_length,
        send_push_promise=no_op_push,
    )
    with pytest.raises(RequestEntityTooLarge):
        await request.get_data()