Exemplo n.º 1
0
	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))
Exemplo n.º 2
0
	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))