Example #1
0
def test_stream_response_writes_correct_content_to_transport(streaming_app):
    response = StreamingHTTPResponse(sample_streaming_fn)
    response.protocol = MagicMock(HttpProtocol)
    response.protocol.transport = MagicMock(asyncio.Transport)

    async def mock_drain():
        pass

    def mock_push_data(data):
        response.protocol.transport.write(data)

    response.protocol.push_data = mock_push_data
    response.protocol.drain = mock_drain

    @streaming_app.listener('after_server_start')
    async def run_stream(app, loop):
        await response.stream()
        assert response.protocol.transport.write.call_args_list[1][0][0] == (
            b'4\r\nfoo,\r\n')

        assert response.protocol.transport.write.call_args_list[2][0][0] == (
            b'3\r\nbar\r\n')

        assert response.protocol.transport.write.call_args_list[3][0][0] == (
            b'0\r\n\r\n')

        app.stop()

    streaming_app.run(host=HOST, port=PORT)
Example #2
0
def test_stream_response_keep_alive_returns_correct_headers(
        keep_alive_timeout):
    response = StreamingHTTPResponse(sample_streaming_fn)
    headers = response.get_headers(keep_alive=True,
                                   keep_alive_timeout=keep_alive_timeout)

    assert b"Keep-Alive: %s\r\n" % str(keep_alive_timeout).encode() in headers
Example #3
0
def test_stream_response_keep_alive_returns_correct_headers(
        keep_alive_timeout):
    response = StreamingHTTPResponse(sample_streaming_fn)
    headers = response.get_headers(
        keep_alive=True, keep_alive_timeout=keep_alive_timeout)

    assert b"Keep-Alive: %s\r\n" % str(keep_alive_timeout).encode() in headers
Example #4
0
def test_stream_response_writes_correct_content_to_transport_when_not_chunked(
    streaming_app,
):
    response = StreamingHTTPResponse(sample_streaming_fn)
    response.protocol = MagicMock(HttpProtocol)
    response.protocol.transport = MagicMock(asyncio.Transport)

    async def mock_drain():
        pass

    def mock_push_data(data):
        response.protocol.transport.write(data)

    response.protocol.push_data = mock_push_data
    response.protocol.drain = mock_drain

    @streaming_app.listener("after_server_start")
    async def run_stream(app, loop):
        await response.stream(version="1.0")
        assert response.protocol.transport.write.call_args_list[1][0][0] == (
            b"foo,"
        )

        assert response.protocol.transport.write.call_args_list[2][0][0] == (
            b"bar"
        )

        assert len(response.protocol.transport.write.call_args_list) == 3

        app.stop()

    streaming_app.run(host=HOST, port=PORT)
Example #5
0
    async def process(self):
        request = self.request
        headers = (
            ('Connection', request.headers.get('Connection', "close")),
            ('Content-Type', "application/javascript; charset=UTF-8"),
            ('Cache-Control', CACHE_CONTROL),
        )

        headers += session_cookie(request)
        headers += cors_headers(request.headers)

        if request.method == 'OPTIONS':
            headers += (('Access-Control-Allow-Methods', "OPTIONS, POST"), )
            headers += cache_headers()
            return HTTPResponse(None, status=204, headers=headers)

        async def stream(_response):
            nonlocal self
            self.response = _response
            await _response.write(self.open_seq)
            # event loop
            await self.handle_session()

        # open sequence (sockjs protocol)
        return StreamingHTTPResponse(stream, headers=headers)
Example #6
0
    async def process(self):
        request = self.request

        if request.method == 'OPTIONS':
            headers = (
                ('Content-Type', "application/javascript; charset=UTF-8"),
                ('Access-Control-Allow-Methods', "OPTIONS, POST"),
            )
            headers += session_cookie(request)
            headers += cors_headers(request.headers)
            headers += cache_headers()
            return HTTPResponse(None, status=204, headers=headers)

        headers = (
            ('Content-Type', "application/javascript; charset=UTF-8"),
            ('Cache-Control', CACHE_CONTROL),
        )
        headers += session_cookie(request)
        headers += cors_headers(request.headers)

        async def stream(_response):
            nonlocal self
            self.response = _response
            await self.handle_session()

        return StreamingHTTPResponse(stream, headers=headers)
Example #7
0
    async def process(self):
        request = self.request

        try:
            callback = request.query_args.get("c", None)
        except Exception:
            callback = request.args.get("c", None)

        if callback is None:
            await self.session._remote_closed()
            raise exceptions.ServerError('"callback" parameter required')

        elif not self.check_callback.match(callback):
            await self.session._remote_closed()
            raise exceptions.ServerError('invalid "callback" parameter')

        headers = (
            ('Content-Type', "text/html; charset=UTF-8"),
            ('Cache-Control', CACHE_CONTROL),
            ('Connection', "close"),
        )
        headers += session_cookie(request)
        headers += cors_headers(request.headers)

        async def stream(_response):
            nonlocal self
            self.response = _response
            await _response.write(b"".join(
                (PRELUDE1, callback.encode("utf-8"), PRELUDE2, b" " * 1024)))
            # handle session
            await self.handle_session()

        # open sequence (sockjs protocol)
        return StreamingHTTPResponse(stream, headers=headers)
async def test_handle_session_interrupted(make_transport, make_fut):
    trans = make_transport()
    trans.session.interrupted = True
    trans.send = make_fut(1)
    trans.response = StreamingHTTPResponse(make_fut(0))
    await trans.handle_session()
    trans.send.assert_called_with('c[1002,"Connection interrupted"]')
Example #9
0
    def sendAudioFiles(self, location):

        status = 200
        chunk_size = 4096
        mime_type = None
        headers = None
        filename = None
        chunked = True
        _range = None
        """Return a streaming response object with file data.
    
        :param location: Location of file on system.
        :param chunk_size: The size of each chunk in the stream (in bytes)
        :param mime_type: Specific mime_type.
        :param headers: Custom Headers.
        :param filename: Override filename.
        :param chunked: Enable or disable chunked transfer-encoding
        :param _range:
        """
        headers = headers or {}
        if filename:
            headers.setdefault("Content-Disposition",
                               f'attachment; filename="{filename}"')
        filename = filename or path.split(location)[-1]
        mime_type = mime_type or guess_type(filename)[0] or "text/plain"
        if _range:
            start = _range.start
        end = _range.end
        total = _range.total

        headers["Content-Range"] = f"bytes {start}-{end}/{total}"
        status = 206

        async def _streaming_fn(response):
            async with await open_async(location, mode="rb") as f:
                if _range:
                    await f.seek(_range.start)
                    to_send = _range.size
                    while to_send > 0:
                        content = await f.read(min((_range.size, chunk_size)))
                        if len(content) < 1:
                            break
                        to_send -= len(content)
                        await response.write(content)
                else:
                    while True:
                        content = await f.read(chunk_size)
                        if len(content) < 1:
                            break
                        await response.write(content)

        return StreamingHTTPResponse(
            streaming_fn=_streaming_fn,
            status=status,
            headers=headers,
            content_type=mime_type,
            chunked=chunked,
        )
Example #10
0
            async def wrapped(*args, **kwargs):
                if asyncio.iscoroutinefunction(func):
                    coro = func
                else:
                    coro = asyncio.coroutine(func)

                context = await coro(*args, **kwargs)

                # wrapped function return HTTPResponse
                # instead of dict-like object
                if isinstance(context, HTTPResponse):
                    return context

                # wrapped function is class method
                # and got `self` as first argument
                if isinstance(args[0], HTTPMethodView):
                    request = args[1]
                else:
                    request = args[0]

                if context is None:
                    context = {}

                env = getattr(request.app, 'jinja_env', None)
                if not env:
                    raise ServerError(
                        "Template engine has not been initialized yet.",
                        status_code=500,
                    )
                try:
                    template = env.get_template(template_name)
                except TemplateNotFound as e:
                    raise ServerError(
                        "Template '{}' not found".format(template_name),
                        status_code=500,
                    )
                if not isinstance(context, Mapping):
                    raise ServerError(
                        "context should be mapping, not {}".format(
                            type(context)),
                        status_code=500,
                    )
                # if request.get(REQUEST_CONTEXT_KEY):
                #     context = dict(request[REQUEST_CONTEXT_KEY], **context)
                update_request_context(request, context)

                content_type = "text/html; charset={}".format(encoding)

                async def do_response(response):
                    async for chunk in template.generate_async(context):
                        await response.write(chunk)

                return StreamingHTTPResponse(
                    do_response, status=status, headers=headers,
                    content_type=content_type
                )
Example #11
0
def test_stream_response_writes_correct_content_to_transport(streaming_app):
    response = StreamingHTTPResponse(sample_streaming_fn)
    response.transport = MagicMock(asyncio.Transport)

    @streaming_app.listener('after_server_start')
    async def run_stream(app, loop):
        await response.stream()
        assert response.transport.write.call_args_list[1][0][0] == (
            b'4\r\nfoo,\r\n')

        assert response.transport.write.call_args_list[2][0][0] == (
            b'3\r\nbar\r\n')

        assert response.transport.write.call_args_list[3][0][0] == (
            b'0\r\n\r\n')

        app.stop()

    streaming_app.run(host=HOST, port=PORT)
async def test_handle_session_closed(make_transport, make_fut):
    trans = make_transport()
    trans.send = make_fut(1)
    trans.session.interrupted = False
    trans.session.state = protocol.STATE_CLOSED
    trans.session._remote_closed = make_fut(1)
    trans.response = StreamingHTTPResponse(make_fut(0))
    await trans.handle_session()
    trans.session._remote_closed.assert_called_with()
    trans.send.assert_called_with('c[3000,"Go away!"]')
Example #13
0
def test_stream_response_writes_correct_content_to_transport(streaming_app):
    response = StreamingHTTPResponse(sample_streaming_fn)
    response.transport = MagicMock(asyncio.Transport)

    @streaming_app.listener('after_server_start')
    async def run_stream(app, loop):
        await response.stream()
        assert response.transport.write.call_args_list[1][0][0] == (
            b'4\r\nfoo,\r\n'
        )

        assert response.transport.write.call_args_list[2][0][0] == (
            b'3\r\nbar\r\n'
        )

        assert response.transport.write.call_args_list[3][0][0] == (
            b'0\r\n\r\n'
        )

        app.stop()

    streaming_app.run(host=HOST, port=PORT)
Example #14
0
def test_on_response_streaming_http_response():
    class MockRequest:
        method = 'GET'
        url = 'http://localhost'

    req = MockRequest()
    resp = StreamingHTTPResponse(None)

    contextvars.bind_contextvars(request_id='test-request', )
    ctx = contextvars._CONTEXT_VARS
    assert 'test-request' == ctx['structlog_request_id'].get()

    app.on_response(req, resp)

    ctx = contextvars._CONTEXT_VARS
    assert ctx['structlog_request_id'].get() is Ellipsis
Example #15
0
    async def process(self):
        headers = (
            ('Content-Type', "text/event-stream"),
            ('Cache-Control', CACHE_CONTROL),
        )
        headers += session_cookie(self.request)

        async def stream(_response):
            nonlocal self
            self.response = _response
            await _response.write(b"\r\n")
            # handle session
            await self.handle_session()

        # open sequence (sockjs protocol)
        return StreamingHTTPResponse(stream, headers=headers)
Example #16
0
def test_stream_response_includes_chunked_header():
    response = StreamingHTTPResponse(sample_streaming_fn)
    headers = response.get_headers()
    assert b"Transfer-Encoding: chunked\r\n" in headers
Example #17
0
def test_stream_response_includes_chunked_header():
    response = StreamingHTTPResponse(sample_streaming_fn)
    headers = response.get_headers()
    assert b"Transfer-Encoding: chunked\r\n" in headers
Example #18
0
def test_stream_response_status_returns_correct_headers(status):
    response = StreamingHTTPResponse(sample_streaming_fn, status=status)
    headers = response.get_headers()
    assert b"HTTP/1.1 %s" % str(status).encode() in headers
Example #19
0
    async def process(self):
        session = self.session
        request = self.request
        meth = request.method

        if request.method == 'GET':
            try:
                callback = self.callback = request.query_args.get("c")
            except Exception:
                callback = self.callback = request.args.get("c", None)

            if not callback:
                await self.session._remote_closed()
                raise exceptions.ServerError('"callback" parameter required')

            elif not self.check_callback.match(callback):
                await self.session._remote_closed()
                raise exceptions.ServerError('invalid "callback" parameter')

            headers = (
                ('Content-Type', "application/javascript; charset=UTF-8"),
                ('Cache-Control', CACHE_CONTROL),
            )
            headers += session_cookie(request)
            headers += cors_headers(request.headers)

            async def stream(_response):
                nonlocal self
                self.response = _response
                # handle session
                await self.handle_session()

            # open sequence (sockjs protocol)
            return StreamingHTTPResponse(stream, headers=headers)

        elif request.method == 'POST':
            data = await request.stream.read()

            ctype = request.content_type.lower()
            if ctype == "application/x-www-form-urlencoded":
                if not data.startswith(b"d="):
                    raise exceptions.ServerError("Payload expected.")

                data = unquote_plus(data[2:].decode(ENCODING))
            else:
                data = data.decode(ENCODING)

            if not data:
                raise exceptions.ServerError("Payload expected.")

            try:
                messages = loads(data)
            except Exception:
                raise exceptions.ServerError("Broken JSON encoding.")

            await session._remote_messages(messages)

            headers = (
                ('Content-Type', "text/html;charset=UTF-8"),
                ('Cache-Control', CACHE_CONTROL),
            )
            headers += session_cookie(request)
            return HTTPResponse(None, body_bytes=b"ok", headers=headers)
        else:
            raise exceptions.MethodNotSupported(
                "No support for such method: %s" % meth, meth, ('GET', 'POST'))
Example #20
0
def test_stream_response_status_returns_correct_headers(status):
    response = StreamingHTTPResponse(sample_streaming_fn, status=status)
    headers = response.get_headers()
    assert b"HTTP/1.1 %s" % str(status).encode() in headers
Example #21
0
def test_stream_response_does_not_include_chunked_header_http10():
    response = StreamingHTTPResponse(sample_streaming_fn)
    headers = response.get_headers(version="1.0")
    assert b"Transfer-Encoding: chunked\r\n" not in headers
Example #22
0
def test_stream_response_does_not_include_chunked_header_if_disabled():
    response = StreamingHTTPResponse(sample_streaming_fn, chunked=False)
    headers = response.get_headers(version="1.1")
    assert b"Transfer-Encoding: chunked\r\n" not in headers