diff --git a/index.js b/index.js index 67d9ac3e..22e87aab 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,7 @@ const CloudEvent = require("./lib/cloudevent.js"); +const HTTPReceiver = require("./lib/bindings/http/http_receiver.js"); -module.exports = CloudEvent; +module.exports = { + CloudEvent, + HTTPReceiver +}; diff --git a/lib/bindings/http/http_receiver.js b/lib/bindings/http/http_receiver.js new file mode 100644 index 00000000..09128642 --- /dev/null +++ b/lib/bindings/http/http_receiver.js @@ -0,0 +1,61 @@ +const V03Binary = require("./receiver_binary_0_3"); +const V03Structured = require("./receiver_structured_0_3.js"); +const V1Binary = require("./receiver_binary_1.js"); +const V1Structured = require("./receiver_structured_1.js"); +const constants = require("./constants"); + +class HTTPReceiver { + constructor() { + this.receivers = { + v1: { + structured: new V1Structured(), + binary: new V1Binary() + }, + v03: { + structured: new V03Structured(), + binary: new V03Binary() + } + }; + } + + accept(headers, body) { + const mode = getMode(headers); + const version = getVersion(mode, headers, body); + switch (version) { + case constants.SPEC_V1: + return this.receivers.v1[mode].parse(body, headers); + case constants.SPEC_V03: + return this.receivers.v03[mode].parse(body, headers); + default: + console.error( + `Unknown spec version ${version}. Default to ${constants.SPEC_V1}`); + return this.receivers.v1[mode].parse(body, headers); + } + } +} + +function getMode(headers) { + let mode = "binary"; + const contentType = headers[constants.HEADER_CONTENT_TYPE]; + if (contentType && contentType.startsWith(constants.MIME_CE)) { + mode = "structured"; + } + return mode; +} + +function getVersion(mode, headers, body) { + let version = constants.SPEC_V1; // default to 1.0 + + if (mode === "binary") { + // Check the headers for the version + const versionHeader = headers[constants.DEFAULT_SPEC_VERSION_HEADER]; + if (versionHeader) { version = versionHeader; } + } else { + // structured mode - the version is in the body + version = body instanceof String + ? JSON.parse(body).specversion : body.specversion; + } + return version; +} + +module.exports = HTTPReceiver; diff --git a/test/bindings/http/promiscuous_receiver_test.js b/test/bindings/http/promiscuous_receiver_test.js new file mode 100644 index 00000000..e5509166 --- /dev/null +++ b/test/bindings/http/promiscuous_receiver_test.js @@ -0,0 +1,90 @@ +const { expect } = require("chai"); +const { CloudEvent, HTTPReceiver } = require("../../../index.js"); +const constants = require("../../../lib/bindings/http/constants.js"); + +const receiver = new HTTPReceiver(); +const id = "1234"; +const type = "org.cncf.cloudevents.test"; +const source = "urn:event:from:myapi/resourse/123"; +const data = { + lunch: "sushi" +}; + +describe("HTTP Transport Binding Receiver for CloudEvents", () => { + describe("V1", () => { + const specversion = "1.0"; + + it("Structured data returns a CloudEvent", () => { + const payload = { + id, + type, + source, + data, + specversion + }; + + const headers = { + [constants.HEADER_CONTENT_TYPE]: constants.MIME_CE_JSON + }; + + const event = receiver.accept(headers, payload); + validateEvent(event, specversion); + }); + + it("Binary data returns a CloudEvent", () => { + const headers = { + [constants.HEADER_CONTENT_TYPE]: constants.DEFAULT_CONTENT_TYPE, + [constants.DEFAULT_SPEC_VERSION_HEADER]: specversion, + [constants.BINARY_HEADERS_1.ID]: id, + [constants.BINARY_HEADERS_1.TYPE]: type, + [constants.BINARY_HEADERS_1.SOURCE]: source + }; + + const event = receiver.accept(headers, data); + validateEvent(event, specversion); + }); + }); + + describe("V03", () => { + const specversion = "0.3"; + + it("Structured data returns a CloudEvent", () => { + const payload = { + id, + type, + source, + data, + specversion + }; + + const headers = { + [constants.HEADER_CONTENT_TYPE]: constants.MIME_CE_JSON + }; + + const event = receiver.accept(headers, payload); + validateEvent(event, specversion); + }); + + it("Binary data returns a CloudEvent", () => { + const headers = { + [constants.HEADER_CONTENT_TYPE]: constants.DEFAULT_CONTENT_TYPE, + [constants.DEFAULT_SPEC_VERSION_HEADER]: specversion, + [constants.BINARY_HEADERS_03.ID]: id, + [constants.BINARY_HEADERS_03.TYPE]: type, + [constants.BINARY_HEADERS_03.SOURCE]: source + }; + + const event = receiver.accept(headers, data); + validateEvent(event, specversion); + }); + }); +}); + +function validateEvent(event, specversion) { + expect(event instanceof CloudEvent).to.equal(true); + expect(event.getId()).to.equal(id); + expect(event.getType()).to.equal(type); + expect(event.getSource()).to.equal(source); + expect(event.getData()).to.deep.equal(data); + expect(event.getSpecversion()).to.equal(specversion); +} diff --git a/test/bindings/http/receiver_structured_1_test.js b/test/bindings/http/receiver_structured_1_test.js index caee580e..2a5e9ee4 100644 --- a/test/bindings/http/receiver_structured_1_test.js +++ b/test/bindings/http/receiver_structured_1_test.js @@ -1,6 +1,6 @@ const expect = require("chai").expect; const v1 = require("../../../v1/index.js"); -const CloudEvent = require("../../../index.js"); +const { CloudEvent } = require("../../../index.js"); const { asBase64 } = require("../../../lib/utils/fun.js"); diff --git a/test/bindings/http/unmarshaller_0_3_tests.js b/test/bindings/http/unmarshaller_0_3_tests.js index 6bc3deb6..b9c807bb 100644 --- a/test/bindings/http/unmarshaller_0_3_tests.js +++ b/test/bindings/http/unmarshaller_0_3_tests.js @@ -1,6 +1,6 @@ const expect = require("chai").expect; const Unmarshaller = require("../../../lib/bindings/http/unmarshaller_0_3.js"); -const CloudEvent = require("../../../index.js"); +const { CloudEvent } = require("../../../index.js"); const v03 = require("../../../v03/index.js"); const type = "com.github.pull.create"; diff --git a/test/spec_0_3_tests.js b/test/spec_0_3_tests.js index ad6cfbfe..2f96acce 100644 --- a/test/spec_0_3_tests.js +++ b/test/spec_0_3_tests.js @@ -1,6 +1,6 @@ const expect = require("chai").expect; const Spec03 = require("../lib/specs/spec_0_3.js"); -const CloudEvent = require("../index.js"); +const { CloudEvent } = require("../index.js"); const { v4: uuidv4 } = require("uuid"); const id = uuidv4(); diff --git a/test/spec_1_tests.js b/test/spec_1_tests.js index 71ace864..af211f2a 100644 --- a/test/spec_1_tests.js +++ b/test/spec_1_tests.js @@ -1,6 +1,6 @@ const expect = require("chai").expect; const Spec1 = require("../lib/specs/spec_1.js"); -const CloudEvent = require("../index.js"); +const { CloudEvent } = require("../index.js"); const { v4: uuidv4 } = require("uuid"); const { asBase64 } = require("../lib/utils/fun.js");