Ejemplo n.º 1
0
def to_response(
    status_code: int = 200,
    http_version: str = "HTTP/1.1",
    headers: dict = None,
    data=None,
    files=None,
    json: Any = None,
    boundary: bytes = None,
) -> Response:
    """
    Convert to a valid httpcore response.

    :param status_code: HTTP status code of the response. Default to 200 (OK).
    :param http_version: HTTP protocol version of the response. Default to HTTP/1.1
    :param headers: HTTP headers of the response. Default to no headers.
    :param data: HTTP body of the response, can be an iterator to stream content, bytes, str of the full body or
    a dictionary in case of a multipart.
    :param files: Multipart files.
    :param json: HTTP body of the response (if JSON should be used as content type) if data is not provided.
    :param boundary: Multipart boundary if files is provided.
    """
    return (
        http_version.encode(),
        status_code,
        b"",
        [(header.encode(), value.encode())
         for header, value in headers.items()] if headers else [],
        encode(data=data, files=files, json=json, boundary=boundary),
    )
Ejemplo n.º 2
0
async def test_multipart_files_content():
    files = {"file": io.BytesIO(b"<file content>")}
    stream = encode(files=files, boundary=b"+++")
    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert stream.can_replay()
    assert stream.get_headers() == {
        "Content-Length": "138",
        "Content-Type": "multipart/form-data; boundary=+++",
    }
    assert sync_content == b"".join([
        b"--+++\r\n",
        b'Content-Disposition: form-data; name="file"; filename="upload"\r\n',
        b"Content-Type: application/octet-stream\r\n",
        b"\r\n",
        b"<file content>\r\n",
        b"--+++--\r\n",
    ])
    assert async_content == b"".join([
        b"--+++\r\n",
        b'Content-Disposition: form-data; name="file"; filename="upload"\r\n',
        b"Content-Type: application/octet-stream\r\n",
        b"\r\n",
        b"<file content>\r\n",
        b"--+++--\r\n",
    ])
Ejemplo n.º 3
0
def test_multipart_encode(tmp_path: typing.Any) -> None:
    path = str(tmp_path / "name.txt")
    with open(path, "wb") as f:
        f.write(b"<file content>")

    data = {
        "a": "1",
        "b": b"C",
        "c": ["11", "22", "33"],
        "d": "",
    }
    files = {"file": ("name.txt", open(path, "rb"))}

    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = os.urandom(16).hex()

        stream = encode(data=data, files=files)
        assert isinstance(stream, MultipartStream)
        assert stream.can_replay()

        assert stream.content_type == f"multipart/form-data; boundary={boundary}"
        content = (
            '--{0}\r\nContent-Disposition: form-data; name="a"\r\n\r\n1\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="b"\r\n\r\nC\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="c"\r\n\r\n11\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="c"\r\n\r\n22\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="c"\r\n\r\n33\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="d"\r\n\r\n\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="file";'
            ' filename="name.txt"\r\n'
            "Content-Type: text/plain\r\n\r\n<file content>\r\n"
            "--{0}--\r\n"
            "".format(boundary).encode("ascii"))
        assert stream.get_headers()["Content-Length"] == str(len(content))
        assert b"".join(stream) == content
Ejemplo n.º 4
0
def test_multipart_encode():
    data = {
        "a": "1",
        "b": b"C",
        "c": ["11", "22", "33"],
        "d": "",
    }
    files = {"file": ("name.txt", io.BytesIO(b"<file content>"))}

    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = binascii.hexlify(os.urandom(16)).decode("ascii")
        stream = encode(data=data, files=files)
        assert stream.content_type == f"multipart/form-data; boundary={boundary}"
        assert stream.body == (
            '--{0}\r\nContent-Disposition: form-data; name="a"\r\n\r\n1\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="b"\r\n\r\nC\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="c"\r\n\r\n11\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="c"\r\n\r\n22\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="c"\r\n\r\n33\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="d"\r\n\r\n\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="file";'
            ' filename="name.txt"\r\n'
            "Content-Type: text/plain\r\n\r\n<file content>\r\n"
            "--{0}--\r\n"
            "".format(boundary).encode("ascii"))
Ejemplo n.º 5
0
async def test_empty_content():
    stream = encode()
    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert stream.can_replay()
    assert stream.get_headers() == {}
    assert sync_content == b""
    assert async_content == b""
Ejemplo n.º 6
0
async def test_bytes_content():
    stream = encode(data=b"Hello, world!")
    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert stream.can_replay()
    assert stream.get_headers() == {"Content-Length": "13"}
    assert sync_content == b"Hello, world!"
    assert async_content == b"Hello, world!"
Ejemplo n.º 7
0
async def test_empty_request():
    stream = encode(data={}, files={})
    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert stream.can_replay()
    assert stream.get_headers() == {
        "Content-Length": "0",
    }
    assert sync_content == b""
    assert async_content == b""
Ejemplo n.º 8
0
async def test_json_content():
    stream = encode(json={"Hello": "world!"})
    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert stream.can_replay()
    assert stream.get_headers() == {
        "Content-Length": "19",
        "Content-Type": "application/json",
    }
    assert sync_content == b'{"Hello": "world!"}'
    assert async_content == b'{"Hello": "world!"}'
Ejemplo n.º 9
0
async def test_urlencoded_content():
    stream = encode(data={"Hello": "world!"})
    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert stream.can_replay()
    assert stream.get_headers() == {
        "Content-Length": "14",
        "Content-Type": "application/x-www-form-urlencoded",
    }
    assert sync_content == b"Hello=world%21"
    assert async_content == b"Hello=world%21"
Ejemplo n.º 10
0
def test_multipart_encode_files_allows_filenames_as_none():
    files = {"file": (None, io.BytesIO(b"<file content>"))}
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = binascii.hexlify(os.urandom(16)).decode("ascii")

        stream = encode(data={}, files=files)

        assert stream.content_type == f"multipart/form-data; boundary={boundary}"
        assert stream.body == (
            '--{0}\r\nContent-Disposition: form-data; name="file"\r\n\r\n'
            "<file content>\r\n--{0}--\r\n"
            "".format(boundary).encode("ascii"))
Ejemplo n.º 11
0
def test_multipart_encode_files_allows_filenames_as_none() -> None:
    files = {"file": (None, io.BytesIO(b"<file content>"))}
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = os.urandom(16).hex()

        stream = encode(data={}, files=files)
        assert isinstance(stream, MultipartStream)
        assert stream.can_replay()

        assert stream.content_type == f"multipart/form-data; boundary={boundary}"
        assert b"".join(stream) == (
            '--{0}\r\nContent-Disposition: form-data; name="file"\r\n\r\n'
            "<file content>\r\n--{0}--\r\n"
            "".format(boundary).encode("ascii"))
Ejemplo n.º 12
0
def test_multipart_encode_files_guesses_correct_content_type(
        file_name, expected_content_type):
    files = {"file": (file_name, io.BytesIO(b"<file content>"))}
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = binascii.hexlify(os.urandom(16)).decode("ascii")

        stream = encode(data={}, files=files)

        assert stream.content_type == f"multipart/form-data; boundary={boundary}"
        assert stream.body == (
            f'--{boundary}\r\nContent-Disposition: form-data; name="file"; '
            f'filename="{file_name}"\r\nContent-Type: '
            f"{expected_content_type}\r\n\r\n<file content>\r\n--{boundary}--\r\n"
            "".encode("ascii"))
Ejemplo n.º 13
0
def test_multipart_encode_files_allows_str_content():
    files = {"file": ("test.txt", "<string content>", "text/plain")}
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = binascii.hexlify(os.urandom(16)).decode("ascii")

        stream = encode(data={}, files=files)

        assert stream.content_type == f"multipart/form-data; boundary={boundary}"
        assert stream.body == (
            '--{0}\r\nContent-Disposition: form-data; name="file"; '
            'filename="test.txt"\r\n'
            "Content-Type: text/plain\r\n\r\n<string content>\r\n"
            "--{0}--\r\n"
            "".format(boundary).encode("ascii"))
Ejemplo n.º 14
0
def test_multipart_encode_files_guesses_correct_content_type(
        file_name: str, expected_content_type: str) -> None:
    files = {"file": (file_name, io.BytesIO(b"<file content>"))}
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = os.urandom(16).hex()

        stream = encode(data={}, files=files)
        assert isinstance(stream, MultipartStream)
        assert stream.can_replay()

        assert stream.content_type == f"multipart/form-data; boundary={boundary}"
        assert b"".join(stream) == (
            f'--{boundary}\r\nContent-Disposition: form-data; name="file"; '
            f'filename="{file_name}"\r\nContent-Type: '
            f"{expected_content_type}\r\n\r\n<file content>\r\n--{boundary}--\r\n"
            "".encode("ascii"))
Ejemplo n.º 15
0
async def test_aiterator_content():
    async def hello_world():
        yield b"Hello, "
        yield b"world!"

    stream = encode(data=hello_world())
    content = b"".join([part async for part in stream])

    assert not stream.can_replay()
    assert stream.get_headers() == {"Transfer-Encoding": "chunked"}
    assert content == b"Hello, world!"

    with pytest.raises(RuntimeError):
        [part for part in stream]

    with pytest.raises(StreamConsumed):
        [part async for part in stream]
Ejemplo n.º 16
0
def test_multipart_encode_files_allows_bytes_or_str_content(
        value: typing.Union[str, bytes], output: str) -> None:
    files = {"file": ("test.txt", value, "text/plain")}
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = binascii.hexlify(os.urandom(16)).decode("ascii")

        stream = encode(data={}, files=files)
        assert stream.can_replay()

        assert stream.content_type == f"multipart/form-data; boundary={boundary}"
        content = ('--{0}\r\nContent-Disposition: form-data; name="file"; '
                   'filename="test.txt"\r\n'
                   "Content-Type: text/plain\r\n\r\n{1}\r\n"
                   "--{0}--\r\n"
                   "".format(boundary, output).encode("ascii"))
        assert stream.get_headers()["Content-Length"] == str(len(content))
        assert b"".join(stream) == content
Ejemplo n.º 17
0
    def __init__(self, **kwargs):
        data = {
            'body': {},
            'headers': {},
            'path': {},
            'query': {},
        }
        data['header'] = data['headers']
        skip_validation = kwargs.pop('esi_skip_validation', False)
        errors = {}
        for param in self.params:
            value = kwargs.pop(param.safe_name)
            if value == param.default:
                continue
            try:
                param.validate(value)
            except ValidationError as e:
                e.update_error_dict(errors, param.safe_name)
            data[param.part][param.name] = value
        if errors and not skip_validation:
            raise ValidationError(errors)

        cls = self.__class__
        body = None
        if data['body']:
            body = list(data['body'].values())[0]

        self.method = cls.method.upper()
        self.url = URL(self.path.format(**data['path']),
                       allow_relative=True,
                       params=data['query'])
        self.headers = Headers(data['header'])
        self.stream = encode(body, None, None)
        self.timer = ElapsedTimer()
        self.prepare()
        # Clear out headers we don't need (These will be set by the session)
        for key in ["User-Agent"]:
            if key in self.headers:
                del self.headers[key]
Ejemplo n.º 18
0
def test_multipart_encode_non_seekable_filelike() -> None:
    """
    Test that special readable but non-seekable filelike objects are supported,
    at the cost of reading them into memory at most once.
    """

    class IteratorIO(io.IOBase):
        def __init__(self, iterator: typing.Iterator[bytes]) -> None:
            self._iterator = iterator

        def seekable(self) -> bool:
            return False

        def read(self, *args: typing.Any) -> bytes:
            return b"".join(self._iterator)

    def data() -> typing.Iterator[bytes]:
        yield b"Hello"
        yield b"World"

    fileobj = IteratorIO(data())
    files = {"file": fileobj}
    stream = encode(files=files, boundary=b"+++")
    assert not stream.can_replay()

    content = (
        b"--+++\r\n"
        b'Content-Disposition: form-data; name="file"; filename="upload"\r\n'
        b"Content-Type: application/octet-stream\r\n"
        b"\r\n"
        b"HelloWorld\r\n"
        b"--+++--\r\n"
    )
    assert stream.get_headers() == {
        "Content-Type": "multipart/form-data; boundary=+++",
        "Content-Length": str(len(content)),
    }
    assert b"".join(stream) == content
Ejemplo n.º 19
0
def test_invalid_argument():
    with pytest.raises(TypeError):
        encode(123)  # type: ignore