Make SDK compliant with CloudEvents SDK spec
Signed-off-by: Denis Makogon <lildee1991@gmail.com>
This commit is contained in:
parent
a0acdcf4af
commit
22b8b89676
|
@ -123,3 +123,4 @@ venv
|
|||
ChangeLog
|
||||
AUTHORS
|
||||
.pytest_cache/
|
||||
.idea
|
||||
|
|
28
README.md
28
README.md
|
@ -6,11 +6,11 @@ Package **cloudevents** provides primitives to work with CloudEvents specificati
|
|||
|
||||
Parsing upstream Event from HTTP Request:
|
||||
```python
|
||||
from cloudevents.sdk.event import upstream
|
||||
from cloudevents.sdk.event import v02
|
||||
from cloudevents.sdk import marshaller
|
||||
|
||||
data = "<this is where your CloudEvent comes from>"
|
||||
m = marshaller.NewDefaultHTTPMarshaller(upstream.Event)
|
||||
m = marshaller.NewDefaultHTTPMarshaller(v02.Event)
|
||||
event = m.FromRequest(
|
||||
{"Content-Type": "application/cloudevents+json"},
|
||||
data,
|
||||
|
@ -25,12 +25,12 @@ from cloudevents.sdk.event import v01
|
|||
|
||||
event = (
|
||||
v01.Event().
|
||||
WithContentType("application/json").
|
||||
WithData('{"name":"john"}').
|
||||
WithEventID("my-id").
|
||||
WithSource("from-galaxy-far-far-away").
|
||||
WithEventTime("tomorrow").
|
||||
WithEventType("cloudevent.greet.you")
|
||||
SetContentType("application/json").
|
||||
SetData('{"name":"john"}').
|
||||
SetEventID("my-id").
|
||||
SetSource("from-galaxy-far-far-away").
|
||||
SetEventTime("tomorrow").
|
||||
SetEventType("cloudevent.greet.you")
|
||||
)
|
||||
|
||||
```
|
||||
|
@ -44,12 +44,12 @@ from cloudevents.sdk.event import v01
|
|||
|
||||
event = (
|
||||
v01.Event().
|
||||
WithContentType("application/json").
|
||||
WithData('{"name":"john"}').
|
||||
WithEventID("my-id").
|
||||
WithSource("from-galaxy-far-far-away").
|
||||
WithEventTime("tomorrow").
|
||||
WithEventType("cloudevent.greet.you")
|
||||
SetContentType("application/json").
|
||||
SetData('{"name":"john"}').
|
||||
SetEventID("my-id").
|
||||
SetSource("from-galaxy-far-far-away").
|
||||
SetEventTime("tomorrow").
|
||||
SetEventType("cloudevent.greet.you")
|
||||
)
|
||||
m = marshaller.NewHTTPMarshaller(
|
||||
[
|
||||
|
|
|
@ -21,16 +21,7 @@ class Converter(object):
|
|||
|
||||
TYPE = None
|
||||
|
||||
def __init__(
|
||||
self, event_class: base.BaseEvent,
|
||||
supported_media_types: typing.Mapping[str, bool]):
|
||||
self.event = event_class()
|
||||
self.supported_media_types = supported_media_types
|
||||
|
||||
def can_read(self, media_type: str) -> bool:
|
||||
return media_type in self.supported_media_types
|
||||
|
||||
def read(self, headers: dict, body: typing.IO,
|
||||
def read(self, event, headers: dict, body: typing.IO,
|
||||
data_unmarshaller: typing.Callable) -> base.BaseEvent:
|
||||
raise Exception("not implemented")
|
||||
|
||||
|
|
|
@ -17,25 +17,20 @@ import typing
|
|||
from cloudevents.sdk import exceptions
|
||||
from cloudevents.sdk.converters import base
|
||||
from cloudevents.sdk.event import base as event_base
|
||||
from cloudevents.sdk.event import v01
|
||||
from cloudevents.sdk.event import v02
|
||||
|
||||
|
||||
class BinaryHTTPCloudEventConverter(base.Converter):
|
||||
|
||||
TYPE = "binary"
|
||||
|
||||
def __init__(self, event_class: event_base.BaseEvent,
|
||||
supported_media_types: typing.Mapping[str, bool]):
|
||||
if event_class == v01.Event:
|
||||
raise exceptions.UnsupportedEvent(event_class)
|
||||
|
||||
super().__init__(event_class, supported_media_types)
|
||||
SUPPORTED_VERSIONS = [v02.Event, ]
|
||||
|
||||
def read(self,
|
||||
event: event_base.BaseEvent,
|
||||
headers: dict, body: typing.IO,
|
||||
data_unmarshaller: typing.Callable) -> event_base.BaseEvent:
|
||||
# we ignore headers, since the whole CE is in request body
|
||||
event = self.event
|
||||
if type(event) not in self.SUPPORTED_VERSIONS:
|
||||
raise exceptions.UnsupportedEvent(type(event))
|
||||
event.UnmarshalBinary(headers, body, data_unmarshaller)
|
||||
return event
|
||||
|
||||
|
@ -48,11 +43,5 @@ class BinaryHTTPCloudEventConverter(base.Converter):
|
|||
return hs, data_marshaller(data)
|
||||
|
||||
|
||||
def NewBinaryHTTPCloudEventConverter(
|
||||
event_class: event_base.BaseEvent) -> BinaryHTTPCloudEventConverter:
|
||||
media_types = {
|
||||
"application/json": True,
|
||||
"application/xml": True,
|
||||
"application/octet-stream": True,
|
||||
}
|
||||
return BinaryHTTPCloudEventConverter(event_class, media_types)
|
||||
def NewBinaryHTTPCloudEventConverter() -> BinaryHTTPCloudEventConverter:
|
||||
return BinaryHTTPCloudEventConverter()
|
||||
|
|
|
@ -23,15 +23,10 @@ class JSONHTTPCloudEventConverter(base.Converter):
|
|||
|
||||
TYPE = "structured"
|
||||
|
||||
def __init__(self, event_class: event_base.BaseEvent,
|
||||
supported_media_types: typing.Mapping[str, bool]):
|
||||
super().__init__(event_class, supported_media_types)
|
||||
|
||||
def read(self, headers: dict,
|
||||
def read(self, event: event_base.BaseEvent,
|
||||
headers: dict,
|
||||
body: typing.IO,
|
||||
data_unmarshaller: typing.Callable) -> event_base.BaseEvent:
|
||||
# we ignore headers, since the whole CE is in request body
|
||||
event = self.event
|
||||
event.UnmarshalJSON(body, data_unmarshaller)
|
||||
return event
|
||||
|
||||
|
@ -44,10 +39,5 @@ class JSONHTTPCloudEventConverter(base.Converter):
|
|||
return {}, event.MarshalJSON(data_marshaller)
|
||||
|
||||
|
||||
def NewJSONHTTPCloudEventConverter(
|
||||
event_class: event_base.BaseEvent) -> JSONHTTPCloudEventConverter:
|
||||
media_types = {
|
||||
"application/cloudevents+json": True,
|
||||
}
|
||||
|
||||
return JSONHTTPCloudEventConverter(event_class, media_types)
|
||||
def NewJSONHTTPCloudEventConverter() -> JSONHTTPCloudEventConverter:
|
||||
return JSONHTTPCloudEventConverter()
|
||||
|
|
|
@ -50,28 +50,28 @@ class EventGetterSetter(object):
|
|||
# CloudEvent attribute constructors
|
||||
# Each setter return an instance of its class
|
||||
# in order to build a pipeline of setter
|
||||
def WithEventType(self, eventType: str) -> object:
|
||||
def SetEventType(self, eventType: str) -> object:
|
||||
raise Exception("not implemented")
|
||||
|
||||
def WithSource(self, source: str) -> object:
|
||||
def SetSource(self, source: str) -> object:
|
||||
raise Exception("not implemented")
|
||||
|
||||
def WithEventID(self, eventID: str) -> object:
|
||||
def SetEventID(self, eventID: str) -> object:
|
||||
raise Exception("not implemented")
|
||||
|
||||
def WithEventTime(self, eventTime: str) -> object:
|
||||
def SetEventTime(self, eventTime: str) -> object:
|
||||
raise Exception("not implemented")
|
||||
|
||||
def WithSchemaURL(self, schemaURL: str) -> object:
|
||||
def SetSchemaURL(self, schemaURL: str) -> object:
|
||||
raise Exception("not implemented")
|
||||
|
||||
def WithData(self, data: object) -> object:
|
||||
def SetData(self, data: object) -> object:
|
||||
raise Exception("not implemented")
|
||||
|
||||
def WithExtensions(self, extensions: dict) -> object:
|
||||
def SetExtensions(self, extensions: dict) -> object:
|
||||
raise Exception("not implemented")
|
||||
|
||||
def WithContentType(self, contentType: str) -> object:
|
||||
def SetContentType(self, contentType: str) -> object:
|
||||
raise Exception("not implemented")
|
||||
|
||||
|
||||
|
|
|
@ -59,35 +59,35 @@ class Event(base.BaseEvent):
|
|||
def ContentType(self) -> str:
|
||||
return self.ce__contentType.get()
|
||||
|
||||
def WithEventType(self, eventType: str) -> base.BaseEvent:
|
||||
def SetEventType(self, eventType: str) -> base.BaseEvent:
|
||||
self.Set("eventType", eventType)
|
||||
return self
|
||||
|
||||
def WithSource(self, source: str) -> base.BaseEvent:
|
||||
def SetSource(self, source: str) -> base.BaseEvent:
|
||||
self.Set("source", source)
|
||||
return self
|
||||
|
||||
def WithEventID(self, eventID: str) -> base.BaseEvent:
|
||||
def SetEventID(self, eventID: str) -> base.BaseEvent:
|
||||
self.Set("eventID", eventID)
|
||||
return self
|
||||
|
||||
def WithEventTime(self, eventTime: str) -> base.BaseEvent:
|
||||
def SetEventTime(self, eventTime: str) -> base.BaseEvent:
|
||||
self.Set("eventTime", eventTime)
|
||||
return self
|
||||
|
||||
def WithSchemaURL(self, schemaURL: str) -> base.BaseEvent:
|
||||
def SetSchemaURL(self, schemaURL: str) -> base.BaseEvent:
|
||||
self.Set("schemaURL", schemaURL)
|
||||
return self
|
||||
|
||||
def WithData(self, data: object) -> base.BaseEvent:
|
||||
def SetData(self, data: object) -> base.BaseEvent:
|
||||
self.Set("data", data)
|
||||
return self
|
||||
|
||||
def WithExtensions(self, extensions: dict) -> base.BaseEvent:
|
||||
def SetExtensions(self, extensions: dict) -> base.BaseEvent:
|
||||
self.Set("extension", extensions)
|
||||
return self
|
||||
|
||||
def WithContentType(self, contentType: str) -> base.BaseEvent:
|
||||
def SetContentType(self, contentType: str) -> base.BaseEvent:
|
||||
self.Set("contentType", contentType)
|
||||
return self
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ from cloudevents.sdk.event import base
|
|||
class Event(base.BaseEvent):
|
||||
|
||||
def __init__(self):
|
||||
self.ce__specversion = opt.Option("specversion", "0.1", True)
|
||||
self.ce__specversion = opt.Option("specversion", "0.2", True)
|
||||
self.ce__type = opt.Option("type", None, True)
|
||||
self.ce__source = opt.Option("source", None, True)
|
||||
self.ce__id = opt.Option("id", None, True)
|
||||
|
@ -56,34 +56,34 @@ class Event(base.BaseEvent):
|
|||
def ContentType(self) -> str:
|
||||
return self.ce__contenttype.get()
|
||||
|
||||
def WithEventType(self, eventType: str) -> base.BaseEvent:
|
||||
def SetEventType(self, eventType: str) -> base.BaseEvent:
|
||||
self.Set("type", eventType)
|
||||
return self
|
||||
|
||||
def WithSource(self, source: str) -> base.BaseEvent:
|
||||
def SetSource(self, source: str) -> base.BaseEvent:
|
||||
self.Set("source", source)
|
||||
return self
|
||||
|
||||
def WithEventID(self, eventID: str) -> base.BaseEvent:
|
||||
def SetEventID(self, eventID: str) -> base.BaseEvent:
|
||||
self.Set("id", eventID)
|
||||
return self
|
||||
|
||||
def WithEventTime(self, eventTime: str) -> base.BaseEvent:
|
||||
def SetEventTime(self, eventTime: str) -> base.BaseEvent:
|
||||
self.Set("time", eventTime)
|
||||
return self
|
||||
|
||||
def WithSchemaURL(self, schemaURL: str) -> base.BaseEvent:
|
||||
def SetSchemaURL(self, schemaURL: str) -> base.BaseEvent:
|
||||
self.Set("schemaurl", schemaURL)
|
||||
return self
|
||||
|
||||
def WithData(self, data: object) -> base.BaseEvent:
|
||||
def SetData(self, data: object) -> base.BaseEvent:
|
||||
self.Set("data", data)
|
||||
return self
|
||||
|
||||
def WithExtensions(self, extensions: dict) -> base.BaseEvent:
|
||||
def SetExtensions(self, extensions: dict) -> base.BaseEvent:
|
||||
self.Set("extension", extensions)
|
||||
return self
|
||||
|
||||
def WithContentType(self, contentType: str) -> base.BaseEvent:
|
||||
def SetContentType(self, contentType: str) -> base.BaseEvent:
|
||||
self.Set("contenttype", contentType)
|
||||
return self
|
|
@ -13,14 +13,6 @@
|
|||
# under the License.
|
||||
|
||||
|
||||
class InvalidMimeTypeFromRequest(Exception):
|
||||
|
||||
def __init__(self, mime_type):
|
||||
super().__init__(
|
||||
"Unable to read CloudEvent from request, "
|
||||
"invalid MIME type: {0}".format(mime_type))
|
||||
|
||||
|
||||
class UnsupportedEvent(Exception):
|
||||
|
||||
def __init__(self, event_class):
|
||||
|
|
|
@ -37,12 +37,15 @@ class HTTPMarshaller(object):
|
|||
"""
|
||||
self.__converters = {c.TYPE: c for c in converters}
|
||||
|
||||
def FromRequest(self, headers: dict,
|
||||
def FromRequest(self, event: event_base.BaseEvent,
|
||||
headers: dict,
|
||||
body: typing.IO,
|
||||
data_unmarshaller:
|
||||
typing.Callable) -> event_base.BaseEvent:
|
||||
"""
|
||||
Reads a CloudEvent from an HTTP headers and request body
|
||||
:param event: CloudEvent placeholder
|
||||
:type event: cloudevents.sdk.event.base.BaseEvent
|
||||
:param headers: a dict-like HTTP headers
|
||||
:type headers: dict
|
||||
:param body: a stream-like HTTP request body
|
||||
|
@ -52,12 +55,8 @@ class HTTPMarshaller(object):
|
|||
:return: a CloudEvent
|
||||
:rtype: event_base.BaseEvent
|
||||
"""
|
||||
mimeType = headers.get("Content-Type")
|
||||
for _, cnvrtr in self.__converters.items():
|
||||
if cnvrtr.can_read(mimeType):
|
||||
return cnvrtr.read(headers, body, data_unmarshaller)
|
||||
|
||||
raise exceptions.InvalidMimeTypeFromRequest(mimeType)
|
||||
return cnvrtr.read(event, headers, body, data_unmarshaller)
|
||||
|
||||
def ToRequest(self, event: event_base.BaseEvent,
|
||||
converter_type: str,
|
||||
|
@ -80,19 +79,16 @@ class HTTPMarshaller(object):
|
|||
raise exceptions.NoSuchConverter(converter_type)
|
||||
|
||||
|
||||
def NewDefaultHTTPMarshaller(
|
||||
event_class: event_base.BaseEvent) -> HTTPMarshaller:
|
||||
def NewDefaultHTTPMarshaller() -> HTTPMarshaller:
|
||||
"""
|
||||
Creates the default HTTP marshaller with both structured
|
||||
and binary converters
|
||||
:param event_class: CloudEvent spec class
|
||||
:type event_class: event_base.BaseEvent
|
||||
:return: an instance of HTTP marshaller
|
||||
:rtype: cloudevents.sdk.marshaller.HTTPMarshaller
|
||||
"""
|
||||
return HTTPMarshaller([
|
||||
structured.NewJSONHTTPCloudEventConverter(event_class),
|
||||
binary.NewBinaryHTTPCloudEventConverter(event_class),
|
||||
structured.NewJSONHTTPCloudEventConverter(),
|
||||
binary.NewBinaryHTTPCloudEventConverter(),
|
||||
])
|
||||
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ contentType = "application/json"
|
|||
ce_type = "word.found.exclamation"
|
||||
ce_id = "16fb5f0b-211e-1102-3dfe-ea6e2806f124"
|
||||
source = "pytest"
|
||||
specversion = "0.1"
|
||||
specversion = "0.2"
|
||||
eventTime = "2018-10-23T12:28:23.3464579Z"
|
||||
body = '{"name":"john"}'
|
||||
headers = {
|
||||
|
|
|
@ -20,7 +20,7 @@ from cloudevents.sdk import exceptions
|
|||
from cloudevents.sdk import marshaller
|
||||
|
||||
from cloudevents.sdk.event import v01
|
||||
from cloudevents.sdk.event import upstream
|
||||
from cloudevents.sdk.event import v02
|
||||
|
||||
from cloudevents.sdk.converters import binary
|
||||
from cloudevents.sdk.converters import structured
|
||||
|
@ -31,10 +31,10 @@ from cloudevents.tests import data
|
|||
def test_binary_converter_upstream():
|
||||
m = marshaller.NewHTTPMarshaller(
|
||||
[
|
||||
binary.NewBinaryHTTPCloudEventConverter(upstream.Event)
|
||||
binary.NewBinaryHTTPCloudEventConverter()
|
||||
]
|
||||
)
|
||||
event = m.FromRequest(data.headers, None, lambda x: x)
|
||||
event = m.FromRequest(v02.Event(), data.headers, None, lambda x: x)
|
||||
assert event is not None
|
||||
assert event.Get("type") == (data.ce_type, True)
|
||||
assert event.Get("id") == (data.ce_id, True)
|
||||
|
@ -43,10 +43,11 @@ def test_binary_converter_upstream():
|
|||
def test_structured_converter_upstream():
|
||||
m = marshaller.NewHTTPMarshaller(
|
||||
[
|
||||
structured.NewJSONHTTPCloudEventConverter(upstream.Event)
|
||||
structured.NewJSONHTTPCloudEventConverter()
|
||||
]
|
||||
)
|
||||
event = m.FromRequest(
|
||||
v02.Event(),
|
||||
{"Content-Type": "application/cloudevents+json"},
|
||||
io.StringIO(ujson.dumps(data.ce)),
|
||||
lambda x: x.read()
|
||||
|
@ -59,19 +60,26 @@ def test_structured_converter_upstream():
|
|||
|
||||
# todo: clarify whether spec 0.1 doesn't support binary format
|
||||
def test_binary_converter_v01():
|
||||
m = marshaller.NewHTTPMarshaller(
|
||||
[
|
||||
binary.NewBinaryHTTPCloudEventConverter()
|
||||
]
|
||||
)
|
||||
|
||||
pytest.raises(
|
||||
exceptions.UnsupportedEvent,
|
||||
binary.NewBinaryHTTPCloudEventConverter,
|
||||
v01.Event)
|
||||
m.FromRequest,
|
||||
v01.Event, None, None, None)
|
||||
|
||||
|
||||
def test_structured_converter_v01():
|
||||
m = marshaller.NewHTTPMarshaller(
|
||||
[
|
||||
structured.NewJSONHTTPCloudEventConverter(v01.Event)
|
||||
structured.NewJSONHTTPCloudEventConverter()
|
||||
]
|
||||
)
|
||||
event = m.FromRequest(
|
||||
v01.Event(),
|
||||
{"Content-Type": "application/cloudevents+json"},
|
||||
io.StringIO(ujson.dumps(data.ce)),
|
||||
lambda x: x.read()
|
||||
|
@ -83,9 +91,10 @@ def test_structured_converter_v01():
|
|||
|
||||
|
||||
def test_default_http_marshaller():
|
||||
m = marshaller.NewDefaultHTTPMarshaller(upstream.Event)
|
||||
m = marshaller.NewDefaultHTTPMarshaller()
|
||||
|
||||
event = m.FromRequest(
|
||||
v02.Event(),
|
||||
{"Content-Type": "application/cloudevents+json"},
|
||||
io.StringIO(ujson.dumps(data.ce)),
|
||||
lambda x: x.read()
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import ujson
|
||||
|
||||
from cloudevents.sdk.event import v01
|
||||
from cloudevents.sdk.event import upstream
|
||||
from cloudevents.sdk.event import v02
|
||||
|
||||
from cloudevents.sdk import converters
|
||||
from cloudevents.sdk import marshaller
|
||||
|
@ -26,15 +26,15 @@ from cloudevents.tests import data
|
|||
|
||||
def test_event_pipeline_upstream():
|
||||
event = (
|
||||
upstream.Event().
|
||||
WithContentType(data.contentType).
|
||||
WithData(data.body).
|
||||
WithEventID(data.ce_id).
|
||||
WithSource(data.source).
|
||||
WithEventTime(data.eventTime).
|
||||
WithEventType(data.ce_type)
|
||||
v02.Event().
|
||||
SetContentType(data.contentType).
|
||||
SetData(data.body).
|
||||
SetEventID(data.ce_id).
|
||||
SetSource(data.source).
|
||||
SetEventTime(data.eventTime).
|
||||
SetEventType(data.ce_type)
|
||||
)
|
||||
m = marshaller.NewDefaultHTTPMarshaller(type(event))
|
||||
m = marshaller.NewDefaultHTTPMarshaller()
|
||||
new_headers, body = m.ToRequest(event, converters.TypeBinary, lambda x: x)
|
||||
assert new_headers is not None
|
||||
assert "ce-specversion" in new_headers
|
||||
|
@ -49,16 +49,16 @@ def test_event_pipeline_upstream():
|
|||
def test_event_pipeline_v01():
|
||||
event = (
|
||||
v01.Event().
|
||||
WithContentType(data.contentType).
|
||||
WithData(data.body).
|
||||
WithEventID(data.ce_id).
|
||||
WithSource(data.source).
|
||||
WithEventTime(data.eventTime).
|
||||
WithEventType(data.ce_type)
|
||||
SetContentType(data.contentType).
|
||||
SetData(data.body).
|
||||
SetEventID(data.ce_id).
|
||||
SetSource(data.source).
|
||||
SetEventTime(data.eventTime).
|
||||
SetEventType(data.ce_type)
|
||||
)
|
||||
m = marshaller.NewHTTPMarshaller(
|
||||
[
|
||||
structured.NewJSONHTTPCloudEventConverter(type(event))
|
||||
structured.NewJSONHTTPCloudEventConverter()
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
@ -21,15 +21,16 @@ from cloudevents.sdk import marshaller
|
|||
|
||||
from cloudevents.sdk.converters import structured
|
||||
from cloudevents.sdk.event import v01
|
||||
from cloudevents.sdk.event import upstream
|
||||
from cloudevents.sdk.event import v02
|
||||
|
||||
|
||||
from cloudevents.tests import data
|
||||
|
||||
|
||||
def test_binary_event_to_request_upstream():
|
||||
m = marshaller.NewDefaultHTTPMarshaller(upstream.Event)
|
||||
m = marshaller.NewDefaultHTTPMarshaller()
|
||||
event = m.FromRequest(
|
||||
v02.Event(),
|
||||
{"Content-Type": "application/cloudevents+json"},
|
||||
io.StringIO(ujson.dumps(data.ce)),
|
||||
lambda x: x.read()
|
||||
|
@ -46,8 +47,9 @@ def test_binary_event_to_request_upstream():
|
|||
|
||||
def test_structured_event_to_request_upstream():
|
||||
copy_of_ce = copy.deepcopy(data.ce)
|
||||
m = marshaller.NewDefaultHTTPMarshaller(upstream.Event)
|
||||
m = marshaller.NewDefaultHTTPMarshaller()
|
||||
event = m.FromRequest(
|
||||
v02.Event(),
|
||||
{"Content-Type": "application/cloudevents+json"},
|
||||
io.StringIO(ujson.dumps(data.ce)),
|
||||
lambda x: x.read()
|
||||
|
@ -65,10 +67,11 @@ def test_structured_event_to_request_v01():
|
|||
copy_of_ce = copy.deepcopy(data.ce)
|
||||
m = marshaller.NewHTTPMarshaller(
|
||||
[
|
||||
structured.NewJSONHTTPCloudEventConverter(v01.Event)
|
||||
structured.NewJSONHTTPCloudEventConverter()
|
||||
]
|
||||
)
|
||||
event = m.FromRequest(
|
||||
v01.Event(),
|
||||
{"Content-Type": "application/cloudevents+json"},
|
||||
io.StringIO(ujson.dumps(data.ce)),
|
||||
lambda x: x.read()
|
||||
|
|
Loading…
Reference in New Issue