mirror of
https://github.com/django/daphne.git
synced 2025-04-20 08:42:18 +03:00
HTTP Long Poll finishing off
This commit is contained in:
parent
4f60726ec4
commit
be1498768f
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
---------
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user