Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support task attr for StreamResponse #1410

Merged
merged 3 commits into from
Nov 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ CHANGES

- Implement range requests for static files #1382

-
- Support task attribute for StreamResponse #1410

-

Expand Down
4 changes: 3 additions & 1 deletion aiohttp/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,9 +560,11 @@ def make_mocked_request(method, path, headers=None, *,
time_service.time.return_value = 12345
time_service.strtime.return_value = "Tue, 15 Nov 1994 08:12:31 GMT"

task = mock.Mock()

req = Request(message, payload,
transport, reader, writer,
time_service,
time_service, task,
secure_proxy_ssl_header=secure_proxy_ssl_header)

match_info = UrlMappingMatchInfo({}, mock.Mock())
Expand Down
2 changes: 1 addition & 1 deletion aiohttp/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def _make_request(self, message, payload, protocol):
return web_reqrep.Request(
message, payload,
protocol.transport, protocol.reader, protocol.writer,
protocol.time_service,
protocol.time_service, protocol._request_handler,
secure_proxy_ssl_header=self._secure_proxy_ssl_header)

@asyncio.coroutine
Expand Down
11 changes: 10 additions & 1 deletion aiohttp/web_reqrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class BaseRequest(collections.MutableMapping, HeadersMixin):
hdrs.METH_TRACE, hdrs.METH_DELETE}

def __init__(self, message, payload, transport, reader, writer,
time_service, *,
time_service, task, *,
secure_proxy_ssl_header=None):
self._message = message
self._transport = transport
Expand All @@ -69,6 +69,7 @@ def __init__(self, message, payload, transport, reader, writer,
self._time_service = time_service
self._state = {}
self._cache = {}
self._task = task

def clone(self, *, method=sentinel, rel_url=sentinel,
headers=sentinel):
Expand Down Expand Up @@ -103,6 +104,7 @@ def clone(self, *, method=sentinel, rel_url=sentinel,
self._reader,
self._writer,
self._time_service,
self._task,
secure_proxy_ssl_header=self._secure_proxy_ssl_header)

# MutableMapping API
Expand Down Expand Up @@ -513,6 +515,8 @@ def __init__(self, *, status=200, reason=None, headers=None):
self._resp_impl = None
self._eof_sent = False

self._task = None

if headers is not None:
self._headers.extend(headers)
if hdrs.CONTENT_TYPE not in self._headers:
Expand All @@ -532,6 +536,10 @@ def started(self):
warnings.warn('use Response.prepared instead', DeprecationWarning)
return self.prepared

@property
def task(self):
return self._task

@property
def status(self):
return self._status
Expand Down Expand Up @@ -835,6 +843,7 @@ def _start(self, request):
resp_impl.headers = headers

self._send_headers(resp_impl)
self._task = request._task
return resp_impl

def _send_headers(self, resp_impl):
Expand Down
15 changes: 9 additions & 6 deletions aiohttp/web_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,15 @@ def handle_request(self, message, payload):
self._request = request

try:
resp = yield from self._handler(request)
except HTTPException as exc:
resp = exc
try:
resp = yield from self._handler(request)
except HTTPException as exc:
resp = exc

resp_msg = yield from resp.prepare(request)
yield from resp.write_eof()
resp_msg = yield from resp.prepare(request)
yield from resp.write_eof()
finally:
resp._task = None

# notify server about keep-alive
self.keep_alive(resp.keep_alive)
Expand Down Expand Up @@ -121,7 +124,7 @@ def _make_request(self, message, payload, protocol):
return BaseRequest(
message, payload,
protocol.transport, protocol.reader, protocol.writer,
protocol.time_service)
protocol.time_service, protocol._request_handler)

@asyncio.coroutine
def shutdown(self, timeout=None):
Expand Down
9 changes: 9 additions & 0 deletions docs/web_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,15 @@ StreamResponse

.. deprecated:: 0.18

.. attribute:: task

A task that serves HTTP request handling.

May be useful for graceful shutdown of long-running requests
(streaming, long polling or web-socket).

.. versionadded:: 1.2

.. attribute:: status

Read-only property for *HTTP response status code*, :class:`int`.
Expand Down
23 changes: 23 additions & 0 deletions tests/test_web_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -1185,3 +1185,26 @@ def handler(request):
resp = yield from client.get('/')
assert 200 == resp.status
assert resp.headers['Date'] == 'Sun, 30 Oct 2016 03:13:52 GMT'


@asyncio.coroutine
def test_response_task(loop, test_client):

srv_resp = None

@asyncio.coroutine
def handler(request):
nonlocal srv_resp
srv_resp = web.StreamResponse()
assert srv_resp.task is None
yield from srv_resp.prepare(request)
assert srv_resp.task is not None
return srv_resp

app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)

resp = yield from client.get('/')
assert 200 == resp.status
assert srv_resp.task is None