def view_func(path): if event_conversion.is_convertable_cloud_event(request): # Convert this CloudEvent to the equivalent background event data and context. data, context = event_conversion.cloud_event_to_background_event( request) function(data, context) elif is_binary(request.headers): # Support CloudEvents in binary content mode, with data being the # whole request body and context attributes retrieved from request # headers. data = request.get_data() context = Context( eventId=request.headers.get("ce-eventId"), timestamp=request.headers.get("ce-timestamp"), eventType=request.headers.get("ce-eventType"), resource=request.headers.get("ce-resource"), ) function(data, context) else: # This is a regular CloudEvent event_data = event_conversion.marshal_background_event_data( request) if not event_data: flask.abort(400) event_object = BackgroundEvent(**event_data) data = event_object.data context = Context(**event_object.context) function(data, context) return "OK"
def is_convertable_cloud_event(request) -> bool: """Is the given request a known CloudEvent that can be converted to background event.""" if is_binary(request.headers): event_type = request.headers.get("ce-type") event_source = request.headers.get("ce-source") return (event_source is not None and event_type is not None and event_type in _CE_TO_BACKGROUND_TYPE) return False
def test_is_binary(): headers = { "ce-id": "my-id", "ce-source": "<event-source>", "ce-type": "cloudevent.event.type", "ce-specversion": "1.0", "Content-Type": "text/plain", } assert is_binary(headers) headers = { "Content-Type": "application/cloudevents+json", } assert not is_binary(headers) headers = {} assert not is_binary(headers)
async def post(self, name: str): if has_binary_headers(self.request.headers): try: #Use default unmarshaller if contenttype is set in header if "ce-contenttype" in self.request.headers: body = from_http(self.request.headers, self.request.body) else: body = from_http(self.request.headers, self.request.body, lambda x: x) except (ce.MissingRequiredFields, ce.InvalidRequiredFields, ce.InvalidStructuredJSON, ce.InvalidHeadersFormat, ce.DataMarshallerError, ce.DataUnmarshallerError) as e: raise tornado.web.HTTPError( status_code=HTTPStatus.BAD_REQUEST, reason="Cloud Event Exceptions: %s" % e) else: try: body = json.loads(self.request.body) except json.decoder.JSONDecodeError as e: raise tornado.web.HTTPError( status_code=HTTPStatus.BAD_REQUEST, reason="Unrecognized request format: %s" % e) model = self.get_model(name) request = model.preprocess(body) request = self.validate(request) response = (await model.predict(request)) if inspect.iscoroutinefunction( model.predict) else model.predict(request) response = model.postprocess(response) if has_binary_headers(self.request.headers): event = CloudEvent(body._attributes, response) if is_binary(self.request.headers): eventheader, eventbody = to_binary(event) elif is_structured(self.request.headers): eventheader, eventbody = to_structured(event) for k, v in eventheader.items(): if k != "ce-time": self.set_header(k, v) else: #utc now() timestamp self.set_header( 'ce-time', datetime.utcnow().replace(tzinfo=pytz.utc).strftime( '%Y-%m-%dT%H:%M:%S.%f%z')) if isinstance(eventbody, (bytes, bytearray)): response = eventbody else: response = eventbody.data self.write(response)
async def post(self, name: str): if has_binary_headers(self.request.headers): try: # Use default unmarshaller if contenttype is set in header if "ce-contenttype" in self.request.headers: body = from_http(self.request.headers, self.request.body) else: body = from_http(self.request.headers, self.request.body, lambda x: x) except (ce.MissingRequiredFields, ce.InvalidRequiredFields, ce.InvalidStructuredJSON, ce.InvalidHeadersFormat, ce.DataMarshallerError, ce.DataUnmarshallerError) as e: raise tornado.web.HTTPError( status_code=HTTPStatus.BAD_REQUEST, reason="Cloud Event Exceptions: %s" % e) else: try: body = json.loads(self.request.body) except json.decoder.JSONDecodeError as e: raise tornado.web.HTTPError( status_code=HTTPStatus.BAD_REQUEST, reason="Unrecognized request format: %s" % e) # call model locally or remote model workers model = self.get_model(name) if not isinstance(model, RayServeHandle): response = await model(body) else: model_handle = model response = await model_handle.remote(body) # process response from the model if has_binary_headers(self.request.headers): event = CloudEvent(body._attributes, response) if is_binary(self.request.headers): eventheader, eventbody = to_binary(event) elif is_structured(self.request.headers): eventheader, eventbody = to_structured(event) for k, v in eventheader.items(): if k != "ce-time": self.set_header(k, v) else: # utc now() timestamp self.set_header( 'ce-time', datetime.utcnow().replace(tzinfo=pytz.utc).strftime( '%Y-%m-%dT%H:%M:%S.%f%z')) response = eventbody self.write(response)
def view_func(path): if is_binary(request.headers): # Support CloudEvents in binary content mode, with data being the # whole request body and context attributes retrieved from request # headers. data = request.get_data() context = Context( eventId=request.headers.get("ce-eventId"), timestamp=request.headers.get("ce-timestamp"), eventType=request.headers.get("ce-eventType"), resource=request.headers.get("ce-resource"), ) function(data, context) else: # This is a regular CloudEvent event_data = request.get_json() if not event_data: flask.abort(400) event_object = _Event(**event_data) data = event_object.data context = Context(**event_object.context) function(data, context) return "OK"