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
def test_drain_before_start(): resp = StreamResponse() with pytest.raises(RuntimeError): yield from resp.drain()
def go(): resp = StreamResponse() with self.assertRaises(RuntimeError): yield from resp.drain()
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)