diff --git a/src/transport/http/binary_receiver.ts b/src/transport/http/binary_receiver.ts index 63169ae..5be62ed 100644 --- a/src/transport/http/binary_receiver.ts +++ b/src/transport/http/binary_receiver.ts @@ -32,10 +32,11 @@ export class BinaryHTTPReceiver { * @returns {CloudEvent} an instance of CloudEvent representing the incoming request * @throws {ValidationError} of the event does not conform to the spec */ - parse(payload: string | Record, headers: Headers): CloudEvent { - if (!payload) throw new ValidationError("payload is null or undefined"); + parse(payload: string | Record | undefined | null, headers: Headers): CloudEvent { if (!headers) throw new ValidationError("headers is null or undefined"); - isStringOrObjectOrThrow(payload, new ValidationError("payload must be an object or a string")); + if (payload) { + isStringOrObjectOrThrow(payload, new ValidationError("payload must be an object or a string")); + } if ( headers[CONSTANTS.CE_HEADERS.SPEC_VERSION] && @@ -61,11 +62,15 @@ export class BinaryHTTPReceiver { } } - const parser = parserByContentType[eventObj.datacontenttype as string]; - if (!parser) { - throw new ValidationError(`no parser found for content type ${eventObj.datacontenttype}`); + let parsedPayload; + + if (payload) { + const parser = parserByContentType[eventObj.datacontenttype as string]; + if (!parser) { + throw new ValidationError(`no parser found for content type ${eventObj.datacontenttype}`); + } + parsedPayload = parser.parse(payload); } - const parsedPayload = parser.parse(payload); // Every unprocessed header can be an extension for (const header in sanitizedHeaders) { diff --git a/src/transport/http/structured_receiver.ts b/src/transport/http/structured_receiver.ts index 56f2683..bf6a7ea 100644 --- a/src/transport/http/structured_receiver.ts +++ b/src/transport/http/structured_receiver.ts @@ -31,7 +31,7 @@ export class StructuredHTTPReceiver { * @returns {CloudEvent} a new CloudEvent instance for the provided headers and payload * @throws {ValidationError} if the payload and header combination do not conform to the spec */ - parse(payload: Record | string, headers: Headers): CloudEvent { + parse(payload: Record | string | undefined | null, headers: Headers): CloudEvent { if (!payload) throw new ValidationError("payload is null or undefined"); if (!headers) throw new ValidationError("headers is null or undefined"); isStringOrObjectOrThrow(payload, new ValidationError("payload must be an object or a string")); diff --git a/src/transport/receiver.ts b/src/transport/receiver.ts index 48fcd1d..996d546 100644 --- a/src/transport/receiver.ts +++ b/src/transport/receiver.ts @@ -59,7 +59,10 @@ export class Receiver { * @param {Object|JSON} body The body of the HTTP request * @return {CloudEvent} A new {CloudEvent} instance */ - accept(headers: Headers, body: string | Record | CloudEventV1 | CloudEventV03): CloudEvent { + accept( + headers: Headers, + body: string | Record | CloudEventV1 | CloudEventV03 | undefined | null, + ): CloudEvent { const cleanHeaders: Headers = sanitize(headers); const mode: Mode = getMode(cleanHeaders); const version = getVersion(mode, cleanHeaders, body); @@ -103,7 +106,7 @@ function getMode(headers: Headers): Mode { function getVersion( mode: Mode, headers: Headers, - body: string | Record | CloudEventV03 | CloudEventV1, + body: string | Record | CloudEventV03 | CloudEventV1 | undefined | null, ) { if (mode === Mode.BINARY) { // Check the headers for the version @@ -113,7 +116,7 @@ function getVersion( } } else { // structured mode - the version is in the body - return typeof body === "string" ? JSON.parse(body).specversion : body.specversion; + return typeof body === "string" ? JSON.parse(body).specversion : (body as CloudEvent).specversion; } return Version.V1; } diff --git a/test/integration/http_receiver_test.ts b/test/integration/http_receiver_test.ts index 8b6416a..d8b440b 100644 --- a/test/integration/http_receiver_test.ts +++ b/test/integration/http_receiver_test.ts @@ -39,6 +39,30 @@ describe("HTTP Transport Binding Receiver for CloudEvents", () => { expect((event.data as Record).lunch).to.equal("sushi"); }); + it("Accepts binary events when the data property is undefined", () => { + const binaryHeaders = { + "content-type": "application/json; charset=utf-8", + "ce-specversion": specversion, + "ce-id": id, + "ce-type": type, + "ce-source": source, + }; + const event = receiver.accept(binaryHeaders, undefined); + expect(event.data).to.be.undefined; + }); + + it("Accepts binary events when the data property is null", () => { + const binaryHeaders = { + "content-type": "application/json; charset=utf-8", + "ce-specversion": specversion, + "ce-id": id, + "ce-type": type, + "ce-source": source, + }; + const event = receiver.accept(binaryHeaders, null); + expect(event.data).to.be.undefined; + }); + it("Converts the JSON body of a structured event to an Object", () => { const payload = { id, diff --git a/test/integration/receiver_binary_03_tests.ts b/test/integration/receiver_binary_03_tests.ts index 025972e..9ac4c6d 100644 --- a/test/integration/receiver_binary_03_tests.ts +++ b/test/integration/receiver_binary_03_tests.ts @@ -9,18 +9,6 @@ const receiver = new BinaryHTTPReceiver(Version.V03); describe("HTTP Transport Binding Binary Receiver for CloudEvents v0.3", () => { describe("Check", () => { - it("Throw error when payload arg is null or undefined", () => { - // setup - const payload = undefined; - const attributes = {}; - - // act and assert - expect(receiver.parse.bind(receiver, (payload as unknown) as string, attributes)).to.throw( - ValidationError, - "payload is null or undefined", - ); - }); - it("Throw error when attributes arg is null or undefined", () => { // setup const payload = {}; diff --git a/test/integration/receiver_binary_1_tests.ts b/test/integration/receiver_binary_1_tests.ts index a527aae..368c55e 100644 --- a/test/integration/receiver_binary_1_tests.ts +++ b/test/integration/receiver_binary_1_tests.ts @@ -10,18 +10,6 @@ const receiver = new BinaryHTTPReceiver(Version.V1); describe("HTTP Transport Binding Binary Receiver for CloudEvents v1.0", () => { describe("Check", () => { - it("Throw error when payload arg is null or undefined", () => { - // setup - const payload = null; - const attributes = {}; - - // act and assert - expect(receiver.parse.bind(receiver, (payload as unknown) as string, attributes)).to.throw( - ValidationError, - "payload is null or undefined", - ); - }); - it("Throw error when attributes arg is null or undefined", () => { // setup const payload = {};