Ejemplo n.º 1
0
def _file(value: FileInput,
          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

    content_type = _ensure_bytes(content_type)

    if isinstance(value, str):
        # value is treated as a path
        content = StreamedContent(content_type, _get_file_provider(value))
    elif isinstance(value, BytesIO):

        async def data_provider():
            while True:
                chunk = value.read(1024 * 64)

                if not chunk:
                    break

                yield chunk
            yield b''

        content = StreamedContent(content_type, data_provider)
    elif callable(value):
        # value is treated as an async generator
        async def data_provider():
            async for chunk in value():
                yield chunk
            yield b''

        content = StreamedContent(content_type, data_provider)
    elif isinstance(value, bytes):
        content = Content(content_type, value)
    elif isinstance(value, bytearray):
        content = Content(content_type, bytes(value))
    else:
        raise ValueError(
            'Invalid value, expected one of: Callable, str, bytes, bytearray, io.BytesIO'
        )

    return Response(
        200, [(b'Content-Disposition', content_disposition_value.encode())],
        content)
Ejemplo n.º 2
0
async def multiple_db_queries_test(request):
    """Test type 3: Multiple Database Queries"""

    num_queries = get_num_queries(request)

    row_ids = [randint(1, 10000) for _ in range(num_queries)]
    worlds = []

    connection = await db_pool.acquire()
    try:
        statement = await connection.prepare(
            'SELECT "randomnumber" FROM "world" WHERE id = $1'
        )
        for row_id in row_ids:
            number = await statement.fetchval(row_id)
            worlds.append({"id": row_id, "randomNumber": number})
    finally:
        await db_pool.release(connection)

    return Response(
        200,
        content=Content(
            b"application/json; charset=utf-8", json_dumps(worlds).encode("utf-8")
        ),
    )
Ejemplo n.º 3
0
async def test_if_read_json_fails_content_type_header_is_checked_json_gives_bad_request_format():
    request = Request("POST", b"/", [(b"Content-Type", b"application/json")])

    request.with_content(Content(b"application/json", b'{"hello":'))  # broken json

    with pytest.raises(BadRequestFormat):
        await request.json()
Ejemplo n.º 4
0
async def home(url: str, request: Request):
    headers = request.headers
    proxy_query_header = make_request_headers(headers)

    try:
        async with httpx.AsyncClient() as client:
            proxy_response = await client.get(url,
                                              headers=proxy_query_header,
                                              timeout=TIMEOUT)

    except requests.exceptions.SSLError:
        # Invalid SSL Certificate
        status = 526
    except requests.exceptions.ConnectionError:
        status = 523
    except requests.exceptions.Timeout:
        status = 524
    except requests.exceptions.TooManyRedirects:
        status = 520
    else:
        body = proxy_response.content
        if proxy_response.status_code == 500:
            status = 520
        else:
            status = 200

    headers = []
    if status == 200:
        # copy_proxy_headers(proxy_response, response)
        headers += [(b"Access-Control-Allow-Origin", get_access_url(headers))]

    response = blacksheep.Response(status,
                                   content=Content(b"text/html", body),
                                   headers=headers)
    return response
Ejemplo n.º 5
0
def html(value: str, status: int = 200) -> Response:
    """
    Returns a response with text/html content,
    and given status (default HTTP 200 OK).
    """
    return Response(status, None,
                    Content(b"text/html; charset=utf-8", value.encode("utf8")))
Ejemplo n.º 6
0
async def test_can_read_json_data_even_without_content_type_header():
    request = Request("POST", b"/", None)

    request.with_content(Content(b"application/json", b'{"hello":"world","foo":false}'))

    json = await request.json()
    assert json == {"hello": "world", "foo": False}
Ejemplo n.º 7
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)))
Ejemplo n.º 8
0
async def db_updates_test(request):
    """Test type 5: Database Updates"""

    num_queries = get_num_queries(request)

    updates = [(randint(1, 10000), randint(1, 10000))
               for _ in range(num_queries)]
    worlds = [{
        'id': row_id,
        'randomNumber': number
    } for row_id, number in updates]

    connection = await db_pool.acquire()
    try:
        statement = await connection.prepare(
            'SELECT "randomnumber" FROM "world" WHERE id = $1')
        for row_id, _ in updates:
            await statement.fetchval(row_id)
        await connection.executemany(
            'UPDATE "world" SET "randomnumber"=$1 WHERE id=$2', updates)
    finally:
        await db_pool.release(connection)

    return Response(200,
                    content=Content(b'application/json',
                                    json_dumps(worlds).encode('utf-8')))
Ejemplo n.º 9
0
async def test_if_read_json_fails_content_type_header_is_checked_non_json_gives_invalid_operation():
    request = Request('POST', b'/', [])

    request.with_content(Content(b'text/html', b'{"hello":'))  # broken json; broken content-type

    with pytest.raises(InvalidOperation):
        await request.json()
Ejemplo n.º 10
0
async def test_if_read_json_fails_content_type_header_is_checked_non_json_gives_invalid_operation(
):
    request = Request("POST", b"/", [])

    request.with_content(Content(
        b"text/html", b'{"hello":'))  # broken json; broken content-type

    with pytest.raises(BadRequestFormat):
        await request.json()
Ejemplo n.º 11
0
async def json_test(request):
    """Test type 1: JSON Serialization"""

    return Response(200,
                    content=Content(
                        b'application/json; charset=utf-8',
                        json_dumps({
                            'message': 'Hello, world!'
                        }).encode('utf-8')))
Ejemplo n.º 12
0
    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))
Ejemplo n.º 13
0
async def json_test(request):
    """Test type 1: JSON Serialization"""

    return Response(
        200,
        content=Content(
            b"application/json; charset=utf-8",
            json_dumps({"message": "Hello, world!"}).encode("utf-8"),
        ),
    )
Ejemplo n.º 14
0
async def single_db_query_test(request):
    """Test type 2: Single Database Query"""

    row_id = randint(1, 10000)
    connection = await db_pool.acquire()
    try:
        number = await connection.fetchval('SELECT "randomnumber" FROM "world" WHERE id = $1', row_id)
        world = {'id': row_id, 'randomNumber': number}
    finally:
        await db_pool.release(connection)

    return Response(200, content=Content(b'application/json; charset=utf-8',
                                         json_dumps(world).encode('utf-8')))
Ejemplo n.º 15
0
def json(data: Any, status: int = 200, dumps=friendly_dumps) -> Response:
    """
    Returns a response with application/json content,
    and given status (default HTTP 200 OK).
    """
    return Response(
        status,
        None,
        Content(
            b"application/json",
            dumps(data, cls=FriendlyEncoder,
                  separators=(",", ":")).encode("utf8"),
        ),
    )
Ejemplo n.º 16
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')))
Ejemplo n.º 17
0
def pretty_json(data: Any,
                status: int = 200,
                dumps=friendly_dumps,
                indent: int = 4) -> Response:
    """
    Returns a response with indented application/json content,
    and given status (default HTTP 200 OK).
    """
    return Response(
        status,
        None,
        Content(
            b"application/json",
            dumps(data, cls=FriendlyEncoder, indent=indent).encode("utf8"),
        ),
    )
Ejemplo n.º 18
0
async def test_chunked_encoding_with_generated_content():
    def data_generator():
        yield b'{"hello":"world",'
        yield b'"lorem":'
        yield b'"ipsum","dolor":"sit"'
        yield b',"amet":"consectetur"}'

    content = Content(b'application/json', data_generator)

    gen = data_generator()

    async for chunk in write_chunks(content):
        try:
            generator_bytes = next(gen)
        except StopIteration:
            assert chunk == b'0\r\n\r\n'
        else:
            assert chunk == hex(len(generator_bytes))[2:].encode() \
                   + b'\r\n' + generator_bytes + b'\r\n'
Ejemplo n.º 19
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
Ejemplo n.º 20
0
    foo = object()

    assert (
        hasattr(response, "response") is False
    ), "This test makes sense if such attribute is not defined"
    response.foo = foo  # type: ignore
    assert response.foo is foo  # type: ignore


@pytest.mark.asyncio
@pytest.mark.parametrize(
    "response,cookies,expected_result",
    [
        (
            Response(400, [(b"Server", b"BlackSheep")]).with_content(
                Content(b"text/plain", b"Hello, World")
            ),
            [],
            b"HTTP/1.1 400 Bad Request\r\n"
            b"Server: BlackSheep\r\n"
            b"content-type: text/plain\r\n"
            b"content-length: 12\r\n\r\nHello, World",
        ),
        (
            Response(400, [(b"Server", b"BlackSheep")]).with_content(
                Content(b"text/plain", b"Hello, World")
            ),
            [Cookie("session", "123")],
            b"HTTP/1.1 400 Bad Request\r\n"
            b"Server: BlackSheep\r\n"
            b"set-cookie: session=123\r\n"
Ejemplo n.º 21
0
async def echo_streamed_test(request):
    async def echo():
        async for chunk in request.stream():
            yield chunk

    return Response(200, content=Content(b'text/plain; charset=utf-8', echo))
Ejemplo n.º 22
0
def test_response_supports_dynamic_attributes():
    response = Response(200)
    foo = object()

    assert hasattr(response, 'response') is False, 'This test makes sense if such attribute is not defined'
    response.foo = foo
    assert response.foo is foo


@pytest.mark.asyncio
@pytest.mark.parametrize('response,cookies,expected_result', [
    (
        Response(400, [
            (b'Server', b'BlackSheep'),
        ]).with_content(Content(b'text/plain', b'Hello, World')),
        [],
        b'HTTP/1.1 400 Bad Request\r\n'
        b'Server: BlackSheep\r\n'
        b'content-type: text/plain\r\n'
        b'content-length: 12\r\n\r\nHello, World'
    ),
    (
        Response(400, [
            (b'Server', b'BlackSheep'),
        ]).with_content(Content(b'text/plain', b'Hello, World')),
        [Cookie(b'session', b'123')],
        b'HTTP/1.1 400 Bad Request\r\n'
        b'Server: BlackSheep\r\n'
        b'set-cookie: session=123\r\n'
        b'content-type: text/plain\r\n'
Ejemplo n.º 23
0
    response = Response(200)
    foo = object()

    assert hasattr(
        response, 'response'
    ) is False, 'This test makes sense if such attribute is not defined'
    response.foo = foo
    assert response.foo is foo


@pytest.mark.asyncio
@pytest.mark.parametrize(
    'response,cookies,expected_result',
    [(Response(400, Headers([
        Header(b'Server', b'BlackSheep'),
    ]), Content(b'text/plain',
                b'Hello, World')), [], b'HTTP/1.1 400 Bad Request\r\n'
      b'Server: BlackSheep\r\n'
      b'Content-Type: text/plain\r\n'
      b'Content-Length: 12\r\n\r\nHello, World'),
     (Response(400, Headers([
         Header(b'Server', b'BlackSheep'),
     ]), Content(b'text/plain', b'Hello, World')),
      [Cookie(b'session', b'123')], b'HTTP/1.1 400 Bad Request\r\n'
      b'Server: BlackSheep\r\n'
      b'Content-Type: text/plain\r\n'
      b'Content-Length: 12\r\n'
      b'Set-Cookie: session=123\r\n\r\nHello, World'),
     (Response(400, Headers([Header(b'Server', b'BlackSheep')]),
               Content(b'text/plain', b'Hello, World')), [
                   Cookie(b'session', b'123'),
                   Cookie(b'aaa', b'bbb', domain=b'bezkitu.org')
Ejemplo n.º 24
0
def pretty_json(data: Any, status: int = 200, dumps=JSON.dumps, indent: int = 4):
    """Returns a response with indented application/json content, and given status (default HTTP 200 OK)."""
    return Response(status, None, Content(b'application/json', dumps(data, indent=indent).encode('utf8')))
Ejemplo n.º 25
0
def text(value: str, status: int = 200):
    """Returns a response with text/plain content, and given status (default HTTP 200 OK)."""
    return Response(status, None, Content(b'text/plain; charset=utf-8', value.encode('utf8')))
Ejemplo n.º 26
0
async def plaintext_test(request):
    """Test type 6: Plaintext"""

    return Response(200, content=Content(b'text/plain', b'Hello, World!'))
Ejemplo n.º 27
0
def json(data: Any, status: int = 200, dumps=JSON.dumps):
    """Returns a response with application/json content, and given status (default HTTP 200 OK)."""
    return Response(status, None, Content(b'application/json', dumps(data, separators=(',', ':')).encode('utf8')))
Ejemplo n.º 28
0
def get_response(html: str):
    return Response(200, [(b"Cache-Control", b"no-cache")]).with_content(
        Content(b"text/html; charset=utf-8", html.encode("utf8"))
    )
Ejemplo n.º 29
0
def get_response(html: str):
    return Response(200, [
        (b'Cache-Control', b'no-cache')
    ]).with_content(Content(b'text/html; charset=utf-8', html.encode('utf8')))
Ejemplo n.º 30
0
async def plaintext_test(request):
    """Test type 6: Plaintext"""

    return Response(200, content=Content(b"text/plain", b"Hello, World!"))