Example #1
0
    def stream_handler(self, request):
        # Without the Content-Type, most (all?) browsers will not render
        # partially downloaded content. Note, the response type is
        # StreamResponse not Response.
        resp = StreamResponse(status=200, reason='OK',
                              headers={'Content-Type': 'text/html'})

        yield from resp.prepare(request)
        yield from asyncio.sleep(5, loop=self._loop)
        yield from resp.drain()
        return resp
Example #2
0
def test_drain_before_start():
    resp = StreamResponse()
    with pytest.raises(RuntimeError):
        yield from resp.drain()
Example #3
0
 def go():
     resp = StreamResponse()
     with self.assertRaises(RuntimeError):
         yield from resp.drain()
Example #4
0
def test_drain_before_start():
    resp = StreamResponse()
    with pytest.raises(RuntimeError):
        yield from resp.drain()
Example #5
0
 def go():
     resp = StreamResponse()
     with self.assertRaises(RuntimeError):
         yield from resp.drain()
Example #6
0
class WSGIResponse:

    __slots__ = (
        "_handler",
        "_request",
        "_response",
    )

    def __init__(self, handler, request):
        self._handler = handler
        self._request = request
        # State.
        self._response = None

    def start_response(self, status, headers, exc_info=None):
        if exc_info:
            # Log the error.
            self._request.app.logger.error("Unexpected error",
                                           exc_info=exc_info)
            # Attempt to modify the response.
            try:
                if self._response and self._response.started:
                    raise exc_info[1].with_traceback(exc_info[2])
                self._response = None
            finally:
                exc_info = None
        # Cannot start response twice.
        assert not self._response, "Cannot call start_response() twice"
        # Parse the status.
        assert isinstance(status, str), "Response status should be str"
        status_code, reason = status.split(None, 1)
        status_code = int(status_code)
        # Store the response.
        self._response = StreamResponse(
            status=status_code,
            reason=reason,
        )
        # Store the headers.
        for header_name, header_value in headers:
            assert not is_hop_by_hop(
                header_name), "Hop-by-hop headers are forbidden"
            self._response.headers.add(header_name, header_value)
        # Return the stream writer interface.
        return self.write_threadsafe

    def _write_head(self):
        assert self._response, "Application did not call start_response()"
        if not self._response.started:
            self._response.start(self._request)

    def write(self, data):
        assert isinstance(
            data, (bytes, bytearray, memoryview)), "Data should be bytes"
        self._write_head()
        self._response.write(data)

    @asyncio.coroutine
    def drain(self):
        self._write_head()
        yield from self._response.drain()

    @asyncio.coroutine
    def write_eof(self):
        self._write_head()
        yield from self._response.write_eof()

    def write_threadsafe(self, data):
        with self._handler._lock_for_write():
            self.write(data)