HTTP Long Poll finishing off

This commit is contained in:
Andrew Godwin 2016-02-14 19:22:46 +00:00
parent 4f60726ec4
commit be1498768f
3 changed files with 46 additions and 9 deletions

View File

@ -23,10 +23,13 @@ class AsgiRequest(http.HttpRequest):
dict, and wraps request body handling.
"""
# Exception that will cause any handler to skip around response
# transmission and presume something else will do it later.
class ResponseLater(Exception):
pass
"""
Exception that will cause any handler to skip around response
transmission and presume something else will do it later.
"""
def __init__(self):
Exception.__init__(self, "Response later")
def __init__(self, message):
self.message = message
@ -171,17 +174,37 @@ class AsgiHandler(base.BaseHandler):
}
)
response = http.HttpResponseBadRequest()
except AsgiRequest.ResponseLater:
# The view has promised something else
# will send a response at a later time
return
else:
response = self.get_response(request)
try:
response = self.get_response(request)
except AsgiRequest.ResponseLater:
# The view has promised something else
# will send a response at a later time
return
# Transform response into messages, which we yield back to caller
for message in self.encode_response(response):
# TODO: file_to_stream
yield message
def process_exception_by_middleware(self, exception, request):
"""
Catches ResponseLater and re-raises it, else tries to delegate
to middleware exception handling.
"""
if isinstance(exception, AsgiRequest.ResponseLater):
raise
else:
return super(AsgiHandler, self).process_exception_by_middleware(exception, request)
def handle_uncaught_exception(self, request, resolver, exc_info):
"""
Propagates ResponseLater up into the higher handler method,
processes everything else
"""
if issubclass(exc_info[0], AsgiRequest.ResponseLater):
raise
return super(AsgiHandler, self).handle_uncaught_exception(request, resolver, exc_info)
@classmethod
def encode_response(cls, response):
"""

View File

@ -25,7 +25,6 @@ class Worker(object):
"""
channels = self.channel_layer.registry.all_channel_names()
while True:
logger.debug("Worker waiting for message")
channel, content = self.channel_layer.receive_many(channels, block=True)
logger.debug("Worker got message on %s: repl %s", channel, content.get("reply_channel", "none"))
# If no message, stall a little to avoid busy-looping then continue

View File

@ -565,6 +565,21 @@ Keys:
server-pushed requests, and applications should not create reply channels.
Disconnect
''''''''''
Sent when a HTTP connection is closed. This is mainly useful for long-polling,
where you may have added the response channel to a Group or other set of
channels you want to trigger a reply to when data arrives.
Channel: ``http.disconnect``
Keys:
* ``reply_channel``: Channel name responses would have been sent on. No longer
valid after this message is sent; all messages to it will be dropped.
WebSocket
---------