Пример #1
0
def get_frozen_file_getter(file_path, cache_max_age=12000):
    mime = get_mime_type(file_path)
    size = os.path.getsize(file_path)
    current_etag = str(os.path.getmtime(file_path)).encode()
    headers = [
        Header(b'Last-Modified',
               unix_timestamp_to_datetime(os.path.getmtime(file_path))),
        Header(b'ETag', current_etag),
        Header(b'Cache-Control', b'max-age=' + str(cache_max_age).encode())
    ]

    head_headers = headers + [
        Header(b'Content-Type', mime),
        Header(b'Content-Length',
               str(size).encode())
    ]

    data = get_file_data(file_path, size, size_limit=1.049e+7)

    async def frozen_file_getter(request):
        previous_etag = request.if_none_match

        if previous_etag and previous_etag == current_etag:
            return Response(304, headers, None)

        if request.method == b'HEAD':
            return Response(200, head_headers, None)

        return Response(200, Headers(headers), Content(mime, data))

    return frozen_file_getter
Пример #2
0
def get_response_for_file(request, resource_path, cache_time):
    # TODO: support for accept-range and bytes ranges
    file_size = os.path.getsize(resource_path)
    modified_time = os.path.getmtime(resource_path)
    current_etag = str(modified_time).encode()
    previous_etag = request.if_none_match

    headers = [
        Header(b'Last-Modified', unix_timestamp_to_datetime(modified_time)),
        Header(b'ETag', current_etag)
    ]

    if cache_time > 0:
        headers.append(
            Header(b'Cache-Control', b'max-age=' + str(cache_time).encode()))

    if previous_etag and current_etag == previous_etag:
        return Response(304, headers, None)

    if request.method == b'HEAD':
        headers.append(Header(b'Content-Type', get_mime_type(resource_path)))
        headers.append(Header(b'Content-Length', str(file_size).encode()))
        return Response(200, headers, None)

    return Response(
        200, Headers(headers),
        Content(get_mime_type(resource_path),
                get_file_data(resource_path, file_size)))
Пример #3
0
def test_http_header_check_equality(name_a, value_a, name_b, value_b,
                                    expected_result):
    a = Header(name_a, value_a)
    b = Header(name_b, value_b)

    assert (a == b) == expected_result
    assert (a != b) != expected_result
    assert (b != a) != expected_result
Пример #4
0
def test_http_header_collection_get_single_raises_if_more_items_are_present():
    headers = Headers()

    values = [
        Header(b'Cookie', b'Hello=World;'),
        Header(b'Cookie', b'Foo=foo;'),
        Header(b'Cookie', b'Ufo=ufo;'),
    ]

    headers.add_many(values)
    # keeps only the last one, if a single header is expected
    headers.get_single(b'cookie').value == b'Ufo=ufo;'
Пример #5
0
def test_iadd_http_header_collection_concatenation_with_duplicate_header():
    headers = Headers([
        Header(b'Hello', b'World'),
        Header(b'Svil', b'Power'),
    ])

    headers += Header(b'Svil', b'Kitty')
    example = headers[b'Svil']

    assert len(example) == 2
    assert any(x.value == b'Power' for x in example)
    assert any(x.value == b'Kitty' for x in example)
Пример #6
0
def test_iadd_http_header_collection_concatenation_with_header():
    headers = Headers([
        Header(b'Hello', b'World'),
        Header(b'Svil', b'Power'),
    ])

    headers += Header(b'Foo', b'foo')

    example = headers[b'Foo']
    assert len(example) == 1

    header = example[0]
    assert header.name == b'Foo'
    assert header.value == b'foo'
Пример #7
0
def test_iadd_http_header_collection_concatenation_with_list_of_headers():
    headers = Headers([
        Header(b'Hello', b'World'),
        Header(b'Svil', b'Power'),
    ])

    headers += [Header(b'foo', b'foo'), Header(b'ufo', b'ufo')]

    for name in {b'foo', b'ufo'}:
        example = headers[name]
        assert len(example) == 1

        header = example[0]
        assert header.name.lower() == name
        assert header.value == name
Пример #8
0
def test_cookie_parsing_multiple_cookie_headers():
    request = Request(
        b'POST', b'/',
        Headers([
            Header(b'Cookie',
                   b'ai=something; hello=world; foo=Hello%20World%3B;'),
            Header(b'Cookie', b'jib=jab; ai=else;'),
        ]), None)

    assert request.cookies == {
        b'ai': b'else',
        b'hello': b'world',
        b'foo': b'Hello World;',
        b'jib': b'jab'
    }
Пример #9
0
async def test_application_get_handler():
    app = FakeApplication()

    @app.router.get(b'/')
    async def home(request):
        pass

    @app.router.get(b'/foo')
    async def foo(request):
        pass

    handler = get_new_connection_handler(app)

    message = b'\r\n'.join([
        b'GET / HTTP/1.1',
        b'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:63.0) Gecko/20100101 Firefox/63.0',
        b'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        b'Accept-Language: en-US,en;q=0.5',
        b'Connection: keep-alive',
        b'Upgrade-Insecure-Requests: 1',
        b'Host: foo\r\n\r\n'
    ])

    handler.data_received(message)

    await app.response_done.wait()
    request = app.request  # type: Request

    assert request is not None

    connection = request.headers[b'connection']
    assert connection == [Header(b'Connection', b'keep-alive')]

    text = await request.text()
    assert text == ''
Пример #10
0
async def test_cookies_jar_single_cookie():
    fake_pools = FakePools([
        Response(
            200,
            Headers([
                Header(b'Set-Cookie',
                       write_response_cookie(Cookie(b'X-Foo', b'Foo')))
            ]), TextContent('Hello, World!')),
        Response(200, Headers(), TextContent('Hello!'))
    ])
    check_cookie = False

    async def middleware_for_assertions(request, next_handler):
        if check_cookie:
            cookie = request.cookies.get(b'X-Foo')
            assert cookie is not None, 'X-Foo cookie must be configured for following requests'

        return await next_handler(request)

    async with ClientSession(url=b'https://bezkitu.org',
                             pools=fake_pools,
                             middlewares=[middleware_for_assertions
                                          ]) as client:
        await client.get(
            b'/'
        )  # the first request doesn't have any cookie because the response will set;
        check_cookie = True
        await client.get(b'/')
Пример #11
0
async def test_request_headers():
    fake_pools = FakePools(
        [Response(200, Headers(), TextContent('Hello, World!'))])

    async def middleware_for_assertions(request, next_handler):
        assert b'Hello' in request.headers
        assert request.headers.get_single(b'Hello').value == b'World'

        return await next_handler(request)

    async with ClientSession(url=b'http://localhost:8080',
                             pools=fake_pools,
                             middlewares=[middleware_for_assertions
                                          ]) as client:
        await client.get(b'/', headers=[Header(b'Hello', b'World')])
        await client.post(b'/', headers=[Header(b'Hello', b'World')])
        await client.put(b'/', headers=[Header(b'Hello', b'World')])
        await client.delete(b'/', headers=[Header(b'Hello', b'World')])
Пример #12
0
def test_http_header_collection_add_multiple_times_items():
    headers = Headers()

    values = [
        Header(b'Cookie', b'Hello=World;'),
        Header(b'Cookie', b'Foo=foo;'),
        Header(b'Cookie', b'Ufo=ufo;'),
    ]

    headers.add_many(values)

    cookie_headers = headers[b'cookie']

    assert cookie_headers
    assert len(cookie_headers) == 3
    assert any(x.value == b'Hello=World;' for x in cookie_headers)
    assert any(x.value == b'Foo=foo;' for x in cookie_headers)
    assert any(x.value == b'Ufo=ufo;' for x in cookie_headers)
Пример #13
0
def test_http_header_collection_instantiating_with_dict_values(values):
    headers = Headers(list(
        Header(key, value) for key, value in values.items()))

    for key, value in values.items():
        header = headers[key]
        assert len(header) == 1
        assert header[0].name == key
        assert header[0].value == value
Пример #14
0
async def test_remove_cookie_with_expiration():
    expire_cookie = Cookie(b'X-Foo', b'Foo')
    expire_cookie.expiration = datetime.utcnow() + timedelta(days=-2)
    fake_pools = FakePools([
        Response(
            200,
            Headers([
                Header(b'Set-Cookie',
                       write_response_cookie(Cookie(b'X-Foo', b'Foo')))
            ]), TextContent('Hello, World!')),
        Response(200, Headers(), TextContent('Hello!')),
        Response(
            200,
            Headers(
                [Header(b'Set-Cookie', write_response_cookie(expire_cookie))]),
            TextContent('Hello, World!')),
        Response(200, Headers(), TextContent('Hello!'))
    ])
    expect_cookie = False

    async def middleware_for_assertions(request, next_handler):
        cookie = request.cookies.get(b'X-Foo')
        if expect_cookie:
            assert cookie is not None, 'X-Foo cookie must be configured'
        else:
            assert cookie is None

        return await next_handler(request)

    async with ClientSession(url=b'https://bezkitu.org',
                             pools=fake_pools,
                             middlewares=[middleware_for_assertions
                                          ]) as client:
        await client.get(b'/')  # <-- cookie set here
        expect_cookie = True
        await client.get(b'/')  # <-- expect cookie in request
        expect_cookie = True
        await client.get(
            b'/')  # <-- expect cookie in request; it gets removed here
        expect_cookie = False
        await client.get(
            b'/'
        )  # <-- expect missing cookie; was deleted by previous response
Пример #15
0
def test_http_header_collection_concatenation_with_other_collection():
    headers = Headers([
        Header(b'Hello', b'World'),
        Header(b'Svil', b'Power'),
    ])

    with_addition = headers + Headers([
        Header(b'Foo', b'foo'), Header(b'Ufo', b'ufo')
    ])

    for name in {b'foo', b'ufo'}:
        assert headers[name] == []

        example = with_addition[name]
        assert len(example) == 1

        header = example[0]
        assert header.name.lower() == name
        assert header.value == name
Пример #16
0
async def test_if_read_json_fails_content_type_header_is_checked_non_json_gives_invalid_operation(
):
    request = Request(b'POST', b'/',
                      Headers([Header(b'Content-Type', b'text/html')]), None)

    request.extend_body(b'{"hello":')  # broken json
    request.complete.set()

    with pytest.raises(InvalidOperation):
        await request.json()
Пример #17
0
async def test_if_read_json_fails_content_type_header_is_checked_json_gives_bad_request_format(
):
    request = Request(b'POST', b'/',
                      Headers([Header(b'Content-Type', b'application/json')]),
                      None)

    request.extend_body(b'{"hello":')  # broken json
    request.complete.set()

    with pytest.raises(BadRequestFormat):
        await request.json()
Пример #18
0
async def test_from_header_binding(expected_type, header_value,
                                   expected_value):

    request = Request(b'GET', b'/', Headers([Header(b'X-Foo', header_value)]),
                      None)

    parameter = FromHeader(expected_type, 'X-Foo')

    value = await parameter.get_value(request)

    assert isinstance(value, expected_type)
    assert value == expected_value
Пример #19
0
    async def create_cat(request):
        nonlocal called_times
        called_times += 1
        assert request is not None

        content = await request.read()
        assert b'{"name":"Celine","kind":"Persian"}' == content

        data = await request.json()
        assert {"name": "Celine", "kind": "Persian"} == data

        return Response(201, Headers([Header(b'Server', b'Python/3.7')]), JsonContent({'id': '123'}))
Пример #20
0
async def test_from_header_binding_iterables(declared_type, expected_type,
                                             header_values, expected_values):

    request = Request(
        b'GET', b'/',
        Headers([Header(b'X-Foo', value) for value in header_values]), None)

    parameter = FromHeader(declared_type, 'X-Foo')

    value = await parameter.get_value(request)

    assert isinstance(value, expected_type)
    assert value == expected_values
Пример #21
0
def test_cookie_parsing():
    request = Request(
        b'POST', b'/',
        Headers([
            Header(b'Cookie',
                   b'ai=something; hello=world; foo=Hello%20World%3B;')
        ]), None)

    assert request.cookies == {
        b'ai': b'something',
        b'hello': b'world',
        b'foo': b'Hello World;'
    }
Пример #22
0
def test_cookie_parsing_duplicated_cookie_header_value():
    request = Request(
        b'POST', b'/',
        Headers([
            Header(
                b'Cookie',
                b'ai=something; hello=world; foo=Hello%20World%3B; hello=kitty;'
            )
        ]), None)

    assert request.cookies == {
        b'ai': b'something',
        b'hello': b'kitty',
        b'foo': b'Hello World;'
    }
Пример #23
0
async def fortunes_test(request):
    """Test type 4: Fortunes"""

    connection = await db_pool.acquire()

    try:
        fortunes = await connection.fetch('SELECT * FROM Fortune')
    finally:
        await db_pool.release(connection)

    fortunes.append([0, 'Additional fortune added at request time.'])
    fortunes.sort(key=lambda x: x[1])

    return Response(200, Headers([
        Header(b'Cache-Control', b'no-cache')
    ]), content=Content(b'text/html; charset=utf-8', fortune_template.render(fortunes=fortunes).encode('utf8')))
Пример #24
0
def _file(value: Union[Callable, bytes],
          content_type: Union[str, bytes],
          content_disposition_type: ContentDispositionType,
          file_name: str = None):
    if file_name:
        exact_file_name = ntpath.basename(file_name)
        if not exact_file_name:
            raise ValueError(
                'Invalid file name: it should be an exact file name without path, for example: "foo.txt"'
            )

        content_disposition_value = f'{content_disposition_type.value}; filename="{exact_file_name}"'
    else:
        content_disposition_value = content_disposition_type.value
    response = Response(200,
                        content=Content(_ensure_bytes(content_type), value))
    response.headers.add(
        Header(b'Content-Disposition', content_disposition_value.encode()))
    return response
Пример #25
0
def get_response(html: str):
    return Response(200,
                    Headers([Header(b'Cache-Control', b'no-cache')]),
                    content=HtmlContent(html))
Пример #26
0
def redirect(location: Union[bytes, str]):
    """Returns an HTTP 302 Found response (commonly called redirect), to the given location"""
    return Response(302,
                    Headers([Header(b'Location', _ensure_bytes(location))]))
Пример #27
0
                                          ]) as client:
        await client.get(
            b'/'
        )  # the first request doesn't have any cookie because the response will set;
        check_cookie = True
        await client.get(b'/')


@pytest.mark.asyncio
@pytest.mark.parametrize(
    'first_request_url,second_request_url,set_cookies,expected_cookies',
    [[
        b'https://foo.bezkitu.org', b'https://bezkitu.org',
        [
            Header(
                b'Set-Cookie',
                write_response_cookie(
                    Cookie(b'X-Foo', b'Foo', domain=b'bezkitu.org')))
        ], [b'X-Foo']
    ],
     [
         b'https://foo.bezkitu.org', b'https://foo.bezkitu.org',
         [
             Header(
                 b'Set-Cookie',
                 write_response_cookie(
                     Cookie(b'X-Foo', b'Foo', domain=b'foo.bezkitu.org')))
         ], [b'X-Foo']
     ],
     [
         b'https://foo.bezkitu.org', b'https://bezkitu.org',
         [
Пример #28
0
def see_other(location: Union[bytes, str]):
    """Returns an HTTP 303 See Other response, to the given location."""
    return Response(303,
                    Headers([Header(b'Location', _ensure_bytes(location))]))
Пример #29
0
def temporary_redirect(location: Union[bytes, str]):
    """Returns an HTTP 307 Temporary Redirect response, to the given location."""
    return Response(307,
                    Headers([Header(b'Location', _ensure_bytes(location))]))
Пример #30
0
import pytest
from pytest import raises
from typing import List, Sequence, Set, Tuple
from blacksheep import Request, Headers, Header, JsonContent
from blacksheep.server.bindings import (FromJson, FromHeader, FromQuery,
                                        FromRoute, FromServices, RequestBinder,
                                        InvalidRequestBody,
                                        MissingConverterError, BadRequest)

JsonContentType = Header(b'Content-Type', b'application/json')


class ExampleOne:
    def __init__(self, a, b):
        self.a = a
        self.b = b


class ExampleTwo:
    def __init__(self, a, b, **kwargs):
        self.a = a
        self.b = b


@pytest.mark.asyncio
async def test_from_body_json_binding():

    request = Request(b'POST', b'/', Headers([JsonContentType]),
                      JsonContent({
                          'a': 'world',
                          'b': 9000