async def handle(self, body): from django_grip import GripMiddleware from .eventrequest import EventRequest from .eventstream import EventPermissionError from .utils import sse_error_response self.listener = None request = AsgiRequest(self.scope, body) gm = GripMiddleware() gm.process_request(request) if 'user' in self.scope: request.user = self.scope['user'] try: event_request = await self.parse_request(request) response = None except EventRequest.ResumeNotAllowedError as e: response = HttpResponseBadRequest( 'Invalid request: %s.\n' % str(e)) except EventRequest.GripError as e: if request.grip.proxied: response = sse_error_response( 'internal-error', 'Invalid internal request.') else: response = sse_error_response( 'bad-request', 'Invalid request: %s.' % str(e)) except EventRequest.Error as e: response = sse_error_response( 'bad-request', 'Invalid request: %s.' % str(e)) # for grip requests, prepare immediate response if not response and request.grip.proxied: try: event_response = await self.get_events(event_request) response = event_response.to_http_response(request) except EventPermissionError as e: response = sse_error_response( 'forbidden', str(e), {'channels': e.channels}) extra_headers = {} extra_headers['Cache-Control'] = 'no-cache' extra_headers['X-Accel-Buffering'] = 'no' augment_cors_headers(extra_headers) # if this was a grip request or we encountered an error, respond now if response: response = gm.process_response(request, response) headers = [] for name, value in response.items(): if isinstance(name, six.text_type): name = name.encode('utf-8') if isinstance(value, six.text_type): value = value.encode('utf-8') headers.append((name, value)) for name, value in extra_headers.items(): if isinstance(name, six.text_type): name = name.encode('utf-8') if isinstance(value, six.text_type): value = value.encode('utf-8') headers.append((name, value)) await self.send_response( response.status_code, response.content, headers=headers ) return # if we got here then the request was not a grip request, and there # were no errors, so we can begin a local stream response headers = [(six.b('Content-Type'), six.b('text/event-stream'))] for name, value in extra_headers.items(): if isinstance(name, six.text_type): name = name.encode('utf-8') if isinstance(value, six.text_type): value = value.encode('utf-8') headers.append((name, value)) await self.send_headers(headers=headers) self.listener = Listener() self.is_streaming = True asyncio.get_event_loop().create_task(self.stream(event_request))
async def handle(self, body): from .eventrequest import EventRequest from .eventstream import EventPermissionError from .utils import sse_encode_event, sse_error_response, make_id self.listener = None request = AsgiRequest(self.scope, body) # TODO use GripMiddleware request.grip_proxied = False for name, value in self.scope['headers']: if name == b'grip-sig': request.grip_proxied = True break if 'user' in self.scope: request.user = self.scope['user'] try: event_request = await self.parse_request(request) response = None except EventRequest.ResumeNotAllowedError as e: response = HttpResponseBadRequest( 'Invalid request: %s.\n' % str(e)) except EventRequest.GripError as e: if request.grip_proxied: response = sse_error_response( 'internal-error', 'Invalid internal request.') else: response = sse_error_response( 'bad-request', 'Invalid request: %s.' % str(e)) except EventRequest.Error as e: response = sse_error_response( 'bad-request', 'Invalid request: %s.' % str(e)) user = None if hasattr(request, 'user') and request.user.is_authenticated: user = request.user # for grip requests, prepare immediate response if not response and request.grip_proxied: try: event_response = await self.get_events(event_request, user) response = event_response.to_http_response(request) except EventPermissionError as e: response = sse_error_response( 'forbidden', str(e), {'channels': e.channels}) extra_headers = {} extra_headers['Cache-Control'] = 'no-cache' cors_origin = '' if hasattr(settings, 'EVENTSTREAM_ALLOW_ORIGIN'): cors_origin = settings.EVENTSTREAM_ALLOW_ORIGIN if cors_origin: extra_headers['Access-Control-Allow-Origin'] = cors_origin # if this was a grip request or we encountered an error, respond now if response: headers = [] for name, value in response.items(): headers.append((name, value)) for name, value in extra_headers.items(): headers.append((name, value)) await self.send_response( response.status_code, response.content, headers=headers ) return # if we got here then the request was not a grip request, and there # were no errors, so we can begin a local stream response headers = [('Content-Type', 'text/event-stream')] for name, value in extra_headers.items(): headers.append((name, value)) await self.send_headers(headers=headers) body = b':' + (b' ' * 2048) + b'\n\n' body += b'event: stream-open\ndata:\n\n' await self.send_body(body, more_body=True) self.listener = Listener() self.is_streaming = True asyncio.get_event_loop().create_task(self.stream(event_request, user))