From a0484d9e5b40faa059ef40b9b36922b467e7c3ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 6 Jun 2019 19:52:41 -0300 Subject: [PATCH 001/110] Arrangements to receiver impl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/{binary_0_1.js => emitter_binary_0_1.js} | 0 lib/bindings/http/{binary_0_2.js => emitter_binary_0_2.js} | 0 lib/cloudevent.js | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename lib/bindings/http/{binary_0_1.js => emitter_binary_0_1.js} (100%) rename lib/bindings/http/{binary_0_2.js => emitter_binary_0_2.js} (100%) diff --git a/lib/bindings/http/binary_0_1.js b/lib/bindings/http/emitter_binary_0_1.js similarity index 100% rename from lib/bindings/http/binary_0_1.js rename to lib/bindings/http/emitter_binary_0_1.js diff --git a/lib/bindings/http/binary_0_2.js b/lib/bindings/http/emitter_binary_0_2.js similarity index 100% rename from lib/bindings/http/binary_0_2.js rename to lib/bindings/http/emitter_binary_0_2.js diff --git a/lib/cloudevent.js b/lib/cloudevent.js index 45d83284..977934ea 100644 --- a/lib/cloudevent.js +++ b/lib/cloudevent.js @@ -3,8 +3,8 @@ var Spec02 = require("./specs/spec_0_2.js"); var JSONFormatter01 = require("./formats/json_0_1.js"); var HTTPStructured01 = require("./bindings/http/structured_0_1.js"); var HTTPStructured02 = require("./bindings/http/structured_0_2.js"); -var HTTPBinary01 = require("./bindings/http/binary_0_1.js"); -var HTTPBinary02 = require("./bindings/http/binary_0_2.js"); +var HTTPBinary01 = require("./bindings/http/emitter_binary_0_1.js"); +var HTTPBinary02 = require("./bindings/http/emitter_binary_0_2.js"); /* * Class created using the Builder Design Pattern. From 8b46c25588f41adb1e3fb6dfc065b84c1a0b97b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 6 Jun 2019 19:56:01 -0300 Subject: [PATCH 002/110] Arrangements to receiver impl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- .../http/{structured_0_1.js => emitter_structured_0_1.js} | 0 .../http/{structured_0_2.js => emitter_structured_0_2.js} | 0 lib/cloudevent.js | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename lib/bindings/http/{structured_0_1.js => emitter_structured_0_1.js} (100%) rename lib/bindings/http/{structured_0_2.js => emitter_structured_0_2.js} (100%) diff --git a/lib/bindings/http/structured_0_1.js b/lib/bindings/http/emitter_structured_0_1.js similarity index 100% rename from lib/bindings/http/structured_0_1.js rename to lib/bindings/http/emitter_structured_0_1.js diff --git a/lib/bindings/http/structured_0_2.js b/lib/bindings/http/emitter_structured_0_2.js similarity index 100% rename from lib/bindings/http/structured_0_2.js rename to lib/bindings/http/emitter_structured_0_2.js diff --git a/lib/cloudevent.js b/lib/cloudevent.js index 977934ea..c6006fe4 100644 --- a/lib/cloudevent.js +++ b/lib/cloudevent.js @@ -1,8 +1,8 @@ var Spec01 = require("./specs/spec_0_1.js"); var Spec02 = require("./specs/spec_0_2.js"); var JSONFormatter01 = require("./formats/json_0_1.js"); -var HTTPStructured01 = require("./bindings/http/structured_0_1.js"); -var HTTPStructured02 = require("./bindings/http/structured_0_2.js"); +var HTTPStructured01 = require("./bindings/http/emitter_structured_0_1.js"); +var HTTPStructured02 = require("./bindings/http/emitter_structured_0_2.js"); var HTTPBinary01 = require("./bindings/http/emitter_binary_0_1.js"); var HTTPBinary02 = require("./bindings/http/emitter_binary_0_2.js"); From 5794ba96d67dfb9207dddf43bb4610c111c255ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 6 Jun 2019 22:46:29 -0300 Subject: [PATCH 003/110] Starting the binding impl to receive events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_binary_0_2.js | 102 +++++++++++++++++++++ test/http_binding_0_2.js | 111 ++++++++++++++++++++++- 2 files changed, 209 insertions(+), 4 deletions(-) create mode 100644 lib/bindings/http/receiver_binary_0_2.js diff --git a/lib/bindings/http/receiver_binary_0_2.js b/lib/bindings/http/receiver_binary_0_2.js new file mode 100644 index 00000000..19b6aace --- /dev/null +++ b/lib/bindings/http/receiver_binary_0_2.js @@ -0,0 +1,102 @@ +var http = require("http"); +var Spec02 = require("../../specs/spec_0_2.js") +var spec02 = new Spec02(); + +const allowedContentTypes = []; +allowedContentTypes.push("application/cloudevents+json; charset=utf-8"); + +function is_http_request_valid(req, res, config) { + var valid = true; + + if(req.url === config.path + && req.method.toLowerCase() + === config.method.toLowerCase()) { + + if(!req.headers["content-type"] + || !allowedContentTypes.includes( + req.headers["content-type"].toLowerCase())){ + res.statusCode = 400; + res.end("Bad Request"); + + valid = false; + } + + } else if(req.url !== config.path) { + res.statusCode = 404; + res.end("Not Found"); + + valid = false; + } else { + res.statusCode = 405; + res.end("Method Not Allowed"); + + valid = false; + } + + return valid; +} + +function HTTPBinary(configuration){ + this.config = configuration; + + this.config["headers"] = { + "content-type":"application/cloudevents+json; charset=utf-8" + }; + + if(!this.config["path"]){ + this.config["path"] = "/"; + } + + if(!this.config["method"]){ + this.config["method"] = "POST"; + } +} + +HTTPBinary.prototype.receive = function(){ + this.server; + var self = this; + + return new Promise((resolve, reject) => { + self.server = + http.createServer((request, res) => { + if(is_http_request_valid(request, res, this.config)){ + var body = []; + request.on("error", err => { + console.error(err); + }) + .on("data", chunk => { + // accumulate the chunks + body.push(chunk); + }) + .on("end", () => { + body = Buffer.concat(body).toString(); + var jsonBody = JSON.parse(body); + + try { + // Process/validate the body + spec02.check(jsonBody); + + res.statusCode = 201; + res.end("Event Accepted"); + }catch(e) { + res.statusCode = 400; + res.end(JSON.stringify(e)); + } + }); + } + }); + + self.server.listen(this.config.port, (err) => { + if(err){ + console.error(err); + reject(err); + } + }); + }); +} + +HTTPBinary.prototype.stop = function() { + this.server.close(); +} + +module.exports = HTTPBinary; diff --git a/test/http_binding_0_2.js b/test/http_binding_0_2.js index 56849526..6bd5046f 100644 --- a/test/http_binding_0_2.js +++ b/test/http_binding_0_2.js @@ -1,6 +1,10 @@ -var expect = require("chai").expect; -var Cloudevent = require("../index.js"); -var nock = require("nock"); +var expect = require("chai").expect; +var Cloudevent = require("../index.js"); +var nock = require("nock"); +var ReceiverBinary01 = require("../lib/bindings/http/receiver_binary_0_2.js"); +var http = require("http"); +var request = require("request"); +var Spec02 = require("../lib/specs/spec_0_2.js"); const type = "com.github.pull.create"; const source = "urn:event:from:myapi/resourse/123"; @@ -20,10 +24,16 @@ const ext1Value = "foobar"; const ext2Name = "extension2"; const ext2Value = "acme"; +const receiverConfig = { + path : "/events", + port : 10300, + method : "POST" +}; + const Structured02 = Cloudevent.bindings["http-structured0.2"]; const Binary02 = Cloudevent.bindings["http-binary0.2"]; -var cloudevent = +var cloudevent = new Cloudevent() .type(type) .source(source) @@ -145,5 +155,98 @@ describe("HTTP Transport Binding - Version 0.2", () => { }); }); }); + + describe("Receiver", () => { + var receiver; + before(() => { + // setup + receiver = new ReceiverBinary01(receiverConfig); + receiver.receive() + .then(response => { + console.log(response); + }) + .catch(err => { + console.error(err); + }); + }); + + after(() => { + receiver.stop(); + }); + + it("Should return 404 when path is wrong", () => { + // act + request.post("http://localhost:" + receiverConfig.port + "/foobar", + (err, res, body) => { + // assert + expect(res.statusCode).to.equal(404); + }); + }); + + it("Should return 405 when method is wrong", () => { + // act + request.get("http://localhost:" + receiverConfig.port + + receiverConfig.path, + (err, res, body) => { + // assert + expect(res.statusCode).to.equal(405); + }); + }); + + it("Should return 400 when Content-Type is wrong", () => { + // act + request.post("http://localhost:" + receiverConfig.port + + receiverConfig.path, + (err, res, body) => { + // assert + expect(res.statusCode).to.equal(400); + }); + }); + + it("Should return 400 when is not a cloudevent", () => { + // setup + var requestOptions = { + url : "http://localhost:" + receiverConfig.port + + receiverConfig.path, + method : "POST", + headers : { + "Content-Type":"application/cloudevents+json; charset=utf-8" + }, + body : JSON.stringify({"foo": "bar"}) + }; + + // act + request(requestOptions, + (err, res, body) => { + // assert + expect(res.statusCode).to.equal(400); + }); + }); + + it("Should return 201 when accepts the event", () => { + // setup + var ce_spec02 = new Spec02(); + ce_spec02 + .type(type) + .source(source); + + var requestOptions = { + url : "http://localhost:" + receiverConfig.port + + receiverConfig.path, + method : "POST", + headers : { + "Content-Type":"application/cloudevents+json; charset=utf-8" + }, + body : JSON.stringify(ce_spec02.payload) + }; + + // act + request(requestOptions, + (err, res, body) => { + // assert + expect(res.statusCode).to.equal(201); + }); + }); + }); }); }); From a095a7f0caed9e8df3954041750412957dfc646a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 6 Jun 2019 22:46:53 -0300 Subject: [PATCH 004/110] Request dep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 1e1a75a2..e65d14a3 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,8 @@ "nock": "10.0.2", "codacy-coverage": "3.3.0", "mocha-lcov-reporter": "1.3.0", - "istanbul": "0.4.5" + "istanbul": "0.4.5", + "request": "^2.88.0" }, "publishConfig": { "access": "public" From a8a0c969588729601804a92ab22356c395348ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 6 Jun 2019 22:47:22 -0300 Subject: [PATCH 005/110] Method to valid any object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/specs/spec_0_2.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/specs/spec_0_2.js b/lib/specs/spec_0_2.js index ac105b7c..489af96c 100644 --- a/lib/specs/spec_0_2.js +++ b/lib/specs/spec_0_2.js @@ -30,16 +30,18 @@ function Spec02(){ } /* - * Check the spec constraints. + * Check the spec constraints */ -Spec02.prototype.check = function(){ - - var valid = validate(this.payload); +Spec02.prototype.check = function(ce){ + var to_check = ce; + if(!to_check) { + to_check = this.payload; + } + var valid = validate(to_check); if(!valid) { throw {message: "invalid payload", errors: validate.errors}; } - }; Spec02.prototype.type = function(_type){ From 680731d8b9b9201029b01d3157eab1ad46766de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 6 Jun 2019 22:48:02 -0300 Subject: [PATCH 006/110] Docs for the new functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 78 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 0679c122..1f3d2bb1 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,9 @@ Official CloudEvents' SDK for JavaScript. ### Before Spec reaches 1.0 -- `0.x.p`: where `x` relates to spec version and `p` relates to fixes, see -[semver](https://semver.org/). +- `0.x.p`: where `x` relates to spec version and `p` relates to fixes. -### After Spec reaches 1.0__ +### After Spec reaches 1.0 - `x.M.p`: where `x` relates to spec version, `M` relates to minor and `p` relates to fixes. See [semver](https://semver.org/) @@ -40,12 +39,15 @@ These are the supported specifications by this version. | HTTP Transport Binding - Binary | yes | yes | | JSON Event Format | yes | yes | +### What we can do? + + + ## How to use The `Cloudevent` constructor arguments. ```js - /* * spec : if is null, set the spec 0.1 impl * format: if is null, set the JSON Format 0.1 impl @@ -74,7 +76,7 @@ cloudevent01 .source("urn:event:from:myapi/resourse/123"); /* - * Backward compatibility to spec 0.1 by injecting methods from spec implementation + * Backward compatibility to spec 0.1 by injecting methods from spec implementation * to Cloudevent */ cloudevent01 @@ -104,7 +106,7 @@ var Cloudevent = require("cloudevents-sdk"); /* * Creates an instance with default spec and format */ -var cloudevent = +var cloudevent = new Cloudevent() .type("com.github.pull.create") .source("urn:event:from:myapi/resourse/123"); @@ -114,6 +116,7 @@ var cloudevent = */ var formatted = cloudevent.format(); +var ce = ``` #### Emitting @@ -147,7 +150,33 @@ binding.emit(cloudevent) console.log(response.data); }).catch(err => { - // Treat the error + // Deal with errors + console.error(err); + }); +``` + +#### Receiving + +```js +var Cloudevent = require("cloudevents-sdk"); + +// The binding configuration +var config = { + path : "/events", + port : 10300, + method : "POST" +}; + +// The binding instance +var binding = Cloudevent + .bindings["http-structured0.2"](config); + +binding.receive() + .then(cloudevent => { + // do something with event + }) + .catch(err => { + // deal with errors console.error(err); }); ``` @@ -179,7 +208,6 @@ binding.emit(cloudevent) The unit test checks the result of formatted payload and the constraints. ```bash - npm test ``` @@ -189,7 +217,6 @@ npm test ### `Cloudevent` class ```js - /* * Format the payload and return an Object. */ @@ -200,6 +227,11 @@ Object Cloudevent.format() */ String Cloudevent.toString() +/* + * Create a Cloudevent instance from String. + */ +Cloudevent Cloudevent.fromString(String) + ``` ### `Formatter` classes @@ -207,7 +239,6 @@ String Cloudevent.toString() Every formatter class must implement these methods to work properly. ```js - /* * Format the Cloudevent payload argument and return an Object. */ @@ -225,7 +256,6 @@ String Formatter.toString(payload) Every Spec class must implement these methods to work properly. ```js - /* * The constructor must receives the Cloudevent type. */ @@ -236,13 +266,21 @@ Spec(Cloudevent) */ Spec.check() +/* + * Checks if the argument pass through the spec constraints + */ +Spec.check(Object) + ``` ### `Binding` classes Every Binding class must implement these methods to work properly. -```js +#### Emitter Binding + +Following we have the signature for the binding to emit Cloudevents. +```js /* * The constructor must receives the map of configurations. */ @@ -255,6 +293,22 @@ Binding.emit(cloudevent) ``` +#### Receiver Binding + +Following we have the signature for the binding to receive Cloudevents. + +```js +/* + * The constructor must receives the map of configurations. + */ +ReceiverBinding(config) + +/* + * Receives the events and returns a Promise. + */ +ReceiverBinding.receive() +``` + > See how to implement the method injection [here](lib/specs/spec_0_1.js#L17) > > Learn about [Builder Design Pattern](https://en.wikipedia.org/wiki/Builder_pattern) From 854d4e38cb49243b18505db6da5e8104a35136ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 6 Jun 2019 23:21:04 -0300 Subject: [PATCH 007/110] Event receiver for structure version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- ...{receiver_binary_0_2.js => receiver_structured_0_2.js} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename lib/bindings/http/{receiver_binary_0_2.js => receiver_structured_0_2.js} (92%) diff --git a/lib/bindings/http/receiver_binary_0_2.js b/lib/bindings/http/receiver_structured_0_2.js similarity index 92% rename from lib/bindings/http/receiver_binary_0_2.js rename to lib/bindings/http/receiver_structured_0_2.js index 19b6aace..77caea07 100644 --- a/lib/bindings/http/receiver_binary_0_2.js +++ b/lib/bindings/http/receiver_structured_0_2.js @@ -36,7 +36,7 @@ function is_http_request_valid(req, res, config) { return valid; } -function HTTPBinary(configuration){ +function HTTPStructured(configuration){ this.config = configuration; this.config["headers"] = { @@ -52,7 +52,7 @@ function HTTPBinary(configuration){ } } -HTTPBinary.prototype.receive = function(){ +HTTPStructured.prototype.receive = function(){ this.server; var self = this; @@ -95,8 +95,8 @@ HTTPBinary.prototype.receive = function(){ }); } -HTTPBinary.prototype.stop = function() { +HTTPStructured.prototype.stop = function() { this.server.close(); } -module.exports = HTTPBinary; +module.exports = HTTPStructured; From 1a88690da6444650a6ac2c63d8bf654e8b1887f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 6 Jun 2019 23:21:50 -0300 Subject: [PATCH 008/110] Event receiver for structure version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 2 +- test/http_binding_0_2.js | 159 ++++++++++++++++++++------------------- 2 files changed, 81 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index 1f3d2bb1..51f662bf 100644 --- a/README.md +++ b/README.md @@ -169,7 +169,7 @@ var config = { // The binding instance var binding = Cloudevent - .bindings["http-structured0.2"](config); + .bindings["http-structured0.2"](config); binding.receive() .then(cloudevent => { diff --git a/test/http_binding_0_2.js b/test/http_binding_0_2.js index 6bd5046f..b5ea70fd 100644 --- a/test/http_binding_0_2.js +++ b/test/http_binding_0_2.js @@ -1,7 +1,8 @@ var expect = require("chai").expect; var Cloudevent = require("../index.js"); var nock = require("nock"); -var ReceiverBinary01 = require("../lib/bindings/http/receiver_binary_0_2.js"); +var ReceiverStructured01 = + require("../lib/bindings/http/receiver_structured_0_2.js"); var http = require("http"); var request = require("request"); var Spec02 = require("../lib/specs/spec_0_2.js"); @@ -78,89 +79,12 @@ describe("HTTP Transport Binding - Version 0.2", () => { }); }); }); - }); - - describe("Binary", () => { - describe("JSON Format", () => { - it("requires '" + cloudevent.getContenttype() + "' Content-Type in the header", () => { - return httpbinary02.emit(cloudevent) - .then((response) => { - expect(response.config.headers["Content-Type"]) - .to.equal(cloudevent.getContenttype()); - }); - }); - - it("the request payload should be correct", () => { - return httpbinary02.emit(cloudevent) - .then((response) => { - expect(JSON.parse(response.config.data)) - .to.deep.equal(cloudevent.getData()); - }); - }); - - it("HTTP Header contains 'ce-type'", () => { - return httpbinary02.emit(cloudevent) - .then((response) => { - expect(response.config.headers) - .to.have.property("ce-type"); - }); - }); - it("HTTP Header contains 'ce-specversion'", () => { - return httpbinary02.emit(cloudevent) - .then((response) => { - expect(response.config.headers) - .to.have.property("ce-specversion"); - }); - }); - it("HTTP Header contains 'ce-source'", () => { - return httpbinary02.emit(cloudevent) - .then((response) => { - expect(response.config.headers) - .to.have.property("ce-source"); - }); - }); - it("HTTP Header contains 'ce-id'", () => { - return httpbinary02.emit(cloudevent) - .then((response) => { - expect(response.config.headers) - .to.have.property("ce-id"); - }); - }); - it("HTTP Header contains 'ce-time'", () => { - return httpbinary02.emit(cloudevent) - .then((response) => { - expect(response.config.headers) - .to.have.property("ce-time"); - }); - }); - it("HTTP Header contains 'ce-schemaurl'", () => { - return httpbinary02.emit(cloudevent) - .then((response) => { - expect(response.config.headers) - .to.have.property("ce-schemaurl"); - }); - }); - it("HTTP Header contains 'ce-" + ext1Name + "'", () => { - return httpbinary02.emit(cloudevent) - .then((response) => { - expect(response.config.headers) - .to.have.property("ce-" + ext1Name); - }); - }); - it("HTTP Header contains 'ce-" + ext2Name + "'", () => { - return httpbinary02.emit(cloudevent) - .then((response) => { - expect(response.config.headers) - .to.have.property("ce-" + ext2Name); - }); - }); - }); describe("Receiver", () => { var receiver; before(() => { // setup - receiver = new ReceiverBinary01(receiverConfig); + receiver = new ReceiverStructured01(receiverConfig); receiver.receive() .then(response => { console.log(response); @@ -249,4 +173,81 @@ describe("HTTP Transport Binding - Version 0.2", () => { }); }); }); + + describe("Binary", () => { + describe("JSON Format", () => { + it("requires '" + cloudevent.getContenttype() + "' Content-Type in the header", () => { + return httpbinary02.emit(cloudevent) + .then((response) => { + expect(response.config.headers["Content-Type"]) + .to.equal(cloudevent.getContenttype()); + }); + }); + + it("the request payload should be correct", () => { + return httpbinary02.emit(cloudevent) + .then((response) => { + expect(JSON.parse(response.config.data)) + .to.deep.equal(cloudevent.getData()); + }); + }); + + it("HTTP Header contains 'ce-type'", () => { + return httpbinary02.emit(cloudevent) + .then((response) => { + expect(response.config.headers) + .to.have.property("ce-type"); + }); + }); + it("HTTP Header contains 'ce-specversion'", () => { + return httpbinary02.emit(cloudevent) + .then((response) => { + expect(response.config.headers) + .to.have.property("ce-specversion"); + }); + }); + it("HTTP Header contains 'ce-source'", () => { + return httpbinary02.emit(cloudevent) + .then((response) => { + expect(response.config.headers) + .to.have.property("ce-source"); + }); + }); + it("HTTP Header contains 'ce-id'", () => { + return httpbinary02.emit(cloudevent) + .then((response) => { + expect(response.config.headers) + .to.have.property("ce-id"); + }); + }); + it("HTTP Header contains 'ce-time'", () => { + return httpbinary02.emit(cloudevent) + .then((response) => { + expect(response.config.headers) + .to.have.property("ce-time"); + }); + }); + it("HTTP Header contains 'ce-schemaurl'", () => { + return httpbinary02.emit(cloudevent) + .then((response) => { + expect(response.config.headers) + .to.have.property("ce-schemaurl"); + }); + }); + it("HTTP Header contains 'ce-" + ext1Name + "'", () => { + return httpbinary02.emit(cloudevent) + .then((response) => { + expect(response.config.headers) + .to.have.property("ce-" + ext1Name); + }); + }); + it("HTTP Header contains 'ce-" + ext2Name + "'", () => { + return httpbinary02.emit(cloudevent) + .then((response) => { + expect(response.config.headers) + .to.have.property("ce-" + ext2Name); + }); + }); + }); + }); }); From e17b2b1809aec4aeeb3d2913c2db68ab933fbb38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 6 Jun 2019 23:22:55 -0300 Subject: [PATCH 009/110] Fix function name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_structured_0_2.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/bindings/http/receiver_structured_0_2.js b/lib/bindings/http/receiver_structured_0_2.js index 77caea07..61858267 100644 --- a/lib/bindings/http/receiver_structured_0_2.js +++ b/lib/bindings/http/receiver_structured_0_2.js @@ -5,7 +5,7 @@ var spec02 = new Spec02(); const allowedContentTypes = []; allowedContentTypes.push("application/cloudevents+json; charset=utf-8"); -function is_http_request_valid(req, res, config) { +function is_valid_http_request(req, res, config) { var valid = true; if(req.url === config.path @@ -59,7 +59,7 @@ HTTPStructured.prototype.receive = function(){ return new Promise((resolve, reject) => { self.server = http.createServer((request, res) => { - if(is_http_request_valid(request, res, this.config)){ + if(is_valid_http_request(request, res, this.config)){ var body = []; request.on("error", err => { console.error(err); From 0e21aa27f66738781820fa0f1c42091f73fccd47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sat, 8 Jun 2019 18:57:14 -0300 Subject: [PATCH 010/110] check() with error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 51f662bf..a2aa8c8a 100644 --- a/README.md +++ b/README.md @@ -263,11 +263,13 @@ Spec(Cloudevent) /* * Checks the spec constraints, throwing an error if do not pass. + * @throws Error when it is an invalid event */ Spec.check() /* * Checks if the argument pass through the spec constraints + * @throws Error when it is an invalid event */ Spec.check(Object) From e9a68e19ff64f8d6430abfb91804ce218385a190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sat, 8 Jun 2019 19:04:30 -0300 Subject: [PATCH 011/110] Remove unused config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_structured_0_2.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/bindings/http/receiver_structured_0_2.js b/lib/bindings/http/receiver_structured_0_2.js index 61858267..70751187 100644 --- a/lib/bindings/http/receiver_structured_0_2.js +++ b/lib/bindings/http/receiver_structured_0_2.js @@ -39,10 +39,6 @@ function is_valid_http_request(req, res, config) { function HTTPStructured(configuration){ this.config = configuration; - this.config["headers"] = { - "content-type":"application/cloudevents+json; charset=utf-8" - }; - if(!this.config["path"]){ this.config["path"] = "/"; } From 2550d732f55f597b400dc17a5c66965e93870882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sat, 8 Jun 2019 19:13:02 -0300 Subject: [PATCH 012/110] Interface to bind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_structured_0_2.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/bindings/http/receiver_structured_0_2.js b/lib/bindings/http/receiver_structured_0_2.js index 70751187..81eec42a 100644 --- a/lib/bindings/http/receiver_structured_0_2.js +++ b/lib/bindings/http/receiver_structured_0_2.js @@ -46,6 +46,10 @@ function HTTPStructured(configuration){ if(!this.config["method"]){ this.config["method"] = "POST"; } + + if(!this.config["interface"]){ + this.config["interface"] = "0.0.0.0"; + } } HTTPStructured.prototype.receive = function(){ @@ -82,7 +86,7 @@ HTTPStructured.prototype.receive = function(){ } }); - self.server.listen(this.config.port, (err) => { + self.server.listen(this.config.port, this.config.interface, (err) => { if(err){ console.error(err); reject(err); From d84c3d5b0ebb239b39a683c32a86bfc999cf2ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 9 Jun 2019 19:52:26 -0300 Subject: [PATCH 013/110] Fix the test script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e65d14a3..8a472d67 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "CloudEvents SDK for JavaScript", "main": "index.js", "scripts": { - "test": "./node_modules/.bin/mocha -C test/*.js", + "test": "./node_modules/.bin/mocha -C test/**/*.js", "coverage": "./node_modules/.bin/istanbul cover -x '**/test/**' _mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/.bin/codacy-coverage && rm -rf ./coverage" }, "repository": { From 15f89e5e971f09fc399cf61578d8630635c8380d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 9 Jun 2019 20:56:05 -0300 Subject: [PATCH 014/110] Folder for bindings test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- test/bindings/http/unmarshaller_0_2_tests.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 test/bindings/http/unmarshaller_0_2_tests.js diff --git a/test/bindings/http/unmarshaller_0_2_tests.js b/test/bindings/http/unmarshaller_0_2_tests.js new file mode 100644 index 00000000..5dca1cf3 --- /dev/null +++ b/test/bindings/http/unmarshaller_0_2_tests.js @@ -0,0 +1,15 @@ +var expect = require("chai").expect; +var Unmarshaller = require("../../../lib/bindings/http/unmarshaller_0_2.js"); + +describe("HTTP Unmarshaller - Version 0.2", () => { + + it("Throw error when payload is not string or object", () => { + // setup + var payload = 83; + var unmarshaller = new Unmarshaller(); + + // act and assert + expect(unmarshaller.unmarshall.bind(payload)) + .to.throw("Invalid payload type, allowed are: string or object"); + }); +}); From c1a2b29bae462550e0a5d75b0532d6d71bb8d11c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 9 Jun 2019 20:56:22 -0300 Subject: [PATCH 015/110] Folder for formats tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- test/formats/json/parser_test.js | 109 +++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 test/formats/json/parser_test.js diff --git a/test/formats/json/parser_test.js b/test/formats/json/parser_test.js new file mode 100644 index 00000000..8619988e --- /dev/null +++ b/test/formats/json/parser_test.js @@ -0,0 +1,109 @@ +var expect = require("chai").expect; +var Parser = require("../../../lib/formats/json/parser.js"); +var Cloudevent = require("../../../index.js"); + +const type = "com.github.pull.create"; +const source = "urn:event:from:myapi/resourse/123"; +const webhook = "https://cloudevents.io/webhook"; +const contentType = "application/cloudevents+json; charset=utf-8"; +const now = new Date(); +const schemaurl = "http://cloudevents.io/schema.json"; + +const ceContentType = "application/json"; + +const data = { + foo: "bar" +}; + +describe("JSON Event Format Parser", () => { + + it("Throw error when payload is an integer", () => { + // setup + var payload = 83; + var parser = new Parser(); + + // act and assert + expect(parser.parse.bind(parser, payload)) + .to.throw("invalid payload type, allowed are: string or object"); + }); + + it("Throw error when payload is null", () => { + // setup + var payload = null; + var parser = new Parser(); + + // act and assert + expect(parser.parse.bind(parser, payload)) + .to.throw("null or undefined payload"); + }); + + it("Throw error when payload is undefined", () => { + // setup + var parser = new Parser(); + + // act and assert + expect(parser.parse.bind(parser)) + .to.throw("null or undefined payload"); + }); + + it("Throw error when payload is a float", () => { + // setup + var payload = 8.3; + var parser = new Parser(); + + // act and assert + expect(parser.parse.bind(parser, payload)) + .to.throw("invalid payload type, allowed are: string or object"); + }); + + it("Throw error when payload is an invalid JSON", () => { + // setup + var payload = "gg"; + var parser = new Parser(); + + // act and assert + expect(parser.parse.bind(parser, payload)) + .to.throw("invalid json payload"); + }); + + it("Throw error when payload is an invalid CloudEvent spec 0.2", () => { + // setup + var payload = + new Cloudevent() + .type(type) + .source(source) + .contenttype(ceContentType) + .time(now) + .schemaurl(schemaurl) + .data(data) + .toString(); + + var parser = new Parser(); + + // act and assert + expect(parser.parse.bind(parser, payload)) + .to.throw("invalid payload"); + }); + + it("Must accept the CloudEvent spec 0.2 as JSON", () => { + // setup + var payload = + new Cloudevent(Cloudevent.specs["0.2"]) + .type(type) + .source(source) + .contenttype(ceContentType) + .time(now) + .schemaurl(schemaurl) + .data(data) + .toString(); + + var parser = new Parser(); + + // act + var actual = parser.parse(payload); + + // assert + expect(actual) + .to.be.an("object"); + }); +}); From a24954514ab27999d0d18213dad1773d6d371523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 9 Jun 2019 20:56:41 -0300 Subject: [PATCH 016/110] Structure for formats impl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/formats/json/formatter.js | 18 +++++++++++ lib/formats/json/parser.js | 56 +++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 lib/formats/json/formatter.js create mode 100644 lib/formats/json/parser.js diff --git a/lib/formats/json/formatter.js b/lib/formats/json/formatter.js new file mode 100644 index 00000000..4f8db002 --- /dev/null +++ b/lib/formats/json/formatter.js @@ -0,0 +1,18 @@ + +function JSONFormatter(){ + +} + +/* + * Every internal data structure are JSON by nature, them + * no transformation is required + */ +JSONFormatter.prototype.format = function(payload){ + return payload; +}; + +JSONFormatter.prototype.toString = function(payload){ + return JSON.stringify(payload); +}; + +module.exports = JSONFormatter; diff --git a/lib/formats/json/parser.js b/lib/formats/json/parser.js new file mode 100644 index 00000000..e2cd9385 --- /dev/null +++ b/lib/formats/json/parser.js @@ -0,0 +1,56 @@ +var Spec02 = require("../../specs/spec_0_2.js"); + +const spec = new Spec02(); + +function JSONParser() { + +} + +/** + * Level 0 of validation: is that string? is that JSON? + */ +function validate_and_parse_as_json(payload) { + var json = payload; + + if(payload) { + if( (typeof payload) == "string"){ + try { + json = JSON.parse(payload); + + }catch(e) { + throw {message: "invalid json payload", errors: e}; + } + + } else if( (typeof payload) != "object"){ + // anything else + throw {message: "invalid payload type, allowed are: string or object"}; + } + } else { + throw {message: "null or undefined payload"}; + } + + return json; +} + +/* + * Level 1 of validation: is that follow a spec? + */ +function validate_spec(payload) { + + spec.check(payload); + + return payload; +} + +JSONParser.prototype.parse = function(payload) { + + // Level 0 of validation: is that string? is that JSON? + var valid0 = validate_and_parse_as_json(payload); + + // Level 1 of validation: is that follow a spec? + var valid1 = validate_spec(valid0); + + return valid1; +} + +module.exports = JSONParser; From 7e2d11fcdd987348f715fb25401b6ddb214bf5c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 9 Jun 2019 20:56:51 -0300 Subject: [PATCH 017/110] Structure for formats impl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/formats/json_0_1.js | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 lib/formats/json_0_1.js diff --git a/lib/formats/json_0_1.js b/lib/formats/json_0_1.js deleted file mode 100644 index dc5ffa5c..00000000 --- a/lib/formats/json_0_1.js +++ /dev/null @@ -1,14 +0,0 @@ - -function JSONFormatter(){ - -} - -JSONFormatter.prototype.format = function(payload){ - return payload; -}; - -JSONFormatter.prototype.toString = function(payload){ - return JSON.stringify(payload); -}; - -module.exports = JSONFormatter; From 0f9fadb718ef818c4327f2c71b353df144bb501b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 9 Jun 2019 20:58:01 -0300 Subject: [PATCH 018/110] Fix the json format import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/cloudevent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cloudevent.js b/lib/cloudevent.js index c6006fe4..40fd0496 100644 --- a/lib/cloudevent.js +++ b/lib/cloudevent.js @@ -1,6 +1,6 @@ var Spec01 = require("./specs/spec_0_1.js"); var Spec02 = require("./specs/spec_0_2.js"); -var JSONFormatter01 = require("./formats/json_0_1.js"); +var JSONFormatter01 = require("./formats/json/formatter.js"); var HTTPStructured01 = require("./bindings/http/emitter_structured_0_1.js"); var HTTPStructured02 = require("./bindings/http/emitter_structured_0_2.js"); var HTTPBinary01 = require("./bindings/http/emitter_binary_0_1.js"); From 25c4ad27f7690ab0f8b538f177edc12429bf30ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 9 Jun 2019 20:58:44 -0300 Subject: [PATCH 019/110] Docs for parser, fix project structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a2aa8c8a..d2e5c32e 100644 --- a/README.md +++ b/README.md @@ -185,11 +185,13 @@ binding.receive() ```text ├── index.js +├── ext ├── lib │   ├── bindings │   │   └── http │   ├── cloudevent.js -│   ├── format +│   ├── formats +│   │   └── json │   └── specs ├── LICENSE ├── package.json @@ -197,10 +199,11 @@ binding.receive() ``` - `index.js`: library exports +- `ext`: external stuff, e.g, Cloud Events JSONSchema - `lib/bindings`: every binding implementation goes here - `lib/bindings/http`: every http binding implementation goes here - `lib/cloudevent.js`: implementation of Cloudevent, an interface -- `lib/format/`: every format implementation goes here +- `lib/formats/`: every format implementation goes here - `lib/specs/`: every spec implementation goes here ## Unit Testing @@ -209,7 +212,6 @@ The unit test checks the result of formatted payload and the constraints. ```bash npm test - ``` ## The API @@ -242,13 +244,23 @@ Every formatter class must implement these methods to work properly. /* * Format the Cloudevent payload argument and return an Object. */ -Object Formatter.format(payload) +Object Formatter.format(Object) /* * Format the Cloudevent payload as String. */ -String Formatter.toString(payload) +String Formatter.toString(Object) +``` + +### `Parser` classes + +Every formatter class must implement these methods to work properly. +```js +/* + * Try to parse the payload to some event format + */ +Object Parser.parse(payload) ``` ## `Spec` classes @@ -272,8 +284,8 @@ Spec.check() * @throws Error when it is an invalid event */ Spec.check(Object) - ``` + ### `Binding` classes Every Binding class must implement these methods to work properly. From a3884160be55423f33a0162ba6dfd3af48455c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 9 Jun 2019 21:04:41 -0300 Subject: [PATCH 020/110] Umarchaller impl start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/unmarshaller_0_2.js | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 lib/bindings/http/unmarshaller_0_2.js diff --git a/lib/bindings/http/unmarshaller_0_2.js b/lib/bindings/http/unmarshaller_0_2.js new file mode 100644 index 00000000..6fdea1ec --- /dev/null +++ b/lib/bindings/http/unmarshaller_0_2.js @@ -0,0 +1,40 @@ + +const content_type_header = "content-type"; +const ce_structured_content_type = "application/cloudevents"; + +/** + * Level 0 of validation: is that string? is that JSON? + */ +function validate_and_parse_as_json(payload) { + var json = payload; + + if( (typeof payload) === "string"){ + try { + json = JSON.parse(payload); + + }catch(e) { + throw {message: "Invalid payload", errors: e}; + } + + } else if( (typeof payload) !== "object"){ + // anything else + throw {message: "Invalid payload type, allowed are: string or object"}; + } + + return json; +} + +var Unmarshaller = function() { + +} + +Unmarshaller.prototype.unmarshall = function(payload, headers) { + + var valid0 = validate_and_parse_as_json(payload); + + //TODO binary or structured ? + //"Content-Type" + +} + +module.exports = Unmarshaller; From 6e8f63c45bef93c96450c49729296e5b9e866926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 9 Jun 2019 22:43:56 -0300 Subject: [PATCH 021/110] What can we do draft MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d2e5c32e..0e127e25 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,12 @@ These are the supported specifications by this version. ### What we can do? - +| **What** | **v0.1** | **v0.2** | +|---------------------------------------|----------|----------| +| Create events | yes | yes | +| Emit Structured events over HTTP | yes | yes | +| Emit Binary events over HTTP - | yes | yes | +| JSON Event Format | yes | yes | ## How to use From 2ca88b089ca3c2585dfa28815f70748110c9a9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 9 Jun 2019 22:44:29 -0300 Subject: [PATCH 022/110] HTTP unmarshaller: args validations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/unmarshaller_0_2.js | 60 +++++++++++++------- test/bindings/http/unmarshaller_0_2_tests.js | 60 ++++++++++++++++++-- 2 files changed, 93 insertions(+), 27 deletions(-) diff --git a/lib/bindings/http/unmarshaller_0_2.js b/lib/bindings/http/unmarshaller_0_2.js index 6fdea1ec..760aa95c 100644 --- a/lib/bindings/http/unmarshaller_0_2.js +++ b/lib/bindings/http/unmarshaller_0_2.js @@ -2,26 +2,45 @@ const content_type_header = "content-type"; const ce_structured_content_type = "application/cloudevents"; -/** - * Level 0 of validation: is that string? is that JSON? - */ -function validate_and_parse_as_json(payload) { - var json = payload; - - if( (typeof payload) === "string"){ - try { - json = JSON.parse(payload); - - }catch(e) { - throw {message: "Invalid payload", errors: e}; - } +const allowed_binary_content_types = []; +allowed_binary_content_types.push("application/json"); + +const allowed_structured_content_types = []; +allowed_structured_content_types.push("application/cloudevents+json"); + +function validate_args(payload, headers) { + if(!payload){ + throw {message: "payload is null or undefined"}; + } - } else if( (typeof payload) !== "object"){ - // anything else - throw {message: "Invalid payload type, allowed are: string or object"}; + if(!headers){ + throw {message: "headers is null or undefined"}; } - return json; + if(!headers[content_type_header]){ + throw {message: "content-type header not found"}; + } +} + +// Is it binary or structured? +function resolve_binding_type(payload, headers) { + + var contentType = headers[content_type_header]; + if(contentType.startsWith(ce_structured_content_type)){ + // Structured + if(allowed_structured_content_types.includes(contentType)){ + + } else { + throw {message: "structured+type not allowed", errors: [contentType]}; + } + } else { + // Binary + if(allowed_binary_content_types.includes(contentType)){ + + } else { + throw {message: "content type not allowed", errors : [contentType]}; + } + } } var Unmarshaller = function() { @@ -29,11 +48,10 @@ var Unmarshaller = function() { } Unmarshaller.prototype.unmarshall = function(payload, headers) { + validate_args(payload, headers); - var valid0 = validate_and_parse_as_json(payload); - - //TODO binary or structured ? - //"Content-Type" + // Resolve the binding + var binding = resolve_binding_type(payload, headers); } diff --git a/test/bindings/http/unmarshaller_0_2_tests.js b/test/bindings/http/unmarshaller_0_2_tests.js index 5dca1cf3..0dddebac 100644 --- a/test/bindings/http/unmarshaller_0_2_tests.js +++ b/test/bindings/http/unmarshaller_0_2_tests.js @@ -1,15 +1,63 @@ var expect = require("chai").expect; var Unmarshaller = require("../../../lib/bindings/http/unmarshaller_0_2.js"); -describe("HTTP Unmarshaller - Version 0.2", () => { +describe("HTTP Transport Binding Unmarshaller", () => { - it("Throw error when payload is not string or object", () => { + it("Throw error when payload is null", () => { // setup - var payload = 83; - var unmarshaller = new Unmarshaller(); + var payload = null; + var un = new Unmarshaller(); // act and assert - expect(unmarshaller.unmarshall.bind(payload)) - .to.throw("Invalid payload type, allowed are: string or object"); + expect(un.unmarshall.bind(un, payload)) + .to.throw("payload is null or undefined"); + }); + + it("Throw error when headers is null", () => { + // setup + var payload = {}; + var headers = null; + var un = new Unmarshaller(); + + // act and assert + expect(un.unmarshall.bind(un, payload, headers)) + .to.throw("headers is null or undefined"); + }); + + it("Throw error when there is no content-type header", () => { + // setup + var payload = {}; + var headers = {}; + var un = new Unmarshaller(); + + // act and assert + expect(un.unmarshall.bind(un, payload, headers)) + .to.throw("content-type header not found"); + }); + + it("Throw error when content-type is not allowed", () => { + // setup + var payload = {}; + var headers = { + "content-type":"text/xml" + }; + var un = new Unmarshaller(); + + // act and assert + expect(un.unmarshall.bind(un, payload, headers)) + .to.throw("content type not allowed"); + }); + + it("Throw error when structured binding has not allowed mime", () => { + // setup + var payload = {}; + var headers = { + "content-type":"application/cloudevents+zip" + }; + var un = new Unmarshaller(); + + // act and assert + expect(un.unmarshall.bind(un, payload, headers)) + .to.throw("structured+type not allowed"); }); }); From 232b39b5b34e549f07096bc4bac98ea6afcc9d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Mon, 10 Jun 2019 21:14:52 -0300 Subject: [PATCH 023/110] Comments, spec0.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/formats/json/parser.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/formats/json/parser.js b/lib/formats/json/parser.js index e2cd9385..b914b1a4 100644 --- a/lib/formats/json/parser.js +++ b/lib/formats/json/parser.js @@ -1,6 +1,6 @@ var Spec02 = require("../../specs/spec_0_2.js"); -const spec = new Spec02(); +const spec02 = new Spec02(); function JSONParser() { @@ -37,7 +37,8 @@ function validate_and_parse_as_json(payload) { */ function validate_spec(payload) { - spec.check(payload); + // is that follow spec 0.2? + spec02.check(payload); return payload; } From 8915048791d7fb4727ab59cb64e42f77b1afe331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Mon, 10 Jun 2019 21:20:04 -0300 Subject: [PATCH 024/110] Spec as parser parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/formats/json/parser.js | 12 ++++++------ test/formats/json/parser_test.js | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/formats/json/parser.js b/lib/formats/json/parser.js index b914b1a4..115b6aed 100644 --- a/lib/formats/json/parser.js +++ b/lib/formats/json/parser.js @@ -2,8 +2,8 @@ var Spec02 = require("../../specs/spec_0_2.js"); const spec02 = new Spec02(); -function JSONParser() { - +function JSONParser(_spec) { + this.spec = (_spec) ? _spec : new Spec02(); } /** @@ -35,10 +35,10 @@ function validate_and_parse_as_json(payload) { /* * Level 1 of validation: is that follow a spec? */ -function validate_spec(payload) { +function validate_spec(payload, spec) { - // is that follow spec 0.2? - spec02.check(payload); + // is that follow the spec? + spec.check(payload); return payload; } @@ -49,7 +49,7 @@ JSONParser.prototype.parse = function(payload) { var valid0 = validate_and_parse_as_json(payload); // Level 1 of validation: is that follow a spec? - var valid1 = validate_spec(valid0); + var valid1 = validate_spec(valid0, this.spec); return valid1; } diff --git a/test/formats/json/parser_test.js b/test/formats/json/parser_test.js index 8619988e..41b6e75a 100644 --- a/test/formats/json/parser_test.js +++ b/test/formats/json/parser_test.js @@ -97,7 +97,7 @@ describe("JSON Event Format Parser", () => { .data(data) .toString(); - var parser = new Parser(); + var parser = new Parser(new Cloudevent.specs["0.2"]()); // act var actual = parser.parse(payload); From 7bf643491f6005c07b30fe7c1997af3a01992b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Mon, 10 Jun 2019 21:25:26 -0300 Subject: [PATCH 025/110] Document the what and Parser API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0e127e25..2071c1b2 100644 --- a/README.md +++ b/README.md @@ -41,12 +41,14 @@ These are the supported specifications by this version. ### What we can do? -| **What** | **v0.1** | **v0.2** | -|---------------------------------------|----------|----------| -| Create events | yes | yes | -| Emit Structured events over HTTP | yes | yes | -| Emit Binary events over HTTP - | yes | yes | -| JSON Event Format | yes | yes | +| __What__ | __v0.1__ | __v0.2__ | +|------------------------------------|----------|----------| +| Create events | yes | yes | +| Emit Structured events over HTTP | yes | yes | +| Emit Binary events over HTTP | yes | yes | +| JSON Event Format | yes | yes | +| Receice Structure events over HTTP | yes | yes | +| Receice Binary events over HTTP | yes | yes | ## How to use @@ -262,13 +264,18 @@ String Formatter.toString(Object) Every formatter class must implement these methods to work properly. ```js +/* + * The default constructor with Spec as parameter + */ +Parser(Spec) + /* * Try to parse the payload to some event format */ Object Parser.parse(payload) ``` -## `Spec` classes +### `Spec` classes Every Spec class must implement these methods to work properly. From c84f6a5e372fc6d72be64644bf1c3f9f8a902830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 10:23:11 -0300 Subject: [PATCH 026/110] Unmarshall for structured MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/unmarshaller_0_2.js | 35 ++++++++++-- test/bindings/http/unmarshaller_0_2_tests.js | 59 ++++++++++++++++---- 2 files changed, 78 insertions(+), 16 deletions(-) diff --git a/lib/bindings/http/unmarshaller_0_2.js b/lib/bindings/http/unmarshaller_0_2.js index 760aa95c..31cf543c 100644 --- a/lib/bindings/http/unmarshaller_0_2.js +++ b/lib/bindings/http/unmarshaller_0_2.js @@ -1,12 +1,25 @@ +var Spec02 = require("../../specs/spec_0_2.js"); +var JSONParser = require("../../formats/json/parser.js"); + +const json_mime = "application/json"; +const ce_json_mime = "application/cloudevents+json"; const content_type_header = "content-type"; const ce_structured_content_type = "application/cloudevents"; +const structured = "structured"; +const binary = "binary"; + +const jsonParserSpec02 = new JSONParser(new Spec02()); +const parsers = {}; +parsers[json_mime] = jsonParserSpec02; +parsers[ce_json_mime] = jsonParserSpec02; + const allowed_binary_content_types = []; -allowed_binary_content_types.push("application/json"); +allowed_binary_content_types.push(json_mime); const allowed_structured_content_types = []; -allowed_structured_content_types.push("application/cloudevents+json"); +allowed_structured_content_types.push(ce_json_mime); function validate_args(payload, headers) { if(!payload){ @@ -23,20 +36,20 @@ function validate_args(payload, headers) { } // Is it binary or structured? -function resolve_binding_type(payload, headers) { +function resolve_binding_name(payload, headers) { var contentType = headers[content_type_header]; if(contentType.startsWith(ce_structured_content_type)){ // Structured if(allowed_structured_content_types.includes(contentType)){ - + return structured; } else { throw {message: "structured+type not allowed", errors: [contentType]}; } } else { // Binary if(allowed_binary_content_types.includes(contentType)){ - + return binary; } else { throw {message: "content type not allowed", errors : [contentType]}; } @@ -51,7 +64,17 @@ Unmarshaller.prototype.unmarshall = function(payload, headers) { validate_args(payload, headers); // Resolve the binding - var binding = resolve_binding_type(payload, headers); + var bindingName = resolve_binding_name(payload, headers); + var contentType = headers[content_type_header]; + + if(bindingName === structured){ + var parser = parsers[contentType]; + var cloudevent = parser.parse(payload); + + return cloudevent; + } else {//binary + + } } diff --git a/test/bindings/http/unmarshaller_0_2_tests.js b/test/bindings/http/unmarshaller_0_2_tests.js index 0dddebac..2dc18adc 100644 --- a/test/bindings/http/unmarshaller_0_2_tests.js +++ b/test/bindings/http/unmarshaller_0_2_tests.js @@ -1,5 +1,19 @@ var expect = require("chai").expect; var Unmarshaller = require("../../../lib/bindings/http/unmarshaller_0_2.js"); +var Cloudevent = require("../../../index.js"); + +const type = "com.github.pull.create"; +const source = "urn:event:from:myapi/resourse/123"; +const webhook = "https://cloudevents.io/webhook"; +const contentType = "application/cloudevents+json; charset=utf-8"; +const now = new Date(); +const schemaurl = "http://cloudevents.io/schema.json"; + +const ceContentType = "application/json"; + +const data = { + foo: "bar" +}; describe("HTTP Transport Binding Unmarshaller", () => { @@ -48,16 +62,41 @@ describe("HTTP Transport Binding Unmarshaller", () => { .to.throw("content type not allowed"); }); - it("Throw error when structured binding has not allowed mime", () => { - // setup - var payload = {}; - var headers = { - "content-type":"application/cloudevents+zip" - }; - var un = new Unmarshaller(); + describe("Structured", () => { + it("Throw error when has not allowed mime", () => { + // setup + var payload = {}; + var headers = { + "content-type":"application/cloudevents+zip" + }; + var un = new Unmarshaller(); - // act and assert - expect(un.unmarshall.bind(un, payload, headers)) - .to.throw("structured+type not allowed"); + // act and assert + expect(un.unmarshall.bind(un, payload, headers)) + .to.throw("structured+type not allowed"); + }); + + it("Throw error when the event does not follow the spec 0.2", () => { + // setup + var payload = + new Cloudevent() + .type(type) + .source(source) + .contenttype(ceContentType) + .time(now) + .schemaurl(schemaurl) + .data(data) + .toString(); + + var headers = { + "content-type":"application/cloudevents+json" + }; + + var un = new Unmarshaller(); + + // act and assert + expect(un.unmarshall.bind(un, payload, headers)) + .to.throw("invalid payload"); + }); }); }); From 8916cbdcf6eeaa11ad02522bd6dbc7d72cf471e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 11:22:03 -0300 Subject: [PATCH 027/110] Test the happy path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- test/bindings/http/unmarshaller_0_2_tests.js | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/bindings/http/unmarshaller_0_2_tests.js b/test/bindings/http/unmarshaller_0_2_tests.js index 2dc18adc..f20d9203 100644 --- a/test/bindings/http/unmarshaller_0_2_tests.js +++ b/test/bindings/http/unmarshaller_0_2_tests.js @@ -98,5 +98,31 @@ describe("HTTP Transport Binding Unmarshaller", () => { expect(un.unmarshall.bind(un, payload, headers)) .to.throw("invalid payload"); }); + + it("Should accept event that follow the spec 0.2", () => { + // setup + var payload = + new Cloudevent(Cloudevent.specs["0.2"]) + .type(type) + .source(source) + .contenttype(ceContentType) + .time(now) + .schemaurl(schemaurl) + .data(data) + .toString(); + + var headers = { + "content-type":"application/cloudevents+json" + }; + + var un = new Unmarshaller(); + + // act + var actual = un.unmarshall(payload, headers); + + // assert + expect(actual) + .to.be.an("object"); + }); }); }); From f1e1f942e116b16504a2fae3fed3625679fa9d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 11:35:54 -0300 Subject: [PATCH 028/110] To concentrate the constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/constants.js | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 lib/bindings/http/constants.js diff --git a/lib/bindings/http/constants.js b/lib/bindings/http/constants.js new file mode 100644 index 00000000..7be8dfc5 --- /dev/null +++ b/lib/bindings/http/constants.js @@ -0,0 +1,7 @@ +// Commons +module.exports = { + MIME_JSON : "application/json", + MIME_CE_JSON : "application/cloudevents+json", + + HEADER_CONTENT_TYPE : "content-type" +} From 7839b733d61737627b0f9f906a47a502546708b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 11:36:04 -0300 Subject: [PATCH 029/110] Constant usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/unmarshaller_0_2.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/bindings/http/unmarshaller_0_2.js b/lib/bindings/http/unmarshaller_0_2.js index 31cf543c..49fc02fb 100644 --- a/lib/bindings/http/unmarshaller_0_2.js +++ b/lib/bindings/http/unmarshaller_0_2.js @@ -1,10 +1,8 @@ var Spec02 = require("../../specs/spec_0_2.js"); var JSONParser = require("../../formats/json/parser.js"); -const json_mime = "application/json"; -const ce_json_mime = "application/cloudevents+json"; +const Constants = require("./constants.js"); -const content_type_header = "content-type"; const ce_structured_content_type = "application/cloudevents"; const structured = "structured"; @@ -12,14 +10,14 @@ const binary = "binary"; const jsonParserSpec02 = new JSONParser(new Spec02()); const parsers = {}; -parsers[json_mime] = jsonParserSpec02; -parsers[ce_json_mime] = jsonParserSpec02; +parsers[Constants.MIME_JSON] = jsonParserSpec02; +parsers[Constants.MIME_CE_JSON] = jsonParserSpec02; const allowed_binary_content_types = []; -allowed_binary_content_types.push(json_mime); +allowed_binary_content_types.push(Constants.MIME_JSON); const allowed_structured_content_types = []; -allowed_structured_content_types.push(ce_json_mime); +allowed_structured_content_types.push(Constants.MIME_CE_JSON); function validate_args(payload, headers) { if(!payload){ @@ -30,7 +28,7 @@ function validate_args(payload, headers) { throw {message: "headers is null or undefined"}; } - if(!headers[content_type_header]){ + if(!headers[Constants.HEADER_CONTENT_TYPE]){ throw {message: "content-type header not found"}; } } @@ -38,9 +36,10 @@ function validate_args(payload, headers) { // Is it binary or structured? function resolve_binding_name(payload, headers) { - var contentType = headers[content_type_header]; + var contentType = headers[Constants.HEADER_CONTENT_TYPE]; if(contentType.startsWith(ce_structured_content_type)){ // Structured + console.log(allowed_structured_content_types); if(allowed_structured_content_types.includes(contentType)){ return structured; } else { @@ -65,7 +64,7 @@ Unmarshaller.prototype.unmarshall = function(payload, headers) { // Resolve the binding var bindingName = resolve_binding_name(payload, headers); - var contentType = headers[content_type_header]; + var contentType = headers[Constants.HEADER_CONTENT_TYPE]; if(bindingName === structured){ var parser = parsers[contentType]; From 6de756d1023a4688855a586b90ed65ad12548a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 12:37:49 -0300 Subject: [PATCH 030/110] New contants + usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/constants.js | 3 +++ lib/bindings/http/unmarshaller_0_2.js | 6 ++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/bindings/http/constants.js b/lib/bindings/http/constants.js index 7be8dfc5..fea4a2ac 100644 --- a/lib/bindings/http/constants.js +++ b/lib/bindings/http/constants.js @@ -1,6 +1,9 @@ // Commons module.exports = { + CHARSET_DEFAULT : "utf-8", + MIME_JSON : "application/json", + MIME_CE : "application/cloudevents", MIME_CE_JSON : "application/cloudevents+json", HEADER_CONTENT_TYPE : "content-type" diff --git a/lib/bindings/http/unmarshaller_0_2.js b/lib/bindings/http/unmarshaller_0_2.js index 49fc02fb..10b00fe6 100644 --- a/lib/bindings/http/unmarshaller_0_2.js +++ b/lib/bindings/http/unmarshaller_0_2.js @@ -3,8 +3,6 @@ var JSONParser = require("../../formats/json/parser.js"); const Constants = require("./constants.js"); -const ce_structured_content_type = "application/cloudevents"; - const structured = "structured"; const binary = "binary"; @@ -37,9 +35,9 @@ function validate_args(payload, headers) { function resolve_binding_name(payload, headers) { var contentType = headers[Constants.HEADER_CONTENT_TYPE]; - if(contentType.startsWith(ce_structured_content_type)){ + if(contentType.startsWith(Constants.MIME_CE)){ // Structured - console.log(allowed_structured_content_types); + if(allowed_structured_content_types.includes(contentType)){ return structured; } else { From f4c86d460ecfa7297ed2999346adffeb8eded69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 12:42:04 -0300 Subject: [PATCH 031/110] Constants usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/emitter_binary_0_1.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/bindings/http/emitter_binary_0_1.js b/lib/bindings/http/emitter_binary_0_1.js index 5bac97bd..d5d4001a 100644 --- a/lib/bindings/http/emitter_binary_0_1.js +++ b/lib/bindings/http/emitter_binary_0_1.js @@ -1,11 +1,15 @@ var axios = require("axios"); +const Constants = require("./constants.js"); + function HTTPBinary(configuration){ this.config = configuration; - this.config["headers"] = { - "Content-Type":"application/cloudevents+json; charset=utf-8" - }; + this.config["headers"] = {}; + + this.config["headers"] + [Constants.HEADER_CONTENT_TYPE] = + Constants.MIME_CE_JSON + "; charset=" + Constants.CHARSET_DEFAULT; } HTTPBinary.prototype.emit = function(cloudevent){ @@ -17,7 +21,7 @@ HTTPBinary.prototype.emit = function(cloudevent){ var _headers = _config["headers"]; if(cloudevent.getContenttype()) { - _headers["Content-Type"] = cloudevent.getContenttype(); + _headers[Constants.HEADER_CONTENT_TYPE] = cloudevent.getContenttype(); } _headers["CE-EventType"] = cloudevent.getType(); From cb149c23c1432fb2d768fbea1b5b2ea4b20cf9a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 12:48:45 -0300 Subject: [PATCH 032/110] Check if has headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/emitter_binary_0_1.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/bindings/http/emitter_binary_0_1.js b/lib/bindings/http/emitter_binary_0_1.js index d5d4001a..440b2379 100644 --- a/lib/bindings/http/emitter_binary_0_1.js +++ b/lib/bindings/http/emitter_binary_0_1.js @@ -5,7 +5,9 @@ const Constants = require("./constants.js"); function HTTPBinary(configuration){ this.config = configuration; - this.config["headers"] = {}; + if(!this.config["headers"]){ + this.config["headers"] = {}; + } this.config["headers"] [Constants.HEADER_CONTENT_TYPE] = From 404753f65585878f7a5d319f063717664c94c188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 12:55:18 -0300 Subject: [PATCH 033/110] Constant usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/emitter_binary_0_2.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/bindings/http/emitter_binary_0_2.js b/lib/bindings/http/emitter_binary_0_2.js index 8d249e53..bcf96950 100644 --- a/lib/bindings/http/emitter_binary_0_2.js +++ b/lib/bindings/http/emitter_binary_0_2.js @@ -1,12 +1,18 @@ var axios = require("axios"); var empty = require("is-empty"); +const Constants = require("./constants.js"); + function HTTPBinary(configuration){ this.config = configuration; - this.config["headers"] = { - "Content-Type":"application/cloudevents+json; charset=utf-8" - }; + if(!this.config["headers"]){ + this.config["headers"] = {}; + } + + this.config["headers"] + [Constants.HEADER_CONTENT_TYPE] = + Constants.MIME_CE_JSON + "; charset=" + Constants.CHARSET_DEFAULT; } HTTPBinary.prototype.emit = function(cloudevent){ @@ -17,7 +23,7 @@ HTTPBinary.prototype.emit = function(cloudevent){ // Always set stuff in _config var _headers = _config["headers"]; - _headers["Content-Type"] = cloudevent.getContenttype(); + _headers[Constants.HEADER_CONTENT_TYPE] = cloudevent.getContenttype(); _headers["ce-type"] = cloudevent.getType(); _headers["ce-specversion"] = cloudevent.getSpecversion(); @@ -32,7 +38,7 @@ HTTPBinary.prototype.emit = function(cloudevent){ _config["data"] = cloudevent.format().data; // Have extensions? - var exts = cloudevent.getExtensions(); + var exts = cloudevent.getExtensions(); for(var ext in exts){ if({}.hasOwnProperty.call(exts, ext)){ _headers["ce-" + ext] = exts[ext]; From 1e17cf165fbe9923ade02f041da076ff05647936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 12:56:49 -0300 Subject: [PATCH 034/110] Constants usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/emitter_structured_0_1.js | 13 ++++++++++--- lib/bindings/http/emitter_structured_0_2.js | 12 +++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/bindings/http/emitter_structured_0_1.js b/lib/bindings/http/emitter_structured_0_1.js index 65c65309..39f7a703 100644 --- a/lib/bindings/http/emitter_structured_0_1.js +++ b/lib/bindings/http/emitter_structured_0_1.js @@ -1,11 +1,18 @@ var axios = require("axios"); +const Constants = require("./constants.js"); + function HTTPStructured(configuration){ this.config = configuration; - this.config["headers"] = { - "Content-Type":"application/cloudevents+json; charset=utf-8" - }; + if(!this.config["headers"]){ + this.config["headers"] = {}; + } + + this.config["headers"] + [Constants.HEADER_CONTENT_TYPE] = + Constants.MIME_CE_JSON + "; charset=" + Constants.CHARSET_DEFAULT; + } HTTPStructured.prototype.emit = function(cloudevent){ diff --git a/lib/bindings/http/emitter_structured_0_2.js b/lib/bindings/http/emitter_structured_0_2.js index 65c65309..20315422 100644 --- a/lib/bindings/http/emitter_structured_0_2.js +++ b/lib/bindings/http/emitter_structured_0_2.js @@ -1,11 +1,17 @@ var axios = require("axios"); +const Constants = require("./constants.js"); + function HTTPStructured(configuration){ this.config = configuration; - this.config["headers"] = { - "Content-Type":"application/cloudevents+json; charset=utf-8" - }; + if(!this.config["headers"]){ + this.config["headers"] = {}; + } + + this.config["headers"] + [Constants.HEADER_CONTENT_TYPE] = + Constants.MIME_CE_JSON + "; charset=" + Constants.CHARSET_DEFAULT; } HTTPStructured.prototype.emit = function(cloudevent){ From 043a4a80729d0d9ee1360680a8e8d748e5fde52c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 13:13:44 -0300 Subject: [PATCH 035/110] Http binary binding with constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/emitter_binary_0_2.js | 33 +++++++++++++++++-------- lib/cloudevent.js | 2 +- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/lib/bindings/http/emitter_binary_0_2.js b/lib/bindings/http/emitter_binary_0_2.js index bcf96950..f507628c 100644 --- a/lib/bindings/http/emitter_binary_0_2.js +++ b/lib/bindings/http/emitter_binary_0_2.js @@ -3,7 +3,17 @@ var empty = require("is-empty"); const Constants = require("./constants.js"); -function HTTPBinary(configuration){ +const Headers02 = { + TYPE : "ce-type", + SPEC_VERSION : "ce-specversion", + SOURCE : "ce-source", + ID : "ce-id", + TIME : "ce-time", + SCHEMA_URL : "ce-schemaurl", + EXTENSIONS_PREFIX : "ce-" +}; + +function HTTPBinary02(configuration){ this.config = configuration; if(!this.config["headers"]){ @@ -15,7 +25,7 @@ function HTTPBinary(configuration){ Constants.MIME_CE_JSON + "; charset=" + Constants.CHARSET_DEFAULT; } -HTTPBinary.prototype.emit = function(cloudevent){ +HTTPBinary02.prototype.emit = function(cloudevent){ // Create new request object var _config = JSON.parse(JSON.stringify(this.config)); @@ -25,14 +35,14 @@ HTTPBinary.prototype.emit = function(cloudevent){ _headers[Constants.HEADER_CONTENT_TYPE] = cloudevent.getContenttype(); - _headers["ce-type"] = cloudevent.getType(); - _headers["ce-specversion"] = cloudevent.getSpecversion(); - _headers["ce-source"] = cloudevent.getSource(); - _headers["ce-id"] = cloudevent.getId(); + _headers[Headers02.TYPE] = cloudevent.getType(); + _headers[Headers02.SPEC_VERSION] = cloudevent.getSpecversion(); + _headers[Headers02.SOURCE] = cloudevent.getSource(); + _headers[Headers02.ID] = cloudevent.getId(); if(cloudevent.getTime()) { - _headers["ce-time"] = cloudevent.getTime(); + _headers[Headers02.TIME] = cloudevent.getTime(); } - _headers["ce-schemaurl"] = cloudevent.getSchemaurl(); + _headers[Headers02.SCHEMA_URL] = cloudevent.getSchemaurl(); // Set the cloudevent payload _config["data"] = cloudevent.format().data; @@ -41,7 +51,7 @@ HTTPBinary.prototype.emit = function(cloudevent){ var exts = cloudevent.getExtensions(); for(var ext in exts){ if({}.hasOwnProperty.call(exts, ext)){ - _headers["ce-" + ext] = exts[ext]; + _headers[Headers02.EXTENSIONS_PREFIX + ext] = exts[ext]; } } @@ -49,4 +59,7 @@ HTTPBinary.prototype.emit = function(cloudevent){ return axios.request(_config); }; -module.exports = HTTPBinary; +module.exports = { + HTTPBinary02, + Headers02 +}; diff --git a/lib/cloudevent.js b/lib/cloudevent.js index 40fd0496..d86ca3ae 100644 --- a/lib/cloudevent.js +++ b/lib/cloudevent.js @@ -4,7 +4,7 @@ var JSONFormatter01 = require("./formats/json/formatter.js"); var HTTPStructured01 = require("./bindings/http/emitter_structured_0_1.js"); var HTTPStructured02 = require("./bindings/http/emitter_structured_0_2.js"); var HTTPBinary01 = require("./bindings/http/emitter_binary_0_1.js"); -var HTTPBinary02 = require("./bindings/http/emitter_binary_0_2.js"); +var {HTTPBinary02} = require("./bindings/http/emitter_binary_0_2.js"); /* * Class created using the Builder Design Pattern. From 555bce84a34fd2be51963d3d6af2cbc6b8af16b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 13:25:46 -0300 Subject: [PATCH 036/110] Remove blank lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/emitter_structured_0_1.js | 1 - lib/bindings/http/unmarshaller_0_2.js | 1 - 2 files changed, 2 deletions(-) diff --git a/lib/bindings/http/emitter_structured_0_1.js b/lib/bindings/http/emitter_structured_0_1.js index 39f7a703..20315422 100644 --- a/lib/bindings/http/emitter_structured_0_1.js +++ b/lib/bindings/http/emitter_structured_0_1.js @@ -12,7 +12,6 @@ function HTTPStructured(configuration){ this.config["headers"] [Constants.HEADER_CONTENT_TYPE] = Constants.MIME_CE_JSON + "; charset=" + Constants.CHARSET_DEFAULT; - } HTTPStructured.prototype.emit = function(cloudevent){ diff --git a/lib/bindings/http/unmarshaller_0_2.js b/lib/bindings/http/unmarshaller_0_2.js index 10b00fe6..b1024e13 100644 --- a/lib/bindings/http/unmarshaller_0_2.js +++ b/lib/bindings/http/unmarshaller_0_2.js @@ -37,7 +37,6 @@ function resolve_binding_name(payload, headers) { var contentType = headers[Constants.HEADER_CONTENT_TYPE]; if(contentType.startsWith(Constants.MIME_CE)){ // Structured - if(allowed_structured_content_types.includes(contentType)){ return structured; } else { From 1fed22fa931ab7de48e2eb4f3dc5a44cc658c22b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 14:40:55 -0300 Subject: [PATCH 037/110] Docs for check() method in the Binding API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 2071c1b2..1fdb14f7 100644 --- a/README.md +++ b/README.md @@ -317,6 +317,11 @@ Binding(config) */ Binding.emit(cloudevent) +/* + * Checks if some Object and a Map of attributes + * follows the binding definition. Throw an error if did not follow + */ +Binding.check(Object, Map) ``` #### Receiver Binding From 141cb045166fc9b01a7751a8748c08d2d3613372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 14:41:28 -0300 Subject: [PATCH 038/110] Partial check() method impl for binary 0.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/emitter_binary_0_2.js | 34 +++++++++ test/http_binding_0_2.js | 91 +++++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/lib/bindings/http/emitter_binary_0_2.js b/lib/bindings/http/emitter_binary_0_2.js index f507628c..08f04056 100644 --- a/lib/bindings/http/emitter_binary_0_2.js +++ b/lib/bindings/http/emitter_binary_0_2.js @@ -13,6 +13,26 @@ const Headers02 = { EXTENSIONS_PREFIX : "ce-" }; +const required_attributes = []; +required_attributes.push(Headers02.TYPE); +required_attributes.push(Headers02.SPEC_VERSION); +required_attributes.push(Headers02.SOURCE); +required_attributes.push(Headers02.ID); + +function validate_args(payload, attributes) { + if(!payload){ + throw {message: "payload is null or undefined"}; + } + + if(!attributes) { + throw {message: "attributes is null or undefined"}; + } + + if((typeof payload) !== "object"){ + throw {message: "payload must be an object", erros: [typeof payload]}; + } +} + function HTTPBinary02(configuration){ this.config = configuration; @@ -25,6 +45,20 @@ function HTTPBinary02(configuration){ Constants.MIME_CE_JSON + "; charset=" + Constants.CHARSET_DEFAULT; } +HTTPBinary02.prototype.check = function(payload, attributes) { + // Validation Level 0 + validate_args(payload, attributes); + + // Validation Level 1 + for(i in required_attributes){ + if(!attributes[required_attributes[i]]){ + throw {message: "header '" + required_attributes[i] + "' not found"}; + } + } + + +} + HTTPBinary02.prototype.emit = function(cloudevent){ // Create new request object diff --git a/test/http_binding_0_2.js b/test/http_binding_0_2.js index b5ea70fd..7471bc30 100644 --- a/test/http_binding_0_2.js +++ b/test/http_binding_0_2.js @@ -7,6 +7,8 @@ var http = require("http"); var request = require("request"); var Spec02 = require("../lib/specs/spec_0_2.js"); +var {HTTPBinary02} = require("../lib/bindings/http/emitter_binary_0_2.js"); + const type = "com.github.pull.create"; const source = "urn:event:from:myapi/resourse/123"; const webhook = "https://cloudevents.io/webhook"; @@ -175,6 +177,95 @@ describe("HTTP Transport Binding - Version 0.2", () => { }); describe("Binary", () => { + describe("Check", () => { + it("Throw error when payload arg is null or undefined", () => { + // setup + var payload = null; + var attributes = {}; + + // act and assert + expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) + .to.throw("payload is null or undefined"); + }); + + it("Throw error when attributes arg is null or undefined", () => { + // setup + var payload = {}; + var attributes = null; + + // act and assert + expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) + .to.throw("attributes is null or undefined"); + }); + + it("Throw error when payload is not an object", () => { + // setup + var payload = "wow"; + var attributes = {}; + + // act and assert + expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) + .to.throw("payload must be an object"); + }); + + it("Throw error when headers has no 'ce-type'", () => { + // setup + var payload = {}; + var attributes = { + //"ce-type" : "type", + "ce-specversion" : "specversion", + "ce-source" : "source", + "ce-id" : "id" + }; + + // act and assert + expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) + .to.throw("header 'ce-type' not found"); + }); + + it("Throw error when headers has no 'ce-specversion'", () => { + // setup + var payload = {}; + var attributes = { + "ce-type" : "type", + "ce-source" : "source", + "ce-id" : "id" + }; + + // act and assert + expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) + .to.throw("header 'ce-specversion' not found"); + }); + + it("Throw error when headers has no 'ce-source'", () => { + // setup + var payload = {}; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "specversion", + "ce-id" : "id" + }; + + // act and assert + expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) + .to.throw("header 'ce-source' not found"); + }); + + it("Throw error when headers has no 'ce-id'", () => { + // setup + var payload = {}; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "specversion", + "ce-source" : "source" + }; + + // act and assert + expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) + .to.throw("header 'ce-id' not found"); + }); + }); + describe("JSON Format", () => { it("requires '" + cloudevent.getContenttype() + "' Content-Type in the header", () => { return httpbinary02.emit(cloudevent) From 441613b103e0cc2203e5220928b57c0630a329f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 20:47:06 -0300 Subject: [PATCH 039/110] Document the parse method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1fdb14f7..4418c147 100644 --- a/README.md +++ b/README.md @@ -175,8 +175,7 @@ var config = { }; // The binding instance -var binding = Cloudevent - .bindings["http-structured0.2"](config); +var binding = new Cloudevent.bindings["http-structured0.2"](config); binding.receive() .then(cloudevent => { @@ -318,10 +317,15 @@ Binding(config) Binding.emit(cloudevent) /* - * Checks if some Object and a Map of attributes + * Checks if some Object and a Map of headers * follows the binding definition. Throw an error if did not follow */ Binding.check(Object, Map) + +/* + * Checks and parse the Binary as Cloudevent + */ +Cloudevent Binding.parse(Object, Map) ``` #### Receiver Binding From cc41f0e015d48d58d56a0e11a7cf44d43576d052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 20:56:21 -0300 Subject: [PATCH 040/110] Headers as constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/emitter_binary_0_2.js | 26 +++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/bindings/http/emitter_binary_0_2.js b/lib/bindings/http/emitter_binary_0_2.js index 08f04056..ce6e9769 100644 --- a/lib/bindings/http/emitter_binary_0_2.js +++ b/lib/bindings/http/emitter_binary_0_2.js @@ -13,11 +13,11 @@ const Headers02 = { EXTENSIONS_PREFIX : "ce-" }; -const required_attributes = []; -required_attributes.push(Headers02.TYPE); -required_attributes.push(Headers02.SPEC_VERSION); -required_attributes.push(Headers02.SOURCE); -required_attributes.push(Headers02.ID); +const required_headers = []; +required_headers.push(Headers02.TYPE); +required_headers.push(Headers02.SPEC_VERSION); +required_headers.push(Headers02.SOURCE); +required_headers.push(Headers02.ID); function validate_args(payload, attributes) { if(!payload){ @@ -45,18 +45,24 @@ function HTTPBinary02(configuration){ Constants.MIME_CE_JSON + "; charset=" + Constants.CHARSET_DEFAULT; } -HTTPBinary02.prototype.check = function(payload, attributes) { +HTTPBinary02.prototype.check = function(payload, headers) { // Validation Level 0 - validate_args(payload, attributes); + validate_args(payload, headers); // Validation Level 1 - for(i in required_attributes){ - if(!attributes[required_attributes[i]]){ - throw {message: "header '" + required_attributes[i] + "' not found"}; + for(i in required_headers){ + if(!headers[required_headers[i]]){ + throw {message: "header '" + required_headers[i] + "' not found"}; } } + // No erros! Its contains the minimum required attributes +} + +HTTPBinary02.prototype.parse = function(payload, headers) { + this.check(payload, headers); + } HTTPBinary02.prototype.emit = function(cloudevent){ From 396e0f94b9085b72b2c5eb01d78e01b0da7acaaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 20:56:59 -0300 Subject: [PATCH 041/110] Happy path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- test/http_binding_0_2.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/http_binding_0_2.js b/test/http_binding_0_2.js index 7471bc30..2125117a 100644 --- a/test/http_binding_0_2.js +++ b/test/http_binding_0_2.js @@ -212,7 +212,6 @@ describe("HTTP Transport Binding - Version 0.2", () => { // setup var payload = {}; var attributes = { - //"ce-type" : "type", "ce-specversion" : "specversion", "ce-source" : "source", "ce-id" : "id" @@ -264,6 +263,25 @@ describe("HTTP Transport Binding - Version 0.2", () => { expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) .to.throw("header 'ce-id' not found"); }); + + it("No error when all required headers are in place", () => { + // setup + var payload = {}; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "specversion", + "ce-source" : "source", + "ce-id" : "id" + }; + + // act and assert + expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) + .to.not.throw(); + }); + }); + + describe("Parse", () => { + }); describe("JSON Format", () => { From 30f499cbc1f9b33dbccb2cc419d7e65d4a4ae461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 21:29:09 -0300 Subject: [PATCH 042/110] Document the receiver and receiver server MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4418c147..133a9380 100644 --- a/README.md +++ b/README.md @@ -315,33 +315,42 @@ Binding(config) * Emits the event using an instance of Cloudevent. */ Binding.emit(cloudevent) +``` + +#### Receiver Binding + +Following we have the signature for the binding to receive Cloudevents. + +```js +/* + * The constructor must receives the map of configurations. + */ +Receiver(config) /* * Checks if some Object and a Map of headers - * follows the binding definition. Throw an error if did not follow + * follows the binding definition, throwing an error if did not follow */ -Binding.check(Object, Map) +Receiver.check(Object, Map) /* - * Checks and parse the Binary as Cloudevent + * Checks and parse as Cloudevent */ -Cloudevent Binding.parse(Object, Map) +Cloudevent Receiver.parse(Object, Map) ``` -#### Receiver Binding - -Following we have the signature for the binding to receive Cloudevents. +##### Receiver Binding Server ```js /* * The constructor must receives the map of configurations. */ -ReceiverBinding(config) +Receiver(config) /* * Receives the events and returns a Promise. */ -ReceiverBinding.receive() +Receiver.receive() ``` > See how to implement the method injection [here](lib/specs/spec_0_1.js#L17) From dd5f694dab4f34173ac94d550671ae8252427363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 21:50:19 -0300 Subject: [PATCH 043/110] http binary receiver to parse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/binary_receiver_0_2.js | 56 +++++++++ .../http/binary_receiver_0_2_tests.js | 115 ++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 lib/bindings/http/binary_receiver_0_2.js create mode 100644 test/bindings/http/binary_receiver_0_2_tests.js diff --git a/lib/bindings/http/binary_receiver_0_2.js b/lib/bindings/http/binary_receiver_0_2.js new file mode 100644 index 00000000..4404b248 --- /dev/null +++ b/lib/bindings/http/binary_receiver_0_2.js @@ -0,0 +1,56 @@ +const Constants = require("./constants.js"); + +const required_headers = []; +required_headers.push(Constants.BINARY_HEADERS_02.TYPE); +required_headers.push(Constants.BINARY_HEADERS_02.SPEC_VERSION); +required_headers.push(Constants.BINARY_HEADERS_02.SOURCE); +required_headers.push(Constants.BINARY_HEADERS_02.ID); + +const setter_reflections = {}; +setter_reflections[Constants.BINARY_HEADERS_02.TYPE] = "type"; +setter_reflections[Constants.BINARY_HEADERS_02.SOURCE] = "source"; +setter_reflections[Constants.BINARY_HEADERS_02.ID] = "id"; +setter_reflections[Constants.BINARY_HEADERS_02.TIME] = "time"; +setter_reflections[Constants.BINARY_HEADERS_02.SCHEMA_URL] = "schemaurl"; + +function validate_args(payload, attributes) { + if(!payload){ + throw {message: "payload is null or undefined"}; + } + + if(!attributes) { + throw {message: "attributes is null or undefined"}; + } + + if((typeof payload) !== "object"){ + throw {message: "payload must be an object", erros: [typeof payload]}; + } +} + +function Receiver(configuration) { + +} + +Receiver.prototype.check = function(payload, headers) { + // Validation Level 0 + validate_args(payload, headers); + + // Validation Level 1 + for(i in required_headers){ + if(!headers[required_headers[i]]){ + throw {message: "header '" + required_headers[i] + "' not found"}; + } + } + + // No erros! Its contains the minimum required attributes +} + +Receiver.prototype.parse = function(payload, headers) { + this.check(payload, headers); + + for(setter in setter_reflections) { + + } +} + +module.exports = Receiver; diff --git a/test/bindings/http/binary_receiver_0_2_tests.js b/test/bindings/http/binary_receiver_0_2_tests.js new file mode 100644 index 00000000..0e914966 --- /dev/null +++ b/test/bindings/http/binary_receiver_0_2_tests.js @@ -0,0 +1,115 @@ +var expect = require("chai").expect; + +var HTTPBinaryReceiver02 = + require("../../../lib/bindings/http/binary_receiver_0_2.js"); + +var receiver = new HTTPBinaryReceiver02(); + +describe("HTTP Transport Binding Binary Receiver 0.2", () => { + describe("Check", () => { + it("Throw error when payload arg is null or undefined", () => { + // setup + var payload = null; + var attributes = {}; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("payload is null or undefined"); + }); + + it("Throw error when attributes arg is null or undefined", () => { + // setup + var payload = {}; + var attributes = null; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("attributes is null or undefined"); + }); + + it("Throw error when payload is not an object", () => { + // setup + var payload = "wow"; + var attributes = {}; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("payload must be an object"); + }); + + it("Throw error when headers has no 'ce-type'", () => { + // setup + var payload = {}; + var attributes = { + "ce-specversion" : "specversion", + "ce-source" : "source", + "ce-id" : "id" + }; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("header 'ce-type' not found"); + }); + + it("Throw error when headers has no 'ce-specversion'", () => { + // setup + var payload = {}; + var attributes = { + "ce-type" : "type", + "ce-source" : "source", + "ce-id" : "id" + }; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("header 'ce-specversion' not found"); + }); + + it("Throw error when headers has no 'ce-source'", () => { + // setup + var payload = {}; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "specversion", + "ce-id" : "id" + }; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("header 'ce-source' not found"); + }); + + it("Throw error when headers has no 'ce-id'", () => { + // setup + var payload = {}; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "specversion", + "ce-source" : "source" + }; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("header 'ce-id' not found"); + }); + + it("No error when all required headers are in place", () => { + // setup + var payload = {}; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "specversion", + "ce-source" : "source", + "ce-id" : "id" + }; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.not.throw(); + }); + }); + + describe("Parse", () => { + + }); +}); From 0db21da02a2dd9eb92b56aa6de90393da7284688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 21:51:06 -0300 Subject: [PATCH 044/110] Remove receiver tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- test/http_binding_0_2.js | 107 --------------------------------------- 1 file changed, 107 deletions(-) diff --git a/test/http_binding_0_2.js b/test/http_binding_0_2.js index 2125117a..345d75e2 100644 --- a/test/http_binding_0_2.js +++ b/test/http_binding_0_2.js @@ -177,113 +177,6 @@ describe("HTTP Transport Binding - Version 0.2", () => { }); describe("Binary", () => { - describe("Check", () => { - it("Throw error when payload arg is null or undefined", () => { - // setup - var payload = null; - var attributes = {}; - - // act and assert - expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) - .to.throw("payload is null or undefined"); - }); - - it("Throw error when attributes arg is null or undefined", () => { - // setup - var payload = {}; - var attributes = null; - - // act and assert - expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) - .to.throw("attributes is null or undefined"); - }); - - it("Throw error when payload is not an object", () => { - // setup - var payload = "wow"; - var attributes = {}; - - // act and assert - expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) - .to.throw("payload must be an object"); - }); - - it("Throw error when headers has no 'ce-type'", () => { - // setup - var payload = {}; - var attributes = { - "ce-specversion" : "specversion", - "ce-source" : "source", - "ce-id" : "id" - }; - - // act and assert - expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) - .to.throw("header 'ce-type' not found"); - }); - - it("Throw error when headers has no 'ce-specversion'", () => { - // setup - var payload = {}; - var attributes = { - "ce-type" : "type", - "ce-source" : "source", - "ce-id" : "id" - }; - - // act and assert - expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) - .to.throw("header 'ce-specversion' not found"); - }); - - it("Throw error when headers has no 'ce-source'", () => { - // setup - var payload = {}; - var attributes = { - "ce-type" : "type", - "ce-specversion" : "specversion", - "ce-id" : "id" - }; - - // act and assert - expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) - .to.throw("header 'ce-source' not found"); - }); - - it("Throw error when headers has no 'ce-id'", () => { - // setup - var payload = {}; - var attributes = { - "ce-type" : "type", - "ce-specversion" : "specversion", - "ce-source" : "source" - }; - - // act and assert - expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) - .to.throw("header 'ce-id' not found"); - }); - - it("No error when all required headers are in place", () => { - // setup - var payload = {}; - var attributes = { - "ce-type" : "type", - "ce-specversion" : "specversion", - "ce-source" : "source", - "ce-id" : "id" - }; - - // act and assert - expect(httpbinary02.check.bind(httpbinary02, payload, attributes)) - .to.not.throw(); - }); - }); - - describe("Parse", () => { - - }); - describe("JSON Format", () => { it("requires '" + cloudevent.getContenttype() + "' Content-Type in the header", () => { return httpbinary02.emit(cloudevent) From e17f9aafbd545abc44e74565c0e8ab463cb8615d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 21:51:22 -0300 Subject: [PATCH 045/110] HTTP Binary headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/constants.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/bindings/http/constants.js b/lib/bindings/http/constants.js index fea4a2ac..8b1898fb 100644 --- a/lib/bindings/http/constants.js +++ b/lib/bindings/http/constants.js @@ -6,5 +6,15 @@ module.exports = { MIME_CE : "application/cloudevents", MIME_CE_JSON : "application/cloudevents+json", - HEADER_CONTENT_TYPE : "content-type" + HEADER_CONTENT_TYPE : "content-type", + + BINARY_HEADERS_02 : { + TYPE : "ce-type", + SPEC_VERSION : "ce-specversion", + SOURCE : "ce-source", + ID : "ce-id", + TIME : "ce-time", + SCHEMA_URL : "ce-schemaurl", + EXTENSIONS_PREFIX : "ce-" + } } From 7f69f8b8fa9b26e16b96e36363d9ca73a3ff5b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 21:52:03 -0300 Subject: [PATCH 046/110] Remore reciver stuff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/emitter_binary_0_2.js | 77 +++++++------------------ 1 file changed, 20 insertions(+), 57 deletions(-) diff --git a/lib/bindings/http/emitter_binary_0_2.js b/lib/bindings/http/emitter_binary_0_2.js index ce6e9769..d5fdfe39 100644 --- a/lib/bindings/http/emitter_binary_0_2.js +++ b/lib/bindings/http/emitter_binary_0_2.js @@ -3,35 +3,18 @@ var empty = require("is-empty"); const Constants = require("./constants.js"); -const Headers02 = { - TYPE : "ce-type", - SPEC_VERSION : "ce-specversion", - SOURCE : "ce-source", - ID : "ce-id", - TIME : "ce-time", - SCHEMA_URL : "ce-schemaurl", - EXTENSIONS_PREFIX : "ce-" -}; - const required_headers = []; -required_headers.push(Headers02.TYPE); -required_headers.push(Headers02.SPEC_VERSION); -required_headers.push(Headers02.SOURCE); -required_headers.push(Headers02.ID); - -function validate_args(payload, attributes) { - if(!payload){ - throw {message: "payload is null or undefined"}; - } - - if(!attributes) { - throw {message: "attributes is null or undefined"}; - } - - if((typeof payload) !== "object"){ - throw {message: "payload must be an object", erros: [typeof payload]}; - } -} +required_headers.push(Constants.BINARY_HEADERS_02.TYPE); +required_headers.push(Constants.BINARY_HEADERS_02.SPEC_VERSION); +required_headers.push(Constants.BINARY_HEADERS_02.SOURCE); +required_headers.push(Constants.BINARY_HEADERS_02.ID); + +const setter_reflections = {}; +setter_reflections[Constants.BINARY_HEADERS_02.TYPE] = "type"; +setter_reflections[Constants.BINARY_HEADERS_02.SOURCE] = "source"; +setter_reflections[Constants.BINARY_HEADERS_02.ID] = "id"; +setter_reflections[Constants.BINARY_HEADERS_02.TIME] = "time"; +setter_reflections[Constants.BINARY_HEADERS_02.SCHEMA_URL] = "schemaurl"; function HTTPBinary02(configuration){ this.config = configuration; @@ -45,26 +28,6 @@ function HTTPBinary02(configuration){ Constants.MIME_CE_JSON + "; charset=" + Constants.CHARSET_DEFAULT; } -HTTPBinary02.prototype.check = function(payload, headers) { - // Validation Level 0 - validate_args(payload, headers); - - // Validation Level 1 - for(i in required_headers){ - if(!headers[required_headers[i]]){ - throw {message: "header '" + required_headers[i] + "' not found"}; - } - } - - // No erros! Its contains the minimum required attributes -} - -HTTPBinary02.prototype.parse = function(payload, headers) { - this.check(payload, headers); - - -} - HTTPBinary02.prototype.emit = function(cloudevent){ // Create new request object @@ -75,14 +38,15 @@ HTTPBinary02.prototype.emit = function(cloudevent){ _headers[Constants.HEADER_CONTENT_TYPE] = cloudevent.getContenttype(); - _headers[Headers02.TYPE] = cloudevent.getType(); - _headers[Headers02.SPEC_VERSION] = cloudevent.getSpecversion(); - _headers[Headers02.SOURCE] = cloudevent.getSource(); - _headers[Headers02.ID] = cloudevent.getId(); + _headers[Constants.BINARY_HEADERS_02.TYPE] = cloudevent.getType(); + _headers[Constants.BINARY_HEADERS_02.SPEC_VERSION] = + cloudevent.getSpecversion(); + _headers[Constants.BINARY_HEADERS_02.SOURCE] = cloudevent.getSource(); + _headers[Constants.BINARY_HEADERS_02.ID] = cloudevent.getId(); if(cloudevent.getTime()) { - _headers[Headers02.TIME] = cloudevent.getTime(); + _headers[Constants.BINARY_HEADERS_02.TIME] = cloudevent.getTime(); } - _headers[Headers02.SCHEMA_URL] = cloudevent.getSchemaurl(); + _headers[Constants.BINARY_HEADERS_02.SCHEMA_URL] = cloudevent.getSchemaurl(); // Set the cloudevent payload _config["data"] = cloudevent.format().data; @@ -91,7 +55,7 @@ HTTPBinary02.prototype.emit = function(cloudevent){ var exts = cloudevent.getExtensions(); for(var ext in exts){ if({}.hasOwnProperty.call(exts, ext)){ - _headers[Headers02.EXTENSIONS_PREFIX + ext] = exts[ext]; + _headers[Constants.BINARY_HEADERS_02.EXTENSIONS_PREFIX + ext] = exts[ext]; } } @@ -100,6 +64,5 @@ HTTPBinary02.prototype.emit = function(cloudevent){ }; module.exports = { - HTTPBinary02, - Headers02 + HTTPBinary02 }; From 9abcd8dc6a43d7ed11e88d6a270231b911659906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 22:00:46 -0300 Subject: [PATCH 047/110] Document the API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 133a9380..f69ca715 100644 --- a/README.md +++ b/README.md @@ -260,7 +260,7 @@ String Formatter.toString(Object) ### `Parser` classes -Every formatter class must implement these methods to work properly. +Every Parser class must implement these methods to work properly. ```js /* @@ -341,6 +341,8 @@ Cloudevent Receiver.parse(Object, Map) ##### Receiver Binding Server +Use this API to start a HTTP server and listen to events. + ```js /* * The constructor must receives the map of configurations. @@ -348,9 +350,14 @@ Cloudevent Receiver.parse(Object, Map) Receiver(config) /* - * Receives the events and returns a Promise. + * Listen to events and returns a Promise. + */ +Promise Receiver.listen() + +/* + * Stops the listen to events */ -Receiver.receive() +Receiver.stop() ``` > See how to implement the method injection [here](lib/specs/spec_0_1.js#L17) From 7f7aa89154b84fe14f13914db1174cb927d09008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 22:17:35 -0300 Subject: [PATCH 048/110] Run coverage for master and develop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- .travis.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 400ce03a..02ed4a78 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ jobs: skip_cleanup: true on: tags: true + - stage: npm release node_js: '6' deploy: @@ -25,7 +26,17 @@ jobs: skip_cleanup: true on: tags: true + + - stage: coverage + node_js: '6' + deploy: + provider: script + script: npm run coverage + on: + branch: master + on: + branch: develop env: global: secure: t0A5/Fk1Qj8WkAk0ZuQqpFjrpINV6gfL+d1fXgq03EOAG/7FEyyz+AKkYaLT6avp26VWBzLgEoWC3RNmWD0v1/Ruckb95YpQcb5e4JotAce1ZsHgGTgx0UO146tkyGvXBw6MmO2nX2O/sHzkmyR6rlKkBi9LEKokJ9OFd6fi9nNtksgUDxkqNlNTu100fIQAV2RcN47C6iUx+gJIa+H/8QX/Cz02MyheXLe8a763wMQapz5GHrk2KuVY6FpylcAlSi2so+PjEGfKq3MWaQnTPkevkRDLtGcecVtFAq/0VbvoKc97PHoVT0x+nf48k1gj2VnQtYj6EVB74yRvqM9KkNOsfAQ0z9zF5wXMRs11SZywSViLQsnD9Ue6eYbYmodOKn4DFlLtoRyLBUspzLuoL76lERGe2cHU+Ebz2Nb9jL88o+SjfGrSJQEJU7SLZLbzJ7T/3SspWcAlo+Fo9UTCOB4/yL22Yge/SWQkdd1orBhohpjpyrU9Z1+IRvVoU1EICr04zSFUwEwn6Yxbt0ArgTZBEf11bf+YpCo+rBXNAd+XbZ79PGOEppFb+Hxrt9i1S1RnesDJnwC0k7cswU55Rv5gcNCo9lC+N4ZwS5y+5r6DsBfB+12YdsFORFyNbClECro1ODv4STf3rBBnjL8+ziPFjP4d4OwiGY+vG8bvLXY= -script: npm run coverage +#script: npm run coverage From 05cbaa4a86e0d44c82f541ec0907052ecd100a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 11 Jun 2019 22:24:07 -0300 Subject: [PATCH 049/110] Closes #19 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 02ed4a78..15813194 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,4 +39,3 @@ jobs: env: global: secure: t0A5/Fk1Qj8WkAk0ZuQqpFjrpINV6gfL+d1fXgq03EOAG/7FEyyz+AKkYaLT6avp26VWBzLgEoWC3RNmWD0v1/Ruckb95YpQcb5e4JotAce1ZsHgGTgx0UO146tkyGvXBw6MmO2nX2O/sHzkmyR6rlKkBi9LEKokJ9OFd6fi9nNtksgUDxkqNlNTu100fIQAV2RcN47C6iUx+gJIa+H/8QX/Cz02MyheXLe8a763wMQapz5GHrk2KuVY6FpylcAlSi2so+PjEGfKq3MWaQnTPkevkRDLtGcecVtFAq/0VbvoKc97PHoVT0x+nf48k1gj2VnQtYj6EVB74yRvqM9KkNOsfAQ0z9zF5wXMRs11SZywSViLQsnD9Ue6eYbYmodOKn4DFlLtoRyLBUspzLuoL76lERGe2cHU+Ebz2Nb9jL88o+SjfGrSJQEJU7SLZLbzJ7T/3SspWcAlo+Fo9UTCOB4/yL22Yge/SWQkdd1orBhohpjpyrU9Z1+IRvVoU1EICr04zSFUwEwn6Yxbt0ArgTZBEf11bf+YpCo+rBXNAd+XbZ79PGOEppFb+Hxrt9i1S1RnesDJnwC0k7cswU55Rv5gcNCo9lC+N4ZwS5y+5r6DsBfB+12YdsFORFyNbClECro1ODv4STf3rBBnjL8+ziPFjP4d4OwiGY+vG8bvLXY= -#script: npm run coverage From 9ab8d55549747095295806eea51994fd3ed5d44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 10:49:41 -0300 Subject: [PATCH 050/110] Fix version and what we can do MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f69ca715..c4171a9c 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Official CloudEvents' SDK for JavaScript. ### Before Spec reaches 1.0 -- `0.x.p`: where `x` relates to spec version and `p` relates to fixes. +- `0.x.p`: where `x` relates to spec version and `p` relates to fixes and releases. ### After Spec reaches 1.0 From 67767da97326d38513ebd450e287d6d5c69b36f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 10:56:53 -0300 Subject: [PATCH 051/110] Fix files names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- .../http/{binary_receiver_0_2.js => receiver_binary_0_2.js} | 0 ...inary_receiver_0_2_tests.js => receiver_binary_0_2_tests.js} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename lib/bindings/http/{binary_receiver_0_2.js => receiver_binary_0_2.js} (100%) rename test/bindings/http/{binary_receiver_0_2_tests.js => receiver_binary_0_2_tests.js} (97%) diff --git a/lib/bindings/http/binary_receiver_0_2.js b/lib/bindings/http/receiver_binary_0_2.js similarity index 100% rename from lib/bindings/http/binary_receiver_0_2.js rename to lib/bindings/http/receiver_binary_0_2.js diff --git a/test/bindings/http/binary_receiver_0_2_tests.js b/test/bindings/http/receiver_binary_0_2_tests.js similarity index 97% rename from test/bindings/http/binary_receiver_0_2_tests.js rename to test/bindings/http/receiver_binary_0_2_tests.js index 0e914966..80f1961c 100644 --- a/test/bindings/http/binary_receiver_0_2_tests.js +++ b/test/bindings/http/receiver_binary_0_2_tests.js @@ -1,7 +1,7 @@ var expect = require("chai").expect; var HTTPBinaryReceiver02 = - require("../../../lib/bindings/http/binary_receiver_0_2.js"); + require("../../../lib/bindings/http/receiver_binary_0_2.js"); var receiver = new HTTPBinaryReceiver02(); From 96d467b1e08ae8030244dc428adf8c0bbc3c97d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 10:57:15 -0300 Subject: [PATCH 052/110] Use the contants.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/emitter_binary_0_2.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/lib/bindings/http/emitter_binary_0_2.js b/lib/bindings/http/emitter_binary_0_2.js index d5fdfe39..8e329405 100644 --- a/lib/bindings/http/emitter_binary_0_2.js +++ b/lib/bindings/http/emitter_binary_0_2.js @@ -3,19 +3,6 @@ var empty = require("is-empty"); const Constants = require("./constants.js"); -const required_headers = []; -required_headers.push(Constants.BINARY_HEADERS_02.TYPE); -required_headers.push(Constants.BINARY_HEADERS_02.SPEC_VERSION); -required_headers.push(Constants.BINARY_HEADERS_02.SOURCE); -required_headers.push(Constants.BINARY_HEADERS_02.ID); - -const setter_reflections = {}; -setter_reflections[Constants.BINARY_HEADERS_02.TYPE] = "type"; -setter_reflections[Constants.BINARY_HEADERS_02.SOURCE] = "source"; -setter_reflections[Constants.BINARY_HEADERS_02.ID] = "id"; -setter_reflections[Constants.BINARY_HEADERS_02.TIME] = "time"; -setter_reflections[Constants.BINARY_HEADERS_02.SCHEMA_URL] = "schemaurl"; - function HTTPBinary02(configuration){ this.config = configuration; From 37f60ceb78ecdfcca28a772ffb30ca4d4585fd6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 12:50:40 -0300 Subject: [PATCH 053/110] Parser for each attribute type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_binary_0_2.js | 52 ++++++++++++++--- .../http/receiver_binary_0_2_tests.js | 56 ++++++++++++++++++- 2 files changed, 99 insertions(+), 9 deletions(-) diff --git a/lib/bindings/http/receiver_binary_0_2.js b/lib/bindings/http/receiver_binary_0_2.js index 4404b248..0d0c2694 100644 --- a/lib/bindings/http/receiver_binary_0_2.js +++ b/lib/bindings/http/receiver_binary_0_2.js @@ -1,4 +1,6 @@ -const Constants = require("./constants.js"); +const Constants = require("./constants.js"); +const Cloudevent = require("../../cloudevent.js"); +const Spec02 = require("../../specs/spec_0_2.js"); const required_headers = []; required_headers.push(Constants.BINARY_HEADERS_02.TYPE); @@ -7,11 +9,26 @@ required_headers.push(Constants.BINARY_HEADERS_02.SOURCE); required_headers.push(Constants.BINARY_HEADERS_02.ID); const setter_reflections = {}; -setter_reflections[Constants.BINARY_HEADERS_02.TYPE] = "type"; -setter_reflections[Constants.BINARY_HEADERS_02.SOURCE] = "source"; -setter_reflections[Constants.BINARY_HEADERS_02.ID] = "id"; -setter_reflections[Constants.BINARY_HEADERS_02.TIME] = "time"; -setter_reflections[Constants.BINARY_HEADERS_02.SCHEMA_URL] = "schemaurl"; +setter_reflections[Constants.BINARY_HEADERS_02.TYPE] = { + name : "type", + parser : (v) => v +}; +setter_reflections[Constants.BINARY_HEADERS_02.SOURCE] = { + name : "source", + parser: (v) => v +}; +setter_reflections[Constants.BINARY_HEADERS_02.ID] = { + name : "id", + parser : (v) => v +}; +setter_reflections[Constants.BINARY_HEADERS_02.TIME] = { + name : "time", + parser : (v) => new Date(Date.parse(v)) +}; +setter_reflections[Constants.BINARY_HEADERS_02.SCHEMA_URL] = { + name: "schemaurl", + parser: (v) => v +}; function validate_args(payload, attributes) { if(!payload){ @@ -42,15 +59,34 @@ Receiver.prototype.check = function(payload, headers) { } } + if(headers[Constants.BINARY_HEADERS_02.SPEC_VERSION] !== "0.2"){ + throw {message: "invalid spec version", + errors: [headers[Constants.BINARY_HEADERS_02.SPEC_VERSION]]}; + } + // No erros! Its contains the minimum required attributes } Receiver.prototype.parse = function(payload, headers) { this.check(payload, headers); - for(setter in setter_reflections) { - + var cloudevent = new Cloudevent(Spec02); + for(header in setter_reflections) { + // dont worry, check() have seen what was required or not + if(headers[header]){ + var setter_name = setter_reflections[header].name; + var parser_fn = setter_reflections[header].parser; + console.log(typeof parser_fn(headers[header])); + // invoke the setter function + cloudevent[setter_name](parser_fn(headers[header])); + } } + + // Checks the event spec + cloudevent.format(); + + // return the result + return cloudevent; } module.exports = Receiver; diff --git a/test/bindings/http/receiver_binary_0_2_tests.js b/test/bindings/http/receiver_binary_0_2_tests.js index 80f1961c..123ebcf7 100644 --- a/test/bindings/http/receiver_binary_0_2_tests.js +++ b/test/bindings/http/receiver_binary_0_2_tests.js @@ -93,7 +93,7 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { .to.throw("header 'ce-id' not found"); }); - it("No error when all required headers are in place", () => { + it("Throw error when spec is not 0.2", () => { // setup var payload = {}; var attributes = { @@ -103,6 +103,21 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { "ce-id" : "id" }; + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("invalid spec version"); + }); + + it("No error when all required headers are in place", () => { + // setup + var payload = {}; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "source", + "ce-id" : "id" + }; + // act and assert expect(receiver.check.bind(receiver, payload, attributes)) .to.not.throw(); @@ -110,6 +125,45 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { }); describe("Parse", () => { + it("Cloudevent contains 'type'", () => { + // setup + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "source", + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00Z", + "ce-schemaurl" : "http://schema.registry/v1" + }; + // act + var actual = receiver.parse(payload, attributes); + + // assert + }); + + it("No error when all attributes are in place", () => { + // setup + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "source", + "ce-id" : "id" + }; + + // act + var actual = receiver.parse(payload, attributes); + + // assert + expect(actual) + .to.be.an("object"); + + }); }); }); From 3ea7d4f45f1a6a94c2cb91afe27aa5d19f255777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 17:28:45 -0300 Subject: [PATCH 054/110] Document the what we can do MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c4171a9c..a931bd39 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,8 @@ These are the supported specifications by this version. | Emit Structured events over HTTP | yes | yes | | Emit Binary events over HTTP | yes | yes | | JSON Event Format | yes | yes | -| Receice Structure events over HTTP | yes | yes | -| Receice Binary events over HTTP | yes | yes | +| Receice Structure events over HTTP | no | yes | +| Receice Binary events over HTTP | no | yes | ## How to use From 14e0583347cff3595fac31e51af1665bc6b65969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 17:30:13 -0300 Subject: [PATCH 055/110] Parse date, set data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_binary_0_2.js | 5 +- .../http/receiver_binary_0_2_tests.js | 138 +++++++++++++++++- 2 files changed, 141 insertions(+), 2 deletions(-) diff --git a/lib/bindings/http/receiver_binary_0_2.js b/lib/bindings/http/receiver_binary_0_2.js index 0d0c2694..023392f1 100644 --- a/lib/bindings/http/receiver_binary_0_2.js +++ b/lib/bindings/http/receiver_binary_0_2.js @@ -76,12 +76,15 @@ Receiver.prototype.parse = function(payload, headers) { if(headers[header]){ var setter_name = setter_reflections[header].name; var parser_fn = setter_reflections[header].parser; - console.log(typeof parser_fn(headers[header])); + // invoke the setter function cloudevent[setter_name](parser_fn(headers[header])); } } + // Sets the data + cloudevent.data(payload); + // Checks the event spec cloudevent.format(); diff --git a/test/bindings/http/receiver_binary_0_2_tests.js b/test/bindings/http/receiver_binary_0_2_tests.js index 123ebcf7..5a6364b8 100644 --- a/test/bindings/http/receiver_binary_0_2_tests.js +++ b/test/bindings/http/receiver_binary_0_2_tests.js @@ -143,6 +143,140 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { var actual = receiver.parse(payload, attributes); // assert + expect(actual.getType()) + .to.equal("type"); + }); + + it("Cloudevent contains 'specversion'", () => { + // setup + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "source", + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00Z", + "ce-schemaurl" : "http://schema.registry/v1" + }; + + // act + var actual = receiver.parse(payload, attributes); + + // assert + expect(actual.getSpecversion()) + .to.equal("0.2"); + }); + + it("Cloudevent contains 'source'", () => { + // setup + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "/source", + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00Z", + "ce-schemaurl" : "http://schema.registry/v1" + }; + + // act + var actual = receiver.parse(payload, attributes); + + // assert + expect(actual.getSource()) + .to.equal("/source"); + }); + + it("Cloudevent contains 'id'", () => { + // setup + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "/source", + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00Z", + "ce-schemaurl" : "http://schema.registry/v1" + }; + + // act + var actual = receiver.parse(payload, attributes); + + // assert + expect(actual.getId()) + .to.equal("id"); + }); + + it("Cloudevent contains 'time'", () => { + // setup + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "/source", + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00.000Z", + "ce-schemaurl" : "http://schema.registry/v1" + }; + + // act + var actual = receiver.parse(payload, attributes); + + // assert + expect(actual.getTime()) + .to.equal("2019-06-16T11:42:00.000Z"); + }); + + it("Cloudevent contains 'schemaurl'", () => { + // setup + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "/source", + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00Z", + "ce-schemaurl" : "http://schema.registry/v1" + }; + + // act + var actual = receiver.parse(payload, attributes); + + // assert + expect(actual.getSchemaurl()) + .to.equal("http://schema.registry/v1"); + }); + + it("Cloudevent contains 'data'", () => { + // setup + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "/source", + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00Z", + "ce-schemaurl" : "http://schema.registry/v1" + }; + + // act + var actual = receiver.parse(payload, attributes); + + // assert + expect(actual.getData()) + .to.deep.equal(payload); }); it("No error when all attributes are in place", () => { @@ -154,7 +288,9 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { "ce-type" : "type", "ce-specversion" : "0.2", "ce-source" : "source", - "ce-id" : "id" + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00Z", + "ce-schemaurl" : "http://schema.registry/v1" }; // act From 21011b5a74605f58c8d9321d3d5c0a2b27e0815e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 17:50:26 -0300 Subject: [PATCH 056/110] Content type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_binary_0_2.js | 31 ++++++++-- .../http/receiver_binary_0_2_tests.js | 58 ++++++++++++++----- 2 files changed, 71 insertions(+), 18 deletions(-) diff --git a/lib/bindings/http/receiver_binary_0_2.js b/lib/bindings/http/receiver_binary_0_2.js index 023392f1..989e435d 100644 --- a/lib/bindings/http/receiver_binary_0_2.js +++ b/lib/bindings/http/receiver_binary_0_2.js @@ -2,6 +2,9 @@ const Constants = require("./constants.js"); const Cloudevent = require("../../cloudevent.js"); const Spec02 = require("../../specs/spec_0_2.js"); +const allowed_content_types = []; +allowed_content_types.push(Constants.MIME_JSON); + const required_headers = []; required_headers.push(Constants.BINARY_HEADERS_02.TYPE); required_headers.push(Constants.BINARY_HEADERS_02.SPEC_VERSION); @@ -44,6 +47,16 @@ function validate_args(payload, attributes) { } } +function sanity(headers) { + var sanity_headers = JSON.parse(JSON.stringify(headers)); + + for(header in sanity_headers){ + sanity_headers[header.toLowerCase()] = sanity_headers[header]; + } + + return sanity_headers; +} + function Receiver(configuration) { } @@ -52,16 +65,26 @@ Receiver.prototype.check = function(payload, headers) { // Validation Level 0 validate_args(payload, headers); + // Clone and low case all headers names + var sanity_headers = sanity(headers); + // Validation Level 1 + if(!allowed_content_types + .includes(sanity_headers[Constants.HEADER_CONTENT_TYPE])){ + throw {message: "invalid content type", + errors: [sanity_headers[Constants.HEADER_CONTENT_TYPE]]}; + } + for(i in required_headers){ - if(!headers[required_headers[i]]){ + if(!sanity_headers[required_headers[i]]){ throw {message: "header '" + required_headers[i] + "' not found"}; } } - if(headers[Constants.BINARY_HEADERS_02.SPEC_VERSION] !== "0.2"){ + if(sanity_headers[Constants.BINARY_HEADERS_02.SPEC_VERSION] !== "0.2"){ throw {message: "invalid spec version", - errors: [headers[Constants.BINARY_HEADERS_02.SPEC_VERSION]]}; + errors: + [sanity_headers[Constants.BINARY_HEADERS_02.SPEC_VERSION]]}; } // No erros! Its contains the minimum required attributes @@ -82,7 +105,7 @@ Receiver.prototype.parse = function(payload, headers) { } } - // Sets the data + // Sets the data cloudevent.data(payload); // Checks the event spec diff --git a/test/bindings/http/receiver_binary_0_2_tests.js b/test/bindings/http/receiver_binary_0_2_tests.js index 5a6364b8..48b62171 100644 --- a/test/bindings/http/receiver_binary_0_2_tests.js +++ b/test/bindings/http/receiver_binary_0_2_tests.js @@ -43,7 +43,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { var attributes = { "ce-specversion" : "specversion", "ce-source" : "source", - "ce-id" : "id" + "ce-id" : "id", + "Content-Type" : "application/json" }; // act and assert @@ -57,7 +58,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { var attributes = { "ce-type" : "type", "ce-source" : "source", - "ce-id" : "id" + "ce-id" : "id", + "Content-Type" : "application/json" }; // act and assert @@ -71,7 +73,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { var attributes = { "ce-type" : "type", "ce-specversion" : "specversion", - "ce-id" : "id" + "ce-id" : "id", + "Content-Type" : "application/json" }; // act and assert @@ -85,7 +88,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { var attributes = { "ce-type" : "type", "ce-specversion" : "specversion", - "ce-source" : "source" + "ce-source" : "source", + "Content-Type" : "application/json" }; // act and assert @@ -100,7 +104,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { "ce-type" : "type", "ce-specversion" : "specversion", "ce-source" : "source", - "ce-id" : "id" + "ce-id" : "id", + "Content-Type" : "application/json" }; // act and assert @@ -108,6 +113,22 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { .to.throw("invalid spec version"); }); + it("Throw error when the content-type is invalid", () => { + // setup + var payload = {}; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "specversion", + "ce-source" : "source", + "ce-id" : "id", + "Content-Type" : "text/html" + }; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("invalid content type"); + }); + it("No error when all required headers are in place", () => { // setup var payload = {}; @@ -115,7 +136,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { "ce-type" : "type", "ce-specversion" : "0.2", "ce-source" : "source", - "ce-id" : "id" + "ce-id" : "id", + "Content-Type" : "application/json" }; // act and assert @@ -136,7 +158,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { "ce-source" : "source", "ce-id" : "id", "ce-time" : "2019-06-16T11:42:00Z", - "ce-schemaurl" : "http://schema.registry/v1" + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "application/json" }; // act @@ -158,7 +181,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { "ce-source" : "source", "ce-id" : "id", "ce-time" : "2019-06-16T11:42:00Z", - "ce-schemaurl" : "http://schema.registry/v1" + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "application/json" }; // act @@ -180,7 +204,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { "ce-source" : "/source", "ce-id" : "id", "ce-time" : "2019-06-16T11:42:00Z", - "ce-schemaurl" : "http://schema.registry/v1" + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "application/json" }; // act @@ -202,7 +227,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { "ce-source" : "/source", "ce-id" : "id", "ce-time" : "2019-06-16T11:42:00Z", - "ce-schemaurl" : "http://schema.registry/v1" + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "application/json" }; // act @@ -224,7 +250,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { "ce-source" : "/source", "ce-id" : "id", "ce-time" : "2019-06-16T11:42:00.000Z", - "ce-schemaurl" : "http://schema.registry/v1" + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "application/json" }; // act @@ -246,7 +273,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { "ce-source" : "/source", "ce-id" : "id", "ce-time" : "2019-06-16T11:42:00Z", - "ce-schemaurl" : "http://schema.registry/v1" + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "application/json" }; // act @@ -268,7 +296,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { "ce-source" : "/source", "ce-id" : "id", "ce-time" : "2019-06-16T11:42:00Z", - "ce-schemaurl" : "http://schema.registry/v1" + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "application/json" }; // act @@ -290,7 +319,8 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { "ce-source" : "source", "ce-id" : "id", "ce-time" : "2019-06-16T11:42:00Z", - "ce-schemaurl" : "http://schema.registry/v1" + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "application/json" }; // act From d1fc0b39f02a1fa1edc51d64752087d206c69bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 17:59:58 -0300 Subject: [PATCH 057/110] Parse content type, sanity in parse method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_binary_0_2.js | 11 +++++++-- .../http/receiver_binary_0_2_tests.js | 23 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/bindings/http/receiver_binary_0_2.js b/lib/bindings/http/receiver_binary_0_2.js index 989e435d..3c607e8f 100644 --- a/lib/bindings/http/receiver_binary_0_2.js +++ b/lib/bindings/http/receiver_binary_0_2.js @@ -32,6 +32,10 @@ setter_reflections[Constants.BINARY_HEADERS_02.SCHEMA_URL] = { name: "schemaurl", parser: (v) => v }; +setter_reflections[Constants.HEADER_CONTENT_TYPE] = { + name: "contenttype", + parser: (v) => v +}; function validate_args(payload, attributes) { if(!payload){ @@ -93,15 +97,18 @@ Receiver.prototype.check = function(payload, headers) { Receiver.prototype.parse = function(payload, headers) { this.check(payload, headers); + // Clone and low case all headers names + var sanity_headers = sanity(headers); + var cloudevent = new Cloudevent(Spec02); for(header in setter_reflections) { // dont worry, check() have seen what was required or not - if(headers[header]){ + if(sanity_headers[header]){ var setter_name = setter_reflections[header].name; var parser_fn = setter_reflections[header].parser; // invoke the setter function - cloudevent[setter_name](parser_fn(headers[header])); + cloudevent[setter_name](parser_fn(sanity_headers[header])); } } diff --git a/test/bindings/http/receiver_binary_0_2_tests.js b/test/bindings/http/receiver_binary_0_2_tests.js index 48b62171..213fff51 100644 --- a/test/bindings/http/receiver_binary_0_2_tests.js +++ b/test/bindings/http/receiver_binary_0_2_tests.js @@ -285,6 +285,29 @@ describe("HTTP Transport Binding Binary Receiver 0.2", () => { .to.equal("http://schema.registry/v1"); }); + it("Cloudevent contains 'contenttype'", () => { + // setup + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "/source", + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00Z", + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "application/json" + }; + + // act + var actual = receiver.parse(payload, attributes); + + // assert + expect(actual.getContenttype()) + .to.equal("application/json"); + }); + it("Cloudevent contains 'data'", () => { // setup var payload = { From c37b31fc3b6c593c629159b81af57f46150c643b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 18:44:38 -0300 Subject: [PATCH 058/110] Commons functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/commons.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 lib/bindings/http/commons.js diff --git a/lib/bindings/http/commons.js b/lib/bindings/http/commons.js new file mode 100644 index 00000000..5b7dd605 --- /dev/null +++ b/lib/bindings/http/commons.js @@ -0,0 +1,13 @@ +function sanity_and_clone(headers) { + var sanity_headers = JSON.parse(JSON.stringify(headers)); + + for(header in sanity_headers){ + sanity_headers[header.toLowerCase()] = sanity_headers[header]; + } + + return sanity_headers; +} + +module.exports = { + sanity_and_clone : sanity_and_clone +}; From 733476f4a1f963b5f5e5a7ef4e7bd40d83d6cd29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 18:45:53 -0300 Subject: [PATCH 059/110] Using the commons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_binary_0_2.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/bindings/http/receiver_binary_0_2.js b/lib/bindings/http/receiver_binary_0_2.js index 3c607e8f..b5ab2122 100644 --- a/lib/bindings/http/receiver_binary_0_2.js +++ b/lib/bindings/http/receiver_binary_0_2.js @@ -1,4 +1,5 @@ const Constants = require("./constants.js"); +const Commons = require("./commons.js"); const Cloudevent = require("../../cloudevent.js"); const Spec02 = require("../../specs/spec_0_2.js"); @@ -51,16 +52,6 @@ function validate_args(payload, attributes) { } } -function sanity(headers) { - var sanity_headers = JSON.parse(JSON.stringify(headers)); - - for(header in sanity_headers){ - sanity_headers[header.toLowerCase()] = sanity_headers[header]; - } - - return sanity_headers; -} - function Receiver(configuration) { } @@ -70,7 +61,7 @@ Receiver.prototype.check = function(payload, headers) { validate_args(payload, headers); // Clone and low case all headers names - var sanity_headers = sanity(headers); + var sanity_headers = Commons.sanity_and_clone(headers); // Validation Level 1 if(!allowed_content_types @@ -98,7 +89,7 @@ Receiver.prototype.parse = function(payload, headers) { this.check(payload, headers); // Clone and low case all headers names - var sanity_headers = sanity(headers); + var sanity_headers = Commons.sanity_and_clone(headers); var cloudevent = new Cloudevent(Spec02); for(header in setter_reflections) { From fbea122b7345fe89782ec755a9592d67a19dd678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 18:47:09 -0300 Subject: [PATCH 060/110] Receiver for structured MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_structured_0_2.js | 114 +++++------------- .../http/receiver_strutured_0_2_test.js | 64 ++++++++++ 2 files changed, 93 insertions(+), 85 deletions(-) create mode 100644 test/bindings/http/receiver_strutured_0_2_test.js diff --git a/lib/bindings/http/receiver_structured_0_2.js b/lib/bindings/http/receiver_structured_0_2.js index 81eec42a..6ca0ebc8 100644 --- a/lib/bindings/http/receiver_structured_0_2.js +++ b/lib/bindings/http/receiver_structured_0_2.js @@ -1,102 +1,46 @@ -var http = require("http"); -var Spec02 = require("../../specs/spec_0_2.js") -var spec02 = new Spec02(); +const Constants = require("./constants.js"); +const Commons = require("./commons.js"); +const Cloudevent = require("../../cloudevent.js"); +const Spec02 = require("../../specs/spec_0_2.js"); -const allowedContentTypes = []; -allowedContentTypes.push("application/cloudevents+json; charset=utf-8"); +const allowed_content_types = []; +allowed_content_types.push(Constants.MIME_CE_JSON); -function is_valid_http_request(req, res, config) { - var valid = true; - - if(req.url === config.path - && req.method.toLowerCase() - === config.method.toLowerCase()) { - - if(!req.headers["content-type"] - || !allowedContentTypes.includes( - req.headers["content-type"].toLowerCase())){ - res.statusCode = 400; - res.end("Bad Request"); - - valid = false; - } - - } else if(req.url !== config.path) { - res.statusCode = 404; - res.end("Not Found"); - - valid = false; - } else { - res.statusCode = 405; - res.end("Method Not Allowed"); - - valid = false; - } - - return valid; -} - -function HTTPStructured(configuration){ - this.config = configuration; - - if(!this.config["path"]){ - this.config["path"] = "/"; +function validate_args(payload, attributes) { + if(!payload){ + throw {message: "payload is null or undefined"}; } - if(!this.config["method"]){ - this.config["method"] = "POST"; + if(!attributes) { + throw {message: "attributes is null or undefined"}; } - if(!this.config["interface"]){ - this.config["interface"] = "0.0.0.0"; + if((typeof payload) !== "object"){ + throw {message: "payload must be an object", erros: [typeof payload]}; } } -HTTPStructured.prototype.receive = function(){ - this.server; - var self = this; +function Receiver(configuration) { - return new Promise((resolve, reject) => { - self.server = - http.createServer((request, res) => { - if(is_valid_http_request(request, res, this.config)){ - var body = []; - request.on("error", err => { - console.error(err); - }) - .on("data", chunk => { - // accumulate the chunks - body.push(chunk); - }) - .on("end", () => { - body = Buffer.concat(body).toString(); - var jsonBody = JSON.parse(body); +} + +Receiver.prototype.check = function(payload, headers) { + validate_args(payload, headers); - try { - // Process/validate the body - spec02.check(jsonBody); + var sanity_headers = Commons.sanity_and_clone(headers); - res.statusCode = 201; - res.end("Event Accepted"); - }catch(e) { - res.statusCode = 400; - res.end(JSON.stringify(e)); - } - }); - } - }); + // Validation Level 1 + if(!allowed_content_types + .includes(sanity_headers[Constants.HEADER_CONTENT_TYPE])){ + throw {message: "invalid content type", + errors: [sanity_headers[Constants.HEADER_CONTENT_TYPE]]}; + } - self.server.listen(this.config.port, this.config.interface, (err) => { - if(err){ - console.error(err); - reject(err); - } - }); - }); + // No erros! Its contains the minimum required attributes } -HTTPStructured.prototype.stop = function() { - this.server.close(); +Receiver.prototype.parse = function(payload, headers) { + this.check(payload, headers); } -module.exports = HTTPStructured; +module.exports = Receiver; diff --git a/test/bindings/http/receiver_strutured_0_2_test.js b/test/bindings/http/receiver_strutured_0_2_test.js new file mode 100644 index 00000000..5087020b --- /dev/null +++ b/test/bindings/http/receiver_strutured_0_2_test.js @@ -0,0 +1,64 @@ +var expect = require("chai").expect; + +var HTTPStructuredReceiver02 = + require("../../../lib/bindings/http/receiver_structured_0_2.js"); + +var receiver = new HTTPStructuredReceiver02(); + +describe("HTTP Transport Binding Structured Receiver 0.2", () => { + describe("Check", () => { + it("Throw error when payload arg is null or undefined", () => { + // setup + var payload = null; + var attributes = {}; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("payload is null or undefined"); + }); + + it("Throw error when attributes arg is null or undefined", () => { + // setup + var payload = {}; + var attributes = null; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("attributes is null or undefined"); + }); + + it("Throw error when payload is not an object", () => { + // setup + var payload = "wow"; + var attributes = {}; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("payload must be an object"); + }); + + it("Throw error when the content-type is invalid", () => { + // setup + var payload = {}; + var attributes = { + "Content-Type" : "text/html" + }; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.throw("invalid content type"); + }); + + it("No error when all required stuff are in place", () => { + // setup + var payload = {}; + var attributes = { + "Content-Type" : "application/cloudevents+json" + }; + + // act and assert + expect(receiver.check.bind(receiver, payload, attributes)) + .to.not.throw(); + }); + }); +}); From a1e2381dc95e9fcaf42a1ae62652249ffe8f12d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 18:47:51 -0300 Subject: [PATCH 061/110] terminator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bindings/http/constants.js b/lib/bindings/http/constants.js index 8b1898fb..6097bb0c 100644 --- a/lib/bindings/http/constants.js +++ b/lib/bindings/http/constants.js @@ -17,4 +17,4 @@ module.exports = { SCHEMA_URL : "ce-schemaurl", EXTENSIONS_PREFIX : "ce-" } -} +}; From 68b9866ffbf3190abc08bd43149f91875d8a2f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 19:10:24 -0300 Subject: [PATCH 062/110] Parses the payload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_structured_0_2.js | 22 ++++++- .../http/receiver_strutured_0_2_test.js | 66 +++++++++++++++++-- 2 files changed, 80 insertions(+), 8 deletions(-) diff --git a/lib/bindings/http/receiver_structured_0_2.js b/lib/bindings/http/receiver_structured_0_2.js index 6ca0ebc8..b61d7938 100644 --- a/lib/bindings/http/receiver_structured_0_2.js +++ b/lib/bindings/http/receiver_structured_0_2.js @@ -3,6 +3,14 @@ const Commons = require("./commons.js"); const Cloudevent = require("../../cloudevent.js"); const Spec02 = require("../../specs/spec_0_2.js"); +var JSONParser = require("../../formats/json/parser.js"); + +const jsonParserSpec02 = new JSONParser(new Spec02()); + +const parsers = {}; +parsers[Constants.MIME_JSON] = jsonParserSpec02; +parsers[Constants.MIME_CE_JSON] = jsonParserSpec02; + const allowed_content_types = []; allowed_content_types.push(Constants.MIME_CE_JSON); @@ -15,8 +23,9 @@ function validate_args(payload, attributes) { throw {message: "attributes is null or undefined"}; } - if((typeof payload) !== "object"){ - throw {message: "payload must be an object", erros: [typeof payload]}; + if((typeof payload) !== "object" && (typeof payload) !== "string"){ + throw {message: "payload must be an object or string", + erros: [typeof payload]}; } } @@ -41,6 +50,15 @@ Receiver.prototype.check = function(payload, headers) { Receiver.prototype.parse = function(payload, headers) { this.check(payload, headers); + + var sanity_headers = Commons.sanity_and_clone(headers); + + var contentType = sanity_headers[Constants.HEADER_CONTENT_TYPE]; + + var parser = parsers[contentType]; + var cloudevent = parser.parse(payload); + + return cloudevent; } module.exports = Receiver; diff --git a/test/bindings/http/receiver_strutured_0_2_test.js b/test/bindings/http/receiver_strutured_0_2_test.js index 5087020b..d668fd38 100644 --- a/test/bindings/http/receiver_strutured_0_2_test.js +++ b/test/bindings/http/receiver_strutured_0_2_test.js @@ -1,10 +1,41 @@ -var expect = require("chai").expect; +var expect = require("chai").expect; +var Cloudevent = require("../../../index.js"); +var Spec02 = require("../../../lib/specs/spec_0_2.js"); var HTTPStructuredReceiver02 = require("../../../lib/bindings/http/receiver_structured_0_2.js"); var receiver = new HTTPStructuredReceiver02(); +const type = "com.github.pull.create"; +const source = "urn:event:from:myapi/resourse/123"; +const webhook = "https://cloudevents.io/webhook"; +const contentType = "application/cloudevents+json; charset=utf-8"; +const now = new Date(); +const schemaurl = "http://cloudevents.io/schema.json"; + +const ceContentType = "application/json"; + +const data = { + foo: "bar" +}; + +const ext1Name = "extension1"; +const ext1Value = "foobar"; +const ext2Name = "extension2"; +const ext2Value = "acme"; + +var cloudevent = + new Cloudevent(Spec02) + .type(type) + .source(source) + .contenttype(ceContentType) + .time(now) + .schemaurl(schemaurl) + .data(data) + .addExtension(ext1Name, ext1Value) + .addExtension(ext2Name, ext2Value); + describe("HTTP Transport Binding Structured Receiver 0.2", () => { describe("Check", () => { it("Throw error when payload arg is null or undefined", () => { @@ -27,21 +58,21 @@ describe("HTTP Transport Binding Structured Receiver 0.2", () => { .to.throw("attributes is null or undefined"); }); - it("Throw error when payload is not an object", () => { + it("Throw error when payload is not an object or string", () => { // setup - var payload = "wow"; + var payload = 1.0; var attributes = {}; // act and assert expect(receiver.check.bind(receiver, payload, attributes)) - .to.throw("payload must be an object"); + .to.throw("payload must be an object or string"); }); it("Throw error when the content-type is invalid", () => { // setup var payload = {}; var attributes = { - "Content-Type" : "text/html" + "Content-Type" : "text/html" }; // act and assert @@ -53,7 +84,7 @@ describe("HTTP Transport Binding Structured Receiver 0.2", () => { // setup var payload = {}; var attributes = { - "Content-Type" : "application/cloudevents+json" + "Content-Type" : "application/cloudevents+json" }; // act and assert @@ -61,4 +92,27 @@ describe("HTTP Transport Binding Structured Receiver 0.2", () => { .to.not.throw(); }); }); + + describe("Parse", () => { + it("Throw error when the event does not follow the spec 0.2", () => { + // setup + var payload = + new Cloudevent() + .type(type) + .source(source) + .contenttype(ceContentType) + .time(now) + .schemaurl(schemaurl) + .data(data) + .toString(); + + var headers = { + "Content-Type":"application/cloudevents+json" + }; + + // act and assert + expect(receiver.parse.bind(receiver, payload, headers)) + .to.throw("invalid payload"); + }); + }); }); From 39cc73084526958ebeafbcb1bfb427d4779bacd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 19:11:55 -0300 Subject: [PATCH 063/110] fix import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- test/http_binding_0_2.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/http_binding_0_2.js b/test/http_binding_0_2.js index 345d75e2..07d01d40 100644 --- a/test/http_binding_0_2.js +++ b/test/http_binding_0_2.js @@ -2,7 +2,7 @@ var expect = require("chai").expect; var Cloudevent = require("../index.js"); var nock = require("nock"); var ReceiverStructured01 = - require("../lib/bindings/http/receiver_structured_0_2.js"); + require("../lib/bindings/http/server/structured_0_2.js"); var http = require("http"); var request = require("request"); var Spec02 = require("../lib/specs/spec_0_2.js"); @@ -201,6 +201,7 @@ describe("HTTP Transport Binding - Version 0.2", () => { .to.have.property("ce-type"); }); }); + it("HTTP Header contains 'ce-specversion'", () => { return httpbinary02.emit(cloudevent) .then((response) => { @@ -208,6 +209,7 @@ describe("HTTP Transport Binding - Version 0.2", () => { .to.have.property("ce-specversion"); }); }); + it("HTTP Header contains 'ce-source'", () => { return httpbinary02.emit(cloudevent) .then((response) => { @@ -215,6 +217,7 @@ describe("HTTP Transport Binding - Version 0.2", () => { .to.have.property("ce-source"); }); }); + it("HTTP Header contains 'ce-id'", () => { return httpbinary02.emit(cloudevent) .then((response) => { @@ -222,6 +225,7 @@ describe("HTTP Transport Binding - Version 0.2", () => { .to.have.property("ce-id"); }); }); + it("HTTP Header contains 'ce-time'", () => { return httpbinary02.emit(cloudevent) .then((response) => { @@ -229,6 +233,7 @@ describe("HTTP Transport Binding - Version 0.2", () => { .to.have.property("ce-time"); }); }); + it("HTTP Header contains 'ce-schemaurl'", () => { return httpbinary02.emit(cloudevent) .then((response) => { @@ -236,6 +241,7 @@ describe("HTTP Transport Binding - Version 0.2", () => { .to.have.property("ce-schemaurl"); }); }); + it("HTTP Header contains 'ce-" + ext1Name + "'", () => { return httpbinary02.emit(cloudevent) .then((response) => { @@ -243,6 +249,7 @@ describe("HTTP Transport Binding - Version 0.2", () => { .to.have.property("ce-" + ext1Name); }); }); + it("HTTP Header contains 'ce-" + ext2Name + "'", () => { return httpbinary02.emit(cloudevent) .then((response) => { From c1e858fbd638aa458a7d862e2d10989c3ccf555f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 19:14:29 -0300 Subject: [PATCH 064/110] Happy path test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- .../http/receiver_strutured_0_2_test.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/bindings/http/receiver_strutured_0_2_test.js b/test/bindings/http/receiver_strutured_0_2_test.js index d668fd38..076c4cec 100644 --- a/test/bindings/http/receiver_strutured_0_2_test.js +++ b/test/bindings/http/receiver_strutured_0_2_test.js @@ -114,5 +114,29 @@ describe("HTTP Transport Binding Structured Receiver 0.2", () => { expect(receiver.parse.bind(receiver, payload, headers)) .to.throw("invalid payload"); }); + + it("Should accept event that follow the spec 0.2", () => { + // setup + var payload = + new Cloudevent(Cloudevent.specs["0.2"]) + .type(type) + .source(source) + .contenttype(ceContentType) + .time(now) + .schemaurl(schemaurl) + .data(data) + .toString(); + + var headers = { + "content-type":"application/cloudevents+json" + }; + + // act + var actual = receiver.parse(payload, headers); + + // assert + expect(actual) + .to.be.an("object"); + }); }); }); From 1e278c0025156b5e234e1ceefa8d1e1d770a8b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 19:16:29 -0300 Subject: [PATCH 065/110] cleanning the code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_structured_0_2.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/bindings/http/receiver_structured_0_2.js b/lib/bindings/http/receiver_structured_0_2.js index b61d7938..e5cacd38 100644 --- a/lib/bindings/http/receiver_structured_0_2.js +++ b/lib/bindings/http/receiver_structured_0_2.js @@ -7,9 +7,9 @@ var JSONParser = require("../../formats/json/parser.js"); const jsonParserSpec02 = new JSONParser(new Spec02()); -const parsers = {}; -parsers[Constants.MIME_JSON] = jsonParserSpec02; -parsers[Constants.MIME_CE_JSON] = jsonParserSpec02; +const parser_by_mime = {}; +parser_by_mime[Constants.MIME_JSON] = jsonParserSpec02; +parser_by_mime[Constants.MIME_CE_JSON] = jsonParserSpec02; const allowed_content_types = []; allowed_content_types.push(Constants.MIME_CE_JSON); @@ -54,8 +54,9 @@ Receiver.prototype.parse = function(payload, headers) { var sanity_headers = Commons.sanity_and_clone(headers); var contentType = sanity_headers[Constants.HEADER_CONTENT_TYPE]; + + var parser = parser_by_mime[contentType]; - var parser = parsers[contentType]; var cloudevent = parser.parse(payload); return cloudevent; From 6a1d70c503d8c1301d30ce96f2a47ae89958aa37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 19:30:23 -0300 Subject: [PATCH 066/110] Fix binding server signature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/server/structured_0_2.js | 102 +++++++++++++++++++++ test/http_binding_0_2.js | 4 +- 2 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 lib/bindings/http/server/structured_0_2.js diff --git a/lib/bindings/http/server/structured_0_2.js b/lib/bindings/http/server/structured_0_2.js new file mode 100644 index 00000000..9d465976 --- /dev/null +++ b/lib/bindings/http/server/structured_0_2.js @@ -0,0 +1,102 @@ +var http = require("http"); +var Spec02 = require("../../../specs/spec_0_2.js") +var spec02 = new Spec02(); + +const allowedContentTypes = []; +allowedContentTypes.push("application/cloudevents+json; charset=utf-8"); + +function is_valid_http_request(req, res, config) { + var valid = true; + + if(req.url === config.path + && req.method.toLowerCase() + === config.method.toLowerCase()) { + + if(!req.headers["content-type"] + || !allowedContentTypes.includes( + req.headers["content-type"].toLowerCase())){ + res.statusCode = 400; + res.end("Bad Request"); + + valid = false; + } + + } else if(req.url !== config.path) { + res.statusCode = 404; + res.end("Not Found"); + + valid = false; + } else { + res.statusCode = 405; + res.end("Method Not Allowed"); + + valid = false; + } + + return valid; +} + +function HTTPStructured(configuration){ + this.config = configuration; + + if(!this.config["path"]){ + this.config["path"] = "/"; + } + + if(!this.config["method"]){ + this.config["method"] = "POST"; + } + + if(!this.config["interface"]){ + this.config["interface"] = "0.0.0.0"; + } +} + +HTTPStructured.prototype.listen = function(){ + this.server; + var self = this; + + return new Promise((resolve, reject) => { + self.server = + http.createServer((request, res) => { + if(is_valid_http_request(request, res, this.config)){ + var body = []; + request.on("error", err => { + console.error(err); + }) + .on("data", chunk => { + // accumulate the chunks + body.push(chunk); + }) + .on("end", () => { + body = Buffer.concat(body).toString(); + var jsonBody = JSON.parse(body); + + try { + // Process/validate the body + spec02.check(jsonBody); + + res.statusCode = 201; + res.end("Event Accepted"); + }catch(e) { + res.statusCode = 400; + res.end(JSON.stringify(e)); + } + }); + } + }); + + self.server.listen(this.config.port, this.config.interface, (err) => { + if(err){ + console.error(err); + reject(err); + } + }); + }); +} + +HTTPStructured.prototype.stop = function() { + this.server.close(); +} + +module.exports = HTTPStructured; diff --git a/test/http_binding_0_2.js b/test/http_binding_0_2.js index 07d01d40..7bbecb53 100644 --- a/test/http_binding_0_2.js +++ b/test/http_binding_0_2.js @@ -87,7 +87,7 @@ describe("HTTP Transport Binding - Version 0.2", () => { before(() => { // setup receiver = new ReceiverStructured01(receiverConfig); - receiver.receive() + receiver.listen() .then(response => { console.log(response); }) @@ -249,7 +249,7 @@ describe("HTTP Transport Binding - Version 0.2", () => { .to.have.property("ce-" + ext1Name); }); }); - + it("HTTP Header contains 'ce-" + ext2Name + "'", () => { return httpbinary02.emit(cloudevent) .then((response) => { From a18baf4aa8155fe2ae0350f7850095be9ba54c46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 20:05:44 -0300 Subject: [PATCH 067/110] Closes #20: contributing guidelines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- CONTRIBUTING.md | 28 ++++++++++++++++++++++++++++ README.md | 4 ++++ 2 files changed, 32 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..c9812862 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,28 @@ +# Contributing to CloudEvents' JavaScript SDK + +:+1::tada: First off, thanks for taking the time to contribute! :tada::+1: + +Following you will see some guidelines about how to contribute with +JavaScript SDK. + +## Pull Requests + +Guidelines about how to perform pull requests. + +### PR to `develop` + +- fixes in the documentation (readme, contributors) +- propose new files for documentation +- implementation of new features + +### PR to `master` + +- hot fixes + +## Style Guide + +_TODO_ + +### JavaScript Style Guide + +_TODO_ diff --git a/README.md b/README.md index a931bd39..a7cb1d7e 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ Official CloudEvents' SDK for JavaScript. CloudEvents logo +## Contributing + +Before create an awesome PR, please read our [guidelines](./CONTRIBUTING.md). + ## Versioning ### Before Spec reaches 1.0 From 064b0226bd599e4122901f4d8b550de83b107ddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 20:08:35 -0300 Subject: [PATCH 068/110] Fix contributing. Closes #20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- CONTRIBUTING.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c9812862..ba67986a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,10 +9,12 @@ JavaScript SDK. Guidelines about how to perform pull requests. +- before submit the PR, open an issue and link them + ### PR to `develop` - fixes in the documentation (readme, contributors) -- propose new files for documentation +- propose new files for the documentation - implementation of new features ### PR to `master` From b4c38464916aa0574df4d8f559ba810728856874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 20:46:18 -0300 Subject: [PATCH 069/110] Unmarshaller impl and tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/unmarshaller_0_2.js | 36 +++++----- test/bindings/http/unmarshaller_0_2_tests.js | 72 ++++++++++++++++++++ 2 files changed, 89 insertions(+), 19 deletions(-) diff --git a/lib/bindings/http/unmarshaller_0_2.js b/lib/bindings/http/unmarshaller_0_2.js index b1024e13..11080868 100644 --- a/lib/bindings/http/unmarshaller_0_2.js +++ b/lib/bindings/http/unmarshaller_0_2.js @@ -1,15 +1,16 @@ -var Spec02 = require("../../specs/spec_0_2.js"); -var JSONParser = require("../../formats/json/parser.js"); +var StructuredReceiver = require("./receiver_structured_0_2.js"); +var BinaryReceiver = require("./receiver_binary_0_2.js"); const Constants = require("./constants.js"); +const Commons = require("./commons.js"); const structured = "structured"; const binary = "binary"; -const jsonParserSpec02 = new JSONParser(new Spec02()); -const parsers = {}; -parsers[Constants.MIME_JSON] = jsonParserSpec02; -parsers[Constants.MIME_CE_JSON] = jsonParserSpec02; +const receiver_by_binding = { + structured : new StructuredReceiver(), + binary : new BinaryReceiver(), +}; const allowed_binary_content_types = []; allowed_binary_content_types.push(Constants.MIME_JSON); @@ -25,10 +26,6 @@ function validate_args(payload, headers) { if(!headers){ throw {message: "headers is null or undefined"}; } - - if(!headers[Constants.HEADER_CONTENT_TYPE]){ - throw {message: "content-type header not found"}; - } } // Is it binary or structured? @@ -59,19 +56,20 @@ var Unmarshaller = function() { Unmarshaller.prototype.unmarshall = function(payload, headers) { validate_args(payload, headers); - // Resolve the binding - var bindingName = resolve_binding_name(payload, headers); - var contentType = headers[Constants.HEADER_CONTENT_TYPE]; + var sanity_headers = Commons.sanity_and_clone(headers); - if(bindingName === structured){ - var parser = parsers[contentType]; - var cloudevent = parser.parse(payload); + // Validation level 1 + if(!sanity_headers[Constants.HEADER_CONTENT_TYPE]){ + throw {message: "content-type header not found"}; + } - return cloudevent; - } else {//binary + // Resolve the binding + var binding_name = resolve_binding_name(payload, sanity_headers); - } + var cloudevent = + receiver_by_binding[binding_name].parse(payload, sanity_headers); + return cloudevent; } module.exports = Unmarshaller; diff --git a/test/bindings/http/unmarshaller_0_2_tests.js b/test/bindings/http/unmarshaller_0_2_tests.js index f20d9203..3760124a 100644 --- a/test/bindings/http/unmarshaller_0_2_tests.js +++ b/test/bindings/http/unmarshaller_0_2_tests.js @@ -125,4 +125,76 @@ describe("HTTP Transport Binding Unmarshaller", () => { .to.be.an("object"); }); }); + + describe("Binary", () => { + it("Throw error when has not allowed mime", () => { + // setup + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "source", + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00Z", + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "text/html" + }; + + var un = new Unmarshaller(); + + // act and assert + expect(un.unmarshall.bind(un, payload, attributes)) + .to.throw("content type not allowed"); + }); + + it("Throw error when the event does not follow the spec 0.2", () => { + // setup + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "CE-CloudEventsVersion" : "0.1", + "ce-source" : "source", + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00Z", + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "application/json" + }; + + var un = new Unmarshaller(); + + // act and assert + expect(un.unmarshall.bind(un, payload, attributes)) + .to.throw(); + }); + + it("No error when all attributes are in place", () => { + // setup + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "source", + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00Z", + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "application/json" + }; + + var un = new Unmarshaller(); + + // act + var actual = un.unmarshall(payload, attributes); + + // assert + expect(actual) + .to.be.an("object"); + + }); + }); }); From 70627ee5d29aebd89cb9a4310b681bec815e658f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 20:53:55 -0300 Subject: [PATCH 070/110] Igore files for npm publish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- .npmignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .npmignore diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..76ba1f98 --- /dev/null +++ b/.npmignore @@ -0,0 +1,3 @@ +examples/ +.travis.yml + From 9b98aad083a22914205b4068e49d90fa37851ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 21:05:10 -0300 Subject: [PATCH 071/110] Examples folder start with expressjs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/express-ex/index.js | 11 +++++++++++ examples/express-ex/package.json | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 examples/express-ex/index.js create mode 100644 examples/express-ex/package.json diff --git a/examples/express-ex/index.js b/examples/express-ex/index.js new file mode 100644 index 00000000..5ee7d3fd --- /dev/null +++ b/examples/express-ex/index.js @@ -0,0 +1,11 @@ +var express = require('express'); +var app = express(); + +app.get('/', function (req, res) { + res.send('Hello World!'); +}); + +app.listen(3000, function () { + console.log('Example app listening on port 3000!'); +}); + diff --git a/examples/express-ex/package.json b/examples/express-ex/package.json new file mode 100644 index 00000000..69e7c0ae --- /dev/null +++ b/examples/express-ex/package.json @@ -0,0 +1,19 @@ +{ + "name": "express-ex", + "version": "1.0.0", + "description": "Examples to use CloudEvents with Express", + "main": "index.js", + "scripts": { + "start": "node index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "cloudevents", + "express" + ], + "author": "fabiojose@gmail.com", + "license": "Apache-2.0", + "dependencies": { + "express": "^4.17.1" + } +} From 6b859f13b47164b59408a3b46cac97b98d1b5ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 21:06:34 -0300 Subject: [PATCH 072/110] Docs for examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a7cb1d7e..0f552cf0 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,10 @@ Official CloudEvents' SDK for JavaScript. Before create an awesome PR, please read our [guidelines](./CONTRIBUTING.md). +## Examples + +To see working examples, point to [examples](./examplpes). + ## Versioning ### Before Spec reaches 1.0 @@ -165,8 +169,19 @@ binding.emit(cloudevent) console.error(err); }); ``` +#### Receiving Events Using Express + +See how to listen to events using +[express](https://github.com/expressjs/express). + +```js + + +``` + +#### Receiving Using our Simple HTTP Server -#### Receiving +See how to listen to events using out simple http server. ```js var Cloudevent = require("cloudevents-sdk"); @@ -181,7 +196,7 @@ var config = { // The binding instance var binding = new Cloudevent.bindings["http-structured0.2"](config); -binding.receive() +binding.listen() .then(cloudevent => { // do something with event }) From d21881a2b58b66dd2e6723d8ba80ae9b57bc89ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Sun, 16 Jun 2019 21:10:26 -0300 Subject: [PATCH 073/110] WIP: example with expressjs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/express-ex/index.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/examples/express-ex/index.js b/examples/express-ex/index.js index 5ee7d3fd..b2c9a11a 100644 --- a/examples/express-ex/index.js +++ b/examples/express-ex/index.js @@ -2,10 +2,14 @@ var express = require('express'); var app = express(); app.get('/', function (req, res) { - res.send('Hello World!'); + console.log(req.headers); + console.log(req.body); + + // TODO use the Unmarshaller + + res.send('Hello World!'); }); app.listen(3000, function () { - console.log('Example app listening on port 3000!'); + console.log('Example app listening on port 3000!'); }); - From d4187897644b32b4ce8f121f5107ce51d90c9f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 20 Jun 2019 21:21:44 -0300 Subject: [PATCH 074/110] Fixing formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0f552cf0..c20c92de 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ These are the supported specifications by this version. | Emit Structured events over HTTP | yes | yes | | Emit Binary events over HTTP | yes | yes | | JSON Event Format | yes | yes | -| Receice Structure events over HTTP | no | yes | +| Receice Structured events over HTTP| no | yes | | Receice Binary events over HTTP | no | yes | ## How to use @@ -95,7 +95,7 @@ cloudevent01 * to Cloudevent */ cloudevent01 - .eventTypeVersion("1.0"); + .eventTypeVersion("1.0"); /* * Constructs an instance with: @@ -130,8 +130,6 @@ var cloudevent = * Format the payload and return it */ var formatted = cloudevent.format(); - -var ce = ``` #### Emitting @@ -140,9 +138,10 @@ var ce = var Cloudevent = require("cloudevents-sdk"); // The event -var cloudevent = new Cloudevent() - .type("com.github.pull.create") - .source("urn:event:from:myapi/resourse/123"); +var cloudevent = + new Cloudevent() + .type("com.github.pull.create") + .source("urn:event:from:myapi/resourse/123"); // The binding configuration using POST var config = { From 68c384ed5bd0dc8b0007906d1d564e9fe542d7e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 20 Jun 2019 21:36:17 -0300 Subject: [PATCH 075/110] Document the unmarshaller api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/README.md b/README.md index c20c92de..0731823f 100644 --- a/README.md +++ b/README.md @@ -378,6 +378,29 @@ Promise Receiver.listen() Receiver.stop() ``` +### `Unmarshaller` classes + +The Unmarshaller classes uses the receiver API, abstracting the formats: + + - structured + - binary + +Choosing the right implementation based on the `headers` map. + +```js +/* + * Constructor without arguments + */ +Unmarshaller() + +/* + * The method to unmarshall the payload. + * @arg payload could be a string or a object + * @arg headers a map of headers + */ +Promise Unmarshaller.unmarshall(payload, headers) +``` + > See how to implement the method injection [here](lib/specs/spec_0_1.js#L17) > > Learn about [Builder Design Pattern](https://en.wikipedia.org/wiki/Builder_pattern) From b000b2b0bd08d2e7e231e2fb7923a9fb5985b7ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 20 Jun 2019 21:42:42 -0300 Subject: [PATCH 076/110] Test titles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- test/bindings/http/receiver_binary_0_2_tests.js | 2 +- test/bindings/http/receiver_strutured_0_2_test.js | 2 +- test/bindings/http/unmarshaller_0_2_tests.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/bindings/http/receiver_binary_0_2_tests.js b/test/bindings/http/receiver_binary_0_2_tests.js index 213fff51..ed2b1493 100644 --- a/test/bindings/http/receiver_binary_0_2_tests.js +++ b/test/bindings/http/receiver_binary_0_2_tests.js @@ -5,7 +5,7 @@ var HTTPBinaryReceiver02 = var receiver = new HTTPBinaryReceiver02(); -describe("HTTP Transport Binding Binary Receiver 0.2", () => { +describe("HTTP Transport Binding Binary Receiver for CloudEvents v0.2", () => { describe("Check", () => { it("Throw error when payload arg is null or undefined", () => { // setup diff --git a/test/bindings/http/receiver_strutured_0_2_test.js b/test/bindings/http/receiver_strutured_0_2_test.js index 076c4cec..25eb9f6b 100644 --- a/test/bindings/http/receiver_strutured_0_2_test.js +++ b/test/bindings/http/receiver_strutured_0_2_test.js @@ -36,7 +36,7 @@ var cloudevent = .addExtension(ext1Name, ext1Value) .addExtension(ext2Name, ext2Value); -describe("HTTP Transport Binding Structured Receiver 0.2", () => { +describe("HTTP Transport Binding Structured Receiver for CloudEvents v0.2", () => { describe("Check", () => { it("Throw error when payload arg is null or undefined", () => { // setup diff --git a/test/bindings/http/unmarshaller_0_2_tests.js b/test/bindings/http/unmarshaller_0_2_tests.js index 3760124a..4123b494 100644 --- a/test/bindings/http/unmarshaller_0_2_tests.js +++ b/test/bindings/http/unmarshaller_0_2_tests.js @@ -15,7 +15,7 @@ const data = { foo: "bar" }; -describe("HTTP Transport Binding Unmarshaller", () => { +describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.2", () => { it("Throw error when payload is null", () => { // setup From 0a740eb136d2680bb994891652bc6b60edab5f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 20 Jun 2019 21:45:49 -0300 Subject: [PATCH 077/110] Export of http unmarshaller 0.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- http/unmarshaller/v02.js | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 http/unmarshaller/v02.js diff --git a/http/unmarshaller/v02.js b/http/unmarshaller/v02.js new file mode 100644 index 00000000..8ae0d3e2 --- /dev/null +++ b/http/unmarshaller/v02.js @@ -0,0 +1,3 @@ +var Unmarshaller = require("../../lib/bindings/http/unmarshaller_0_2.js"); + +module.exports = Unmarshaller; From 46dd70563da87f8e83f163cc4fd715b4a7358692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 20 Jun 2019 21:46:11 -0300 Subject: [PATCH 078/110] Using the export of http unmarchaller 0.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- test/bindings/http/unmarshaller_0_2_tests.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/bindings/http/unmarshaller_0_2_tests.js b/test/bindings/http/unmarshaller_0_2_tests.js index 4123b494..08469160 100644 --- a/test/bindings/http/unmarshaller_0_2_tests.js +++ b/test/bindings/http/unmarshaller_0_2_tests.js @@ -1,6 +1,6 @@ var expect = require("chai").expect; -var Unmarshaller = require("../../../lib/bindings/http/unmarshaller_0_2.js"); -var Cloudevent = require("../../../index.js"); +var Unmarshaller = require("../../../http/unmarshaller/v02.js"); +var Cloudevent = require("../../../index.js"); const type = "com.github.pull.create"; const source = "urn:event:from:myapi/resourse/123"; From 3dad0d200ced10426a100db35b14fd2da0a81c06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Thu, 20 Jun 2019 21:58:10 -0300 Subject: [PATCH 079/110] Remove server stuff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 50 +--------- lib/bindings/http/server/structured_0_2.js | 102 --------------------- test/http_binding_0_2.js | 95 ------------------- 3 files changed, 1 insertion(+), 246 deletions(-) delete mode 100644 lib/bindings/http/server/structured_0_2.js diff --git a/README.md b/README.md index 0731823f..647e0234 100644 --- a/README.md +++ b/README.md @@ -174,37 +174,10 @@ See how to listen to events using [express](https://github.com/expressjs/express). ```js - +var Unmarshaller02 = require("cloudevents-sdk/http/unmarshaller/v02"); ``` -#### Receiving Using our Simple HTTP Server - -See how to listen to events using out simple http server. - -```js -var Cloudevent = require("cloudevents-sdk"); - -// The binding configuration -var config = { - path : "/events", - port : 10300, - method : "POST" -}; - -// The binding instance -var binding = new Cloudevent.bindings["http-structured0.2"](config); - -binding.listen() - .then(cloudevent => { - // do something with event - }) - .catch(err => { - // deal with errors - console.error(err); - }); -``` - ## Repository Structure ```text @@ -357,27 +330,6 @@ Receiver.check(Object, Map) Cloudevent Receiver.parse(Object, Map) ``` -##### Receiver Binding Server - -Use this API to start a HTTP server and listen to events. - -```js -/* - * The constructor must receives the map of configurations. - */ -Receiver(config) - -/* - * Listen to events and returns a Promise. - */ -Promise Receiver.listen() - -/* - * Stops the listen to events - */ -Receiver.stop() -``` - ### `Unmarshaller` classes The Unmarshaller classes uses the receiver API, abstracting the formats: diff --git a/lib/bindings/http/server/structured_0_2.js b/lib/bindings/http/server/structured_0_2.js deleted file mode 100644 index 9d465976..00000000 --- a/lib/bindings/http/server/structured_0_2.js +++ /dev/null @@ -1,102 +0,0 @@ -var http = require("http"); -var Spec02 = require("../../../specs/spec_0_2.js") -var spec02 = new Spec02(); - -const allowedContentTypes = []; -allowedContentTypes.push("application/cloudevents+json; charset=utf-8"); - -function is_valid_http_request(req, res, config) { - var valid = true; - - if(req.url === config.path - && req.method.toLowerCase() - === config.method.toLowerCase()) { - - if(!req.headers["content-type"] - || !allowedContentTypes.includes( - req.headers["content-type"].toLowerCase())){ - res.statusCode = 400; - res.end("Bad Request"); - - valid = false; - } - - } else if(req.url !== config.path) { - res.statusCode = 404; - res.end("Not Found"); - - valid = false; - } else { - res.statusCode = 405; - res.end("Method Not Allowed"); - - valid = false; - } - - return valid; -} - -function HTTPStructured(configuration){ - this.config = configuration; - - if(!this.config["path"]){ - this.config["path"] = "/"; - } - - if(!this.config["method"]){ - this.config["method"] = "POST"; - } - - if(!this.config["interface"]){ - this.config["interface"] = "0.0.0.0"; - } -} - -HTTPStructured.prototype.listen = function(){ - this.server; - var self = this; - - return new Promise((resolve, reject) => { - self.server = - http.createServer((request, res) => { - if(is_valid_http_request(request, res, this.config)){ - var body = []; - request.on("error", err => { - console.error(err); - }) - .on("data", chunk => { - // accumulate the chunks - body.push(chunk); - }) - .on("end", () => { - body = Buffer.concat(body).toString(); - var jsonBody = JSON.parse(body); - - try { - // Process/validate the body - spec02.check(jsonBody); - - res.statusCode = 201; - res.end("Event Accepted"); - }catch(e) { - res.statusCode = 400; - res.end(JSON.stringify(e)); - } - }); - } - }); - - self.server.listen(this.config.port, this.config.interface, (err) => { - if(err){ - console.error(err); - reject(err); - } - }); - }); -} - -HTTPStructured.prototype.stop = function() { - this.server.close(); -} - -module.exports = HTTPStructured; diff --git a/test/http_binding_0_2.js b/test/http_binding_0_2.js index 7bbecb53..01f619ba 100644 --- a/test/http_binding_0_2.js +++ b/test/http_binding_0_2.js @@ -1,8 +1,6 @@ var expect = require("chai").expect; var Cloudevent = require("../index.js"); var nock = require("nock"); -var ReceiverStructured01 = - require("../lib/bindings/http/server/structured_0_2.js"); var http = require("http"); var request = require("request"); var Spec02 = require("../lib/specs/spec_0_2.js"); @@ -81,99 +79,6 @@ describe("HTTP Transport Binding - Version 0.2", () => { }); }); }); - - describe("Receiver", () => { - var receiver; - before(() => { - // setup - receiver = new ReceiverStructured01(receiverConfig); - receiver.listen() - .then(response => { - console.log(response); - }) - .catch(err => { - console.error(err); - }); - }); - - after(() => { - receiver.stop(); - }); - - it("Should return 404 when path is wrong", () => { - // act - request.post("http://localhost:" + receiverConfig.port + "/foobar", - (err, res, body) => { - // assert - expect(res.statusCode).to.equal(404); - }); - }); - - it("Should return 405 when method is wrong", () => { - // act - request.get("http://localhost:" + receiverConfig.port - + receiverConfig.path, - (err, res, body) => { - // assert - expect(res.statusCode).to.equal(405); - }); - }); - - it("Should return 400 when Content-Type is wrong", () => { - // act - request.post("http://localhost:" + receiverConfig.port - + receiverConfig.path, - (err, res, body) => { - // assert - expect(res.statusCode).to.equal(400); - }); - }); - - it("Should return 400 when is not a cloudevent", () => { - // setup - var requestOptions = { - url : "http://localhost:" + receiverConfig.port - + receiverConfig.path, - method : "POST", - headers : { - "Content-Type":"application/cloudevents+json; charset=utf-8" - }, - body : JSON.stringify({"foo": "bar"}) - }; - - // act - request(requestOptions, - (err, res, body) => { - // assert - expect(res.statusCode).to.equal(400); - }); - }); - - it("Should return 201 when accepts the event", () => { - // setup - var ce_spec02 = new Spec02(); - ce_spec02 - .type(type) - .source(source); - - var requestOptions = { - url : "http://localhost:" + receiverConfig.port - + receiverConfig.path, - method : "POST", - headers : { - "Content-Type":"application/cloudevents+json; charset=utf-8" - }, - body : JSON.stringify(ce_spec02.payload) - }; - - // act - request(requestOptions, - (err, res, body) => { - // assert - expect(res.statusCode).to.equal(201); - }); - }); - }); }); describe("Binary", () => { From abdcf0f9f00d88c4ed064275553734e6cf545e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Fri, 21 Jun 2019 09:05:37 -0300 Subject: [PATCH 080/110] CloudEvent payloads examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/payload/data-0.json | 5 +++++ examples/payload/v02/structured-event-0.json | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 examples/payload/data-0.json create mode 100644 examples/payload/v02/structured-event-0.json diff --git a/examples/payload/data-0.json b/examples/payload/data-0.json new file mode 100644 index 00000000..91e844d7 --- /dev/null +++ b/examples/payload/data-0.json @@ -0,0 +1,5 @@ +{ + "data":{ + "much":"wow" + } +} diff --git a/examples/payload/v02/structured-event-0.json b/examples/payload/v02/structured-event-0.json new file mode 100644 index 00000000..298c2d5b --- /dev/null +++ b/examples/payload/v02/structured-event-0.json @@ -0,0 +1,11 @@ +{ + "specversion":"0.2", + "type":"com.github.pull.create", + "source":"https://github.com/cloudevents/spec/pull/123", + "id":"45c83279-c8a1-4db6-a703-b3768db93887", + "time":"2019-06-21T17:31:00Z", + "contenttype":"application/json", + "data":{ + "much":"wow" + } +} From 951008d7975d60401147ceb0ac63742a03ddd7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Fri, 21 Jun 2019 09:08:11 -0300 Subject: [PATCH 081/110] Temporary ref to dep from git MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/express-ex/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/express-ex/package.json b/examples/express-ex/package.json index 69e7c0ae..71fc7e8d 100644 --- a/examples/express-ex/package.json +++ b/examples/express-ex/package.json @@ -14,6 +14,7 @@ "author": "fabiojose@gmail.com", "license": "Apache-2.0", "dependencies": { - "express": "^4.17.1" + "express": "^4.17.1", + "cloudevents-sdk": "cloudevents/sdk-javascript#receive" } } From a2ae5b92319b6f37912629fcefd3a0ad65dd9842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Fri, 21 Jun 2019 10:55:28 -0300 Subject: [PATCH 082/110] Express example doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/express-ex/README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 examples/express-ex/README.md diff --git a/examples/express-ex/README.md b/examples/express-ex/README.md new file mode 100644 index 00000000..64be0d79 --- /dev/null +++ b/examples/express-ex/README.md @@ -0,0 +1,35 @@ +# Express Example + +## To Start + +```bash +npm start +``` + +## To Post an Event + +__A Structured One__ + +```bash +curl -X POST \ + -d'@../payload/v02/structured-event-0.json' \ + -H'Content-Type:application/cloudevents+json' \ + http://localhost:3000/ +``` + +__A Binary One__ + +```bash +curl -X POST \ + -d'@../payload/data-0.json' \ + -H'Content-Type:application/json' \ + -H'ce_specversion:0.2' \ + -H'ce_type:com.github.pull.create' \ + -H'ce_source:https://github.com/cloudevents/spec/pull/123' \ + -H'ce_id:45c83279-c8a1-4db6-a703-b3768db93887' \ + -H'ce_time:2019-06-21T17:31:00Z' \ + http://localhost:3000/ +``` +__A Batch One__ + +TODO From fb92f710ead91a13d0bfa466b195e4e8ea975679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Fri, 21 Jun 2019 10:56:02 -0300 Subject: [PATCH 083/110] Remove the responsability of spec checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/formats/json/parser.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/lib/formats/json/parser.js b/lib/formats/json/parser.js index 115b6aed..66e54193 100644 --- a/lib/formats/json/parser.js +++ b/lib/formats/json/parser.js @@ -1,9 +1,5 @@ -var Spec02 = require("../../specs/spec_0_2.js"); +function JSONParser() { -const spec02 = new Spec02(); - -function JSONParser(_spec) { - this.spec = (_spec) ? _spec : new Spec02(); } /** @@ -45,13 +41,10 @@ function validate_spec(payload, spec) { JSONParser.prototype.parse = function(payload) { - // Level 0 of validation: is that string? is that JSON? - var valid0 = validate_and_parse_as_json(payload); - - // Level 1 of validation: is that follow a spec? - var valid1 = validate_spec(valid0, this.spec); + //is that string? is that JSON? + var valid = validate_and_parse_as_json(payload); - return valid1; + return valid; } module.exports = JSONParser; From 3f13000e35d46f314a0c7102ae6761a7039cdb49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Fri, 21 Jun 2019 10:56:30 -0300 Subject: [PATCH 084/110] Add the responsability of parse the data attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_binary_0_2.js | 32 ++++++++++++++++++------ 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/lib/bindings/http/receiver_binary_0_2.js b/lib/bindings/http/receiver_binary_0_2.js index b5ab2122..9634c8ee 100644 --- a/lib/bindings/http/receiver_binary_0_2.js +++ b/lib/bindings/http/receiver_binary_0_2.js @@ -3,6 +3,11 @@ const Commons = require("./commons.js"); const Cloudevent = require("../../cloudevent.js"); const Spec02 = require("../../specs/spec_0_2.js"); +const JSONParser = require("../../formats/json/parser.js"); + +const parser_by_type = {}; +parser_by_type[Constants.MIME_JSON] = new JSONParser(); + const allowed_content_types = []; allowed_content_types.push(Constants.MIME_JSON); @@ -47,8 +52,11 @@ function validate_args(payload, attributes) { throw {message: "attributes is null or undefined"}; } - if((typeof payload) !== "object"){ - throw {message: "payload must be an object", erros: [typeof payload]}; + if((typeof payload) !== "object" && (typeof payload) !== "string"){ + throw { + message: "payload must be an object or a string", + errors: [typeof payload] + }; } } @@ -66,8 +74,10 @@ Receiver.prototype.check = function(payload, headers) { // Validation Level 1 if(!allowed_content_types .includes(sanity_headers[Constants.HEADER_CONTENT_TYPE])){ - throw {message: "invalid content type", - errors: [sanity_headers[Constants.HEADER_CONTENT_TYPE]]}; + throw { + message: "invalid content type", + errors: [sanity_headers[Constants.HEADER_CONTENT_TYPE]] + }; } for(i in required_headers){ @@ -77,9 +87,10 @@ Receiver.prototype.check = function(payload, headers) { } if(sanity_headers[Constants.BINARY_HEADERS_02.SPEC_VERSION] !== "0.2"){ - throw {message: "invalid spec version", - errors: - [sanity_headers[Constants.BINARY_HEADERS_02.SPEC_VERSION]]}; + throw { + message: "invalid spec version", + errors: [sanity_headers[Constants.BINARY_HEADERS_02.SPEC_VERSION]] + }; } // No erros! Its contains the minimum required attributes @@ -103,8 +114,13 @@ Receiver.prototype.parse = function(payload, headers) { } } + // Parses the payload + var parsedPayload = + parser_by_type[sanity_headers[Constants.HEADER_CONTENT_TYPE]] + .parse(payload); + // Sets the data - cloudevent.data(payload); + cloudevent.data(parsedPayload); // Checks the event spec cloudevent.format(); From 62e5404c0f3a9b006050d60e8ac2f820db781e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Fri, 21 Jun 2019 10:56:41 -0300 Subject: [PATCH 085/110] Remove the responsability of spec checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- test/formats/json/parser_test.js | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/test/formats/json/parser_test.js b/test/formats/json/parser_test.js index 41b6e75a..2c631d5a 100644 --- a/test/formats/json/parser_test.js +++ b/test/formats/json/parser_test.js @@ -66,10 +66,10 @@ describe("JSON Event Format Parser", () => { .to.throw("invalid json payload"); }); - it("Throw error when payload is an invalid CloudEvent spec 0.2", () => { + it("Must accept the CloudEvent spec 0.2 as JSON", () => { // setup var payload = - new Cloudevent() + new Cloudevent(Cloudevent.specs["0.2"]) .type(type) .source(source) .contenttype(ceContentType) @@ -80,24 +80,18 @@ describe("JSON Event Format Parser", () => { var parser = new Parser(); - // act and assert - expect(parser.parse.bind(parser, payload)) - .to.throw("invalid payload"); + // act + var actual = parser.parse(payload); + + // assert + expect(actual) + .to.be.an("object"); }); - it("Must accept the CloudEvent spec 0.2 as JSON", () => { + it("Must accept when the payload is a string well formed as JSON", () => { // setup - var payload = - new Cloudevent(Cloudevent.specs["0.2"]) - .type(type) - .source(source) - .contenttype(ceContentType) - .time(now) - .schemaurl(schemaurl) - .data(data) - .toString(); - - var parser = new Parser(new Cloudevent.specs["0.2"]()); + var payload = "{\"much\" : \"wow\"}"; + var parser = new Parser(); // act var actual = parser.parse(payload); From fea87aaee2c2169195110da706ad043876a6b536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Fri, 21 Jun 2019 10:58:05 -0300 Subject: [PATCH 086/110] Using the Spec to check the format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_structured_0_2.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/bindings/http/receiver_structured_0_2.js b/lib/bindings/http/receiver_structured_0_2.js index e5cacd38..dd7e044c 100644 --- a/lib/bindings/http/receiver_structured_0_2.js +++ b/lib/bindings/http/receiver_structured_0_2.js @@ -5,7 +5,8 @@ const Spec02 = require("../../specs/spec_0_2.js"); var JSONParser = require("../../formats/json/parser.js"); -const jsonParserSpec02 = new JSONParser(new Spec02()); +const spec02 = new Spec02(); +const jsonParserSpec02 = new JSONParser(); const parser_by_mime = {}; parser_by_mime[Constants.MIME_JSON] = jsonParserSpec02; @@ -56,9 +57,12 @@ Receiver.prototype.parse = function(payload, headers) { var contentType = sanity_headers[Constants.HEADER_CONTENT_TYPE]; var parser = parser_by_mime[contentType]; - + var cloudevent = parser.parse(payload); + // Must follow the spec + spec02.check(cloudevent); + return cloudevent; } From 365e0871b7c34fb6cc2b6cbf7382a962084c3834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Fri, 21 Jun 2019 16:42:55 -0300 Subject: [PATCH 087/110] Fix binary data attribute example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/payload/data-0.json | 4 +--- test/bindings/http/receiver_binary_0_2_tests.js | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/payload/data-0.json b/examples/payload/data-0.json index 91e844d7..c0119ee6 100644 --- a/examples/payload/data-0.json +++ b/examples/payload/data-0.json @@ -1,5 +1,3 @@ { - "data":{ - "much":"wow" - } + "much":"wow" } diff --git a/test/bindings/http/receiver_binary_0_2_tests.js b/test/bindings/http/receiver_binary_0_2_tests.js index ed2b1493..1323cba8 100644 --- a/test/bindings/http/receiver_binary_0_2_tests.js +++ b/test/bindings/http/receiver_binary_0_2_tests.js @@ -27,14 +27,14 @@ describe("HTTP Transport Binding Binary Receiver for CloudEvents v0.2", () => { .to.throw("attributes is null or undefined"); }); - it("Throw error when payload is not an object", () => { + it("Throw error when payload is not an object or string", () => { // setup - var payload = "wow"; + var payload = 1.2; var attributes = {}; // act and assert expect(receiver.check.bind(receiver, payload, attributes)) - .to.throw("payload must be an object"); + .to.throw("payload must be an object or a string"); }); it("Throw error when headers has no 'ce-type'", () => { From 5baa52dd2b5da12c3cd6e8f72e2209b5525f8278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Fri, 21 Jun 2019 16:43:25 -0300 Subject: [PATCH 088/110] Fix example body read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/express-ex/index.js | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/examples/express-ex/index.js b/examples/express-ex/index.js index b2c9a11a..ad993b07 100644 --- a/examples/express-ex/index.js +++ b/examples/express-ex/index.js @@ -1,13 +1,39 @@ -var express = require('express'); +var express = require("express"); var app = express(); -app.get('/', function (req, res) { +const Unmarshaller02 = require("cloudevents-sdk/http/unmarshaller/v02"); +var unmarshaller = new Unmarshaller02(); + +app.use((req, res, next) => { + var data=''; + + req.setEncoding('utf8'); + req.on('data', function(chunk) { + data += chunk; + }); + + req.on('end', function() { + req.body = data; + next(); + }); +}); + +app.post('/', function (req, res) { console.log(req.headers); console.log(req.body); - // TODO use the Unmarshaller - - res.send('Hello World!'); + try { + var event = unmarshaller.unmarshall(req.body, req.headers); + + res.status(201) + .send("Event Accepted"); + }catch(e) { + console.error(e); + + res.status(400) + .header("Content-Type", "application/json") + .send(JSON.stringify(e)); + } }); app.listen(3000, function () { From 99310d192058057e86662a09fe4c42d057897802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Fri, 21 Jun 2019 16:48:08 -0300 Subject: [PATCH 089/110] Fix binary example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/express-ex/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/express-ex/README.md b/examples/express-ex/README.md index 64be0d79..353fd248 100644 --- a/examples/express-ex/README.md +++ b/examples/express-ex/README.md @@ -23,11 +23,11 @@ __A Binary One__ curl -X POST \ -d'@../payload/data-0.json' \ -H'Content-Type:application/json' \ - -H'ce_specversion:0.2' \ - -H'ce_type:com.github.pull.create' \ - -H'ce_source:https://github.com/cloudevents/spec/pull/123' \ - -H'ce_id:45c83279-c8a1-4db6-a703-b3768db93887' \ - -H'ce_time:2019-06-21T17:31:00Z' \ + -H'ce-specversion:0.2' \ + -H'ce-type:com.github.pull.create' \ + -H'ce-source:https://github.com/cloudevents/spec/pull/123' \ + -H'ce-id:45c83279-c8a1-4db6-a703-b3768db93887' \ + -H'ce-time:2019-06-21T17:31:00Z' \ http://localhost:3000/ ``` __A Batch One__ From 7024876e49fd7bb13e37d369a24a06c358a52635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 10:30:25 -0300 Subject: [PATCH 090/110] Specversion placebo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/cloudevent.js | 4 ++++ lib/specs/spec_0_2.js | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/lib/cloudevent.js b/lib/cloudevent.js index d86ca3ae..4f05de35 100644 --- a/lib/cloudevent.js +++ b/lib/cloudevent.js @@ -43,6 +43,10 @@ Cloudevent.prototype.getType = function() { return this.spec.getType(); }; +Cloudevent.prototype.specversion = function(version) { + return this.spec.specversion(version); +}; + Cloudevent.prototype.getSpecversion = function() { return this.spec.getSpecversion(); }; diff --git a/lib/specs/spec_0_2.js b/lib/specs/spec_0_2.js index 489af96c..dfef99c8 100644 --- a/lib/specs/spec_0_2.js +++ b/lib/specs/spec_0_2.js @@ -53,6 +53,11 @@ Spec02.prototype.getType = function(){ return this.payload["type"]; }; +Spec02.prototype.specversion = function(_specversion){ + // does not set! This is right + return this; +}; + Spec02.prototype.getSpecversion = function() { return this.payload["specversion"]; }; From 67b3ac2b214e771d51cca294fbde779bb1d8b337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 10:42:26 -0300 Subject: [PATCH 091/110] Processing the extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_binary_0_2.js | 24 ++++++++++++++-- .../http/receiver_binary_0_2_tests.js | 28 +++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/lib/bindings/http/receiver_binary_0_2.js b/lib/bindings/http/receiver_binary_0_2.js index 9634c8ee..6d1abd22 100644 --- a/lib/bindings/http/receiver_binary_0_2.js +++ b/lib/bindings/http/receiver_binary_0_2.js @@ -22,6 +22,10 @@ setter_reflections[Constants.BINARY_HEADERS_02.TYPE] = { name : "type", parser : (v) => v }; +setter_reflections[Constants.BINARY_HEADERS_02.SPEC_VERSION] = { + name : "specversion", + parser : (v) => "0.2" +}; setter_reflections[Constants.BINARY_HEADERS_02.SOURCE] = { name : "source", parser: (v) => v @@ -102,6 +106,7 @@ Receiver.prototype.parse = function(payload, headers) { // Clone and low case all headers names var sanity_headers = Commons.sanity_and_clone(headers); + var processed_headers = []; var cloudevent = new Cloudevent(Spec02); for(header in setter_reflections) { // dont worry, check() have seen what was required or not @@ -111,16 +116,31 @@ Receiver.prototype.parse = function(payload, headers) { // invoke the setter function cloudevent[setter_name](parser_fn(sanity_headers[header])); + + // to use ahead, for extensions processing + processed_headers.push(header); } } // Parses the payload - var parsedPayload = + var parsed_payload = parser_by_type[sanity_headers[Constants.HEADER_CONTENT_TYPE]] .parse(payload); + // Every unprocessed header should be an extension + Array.from(Object.keys(sanity_headers)) + .filter(value => !processed_headers.includes(value)) + .filter(value => + value.startsWith(Constants.BINARY_HEADERS_02.EXTENSIONS_PREFIX)) + .map(extension => + extension.substring(Constants.BINARY_HEADERS_02.EXTENSIONS_PREFIX.length) + ).forEach(extension => + cloudevent.addExtension(extension, + sanity_headers[Constants.BINARY_HEADERS_02.EXTENSIONS_PREFIX+extension]) + ); + // Sets the data - cloudevent.data(parsedPayload); + cloudevent.data(parsed_payload); // Checks the event spec cloudevent.format(); diff --git a/test/bindings/http/receiver_binary_0_2_tests.js b/test/bindings/http/receiver_binary_0_2_tests.js index 1323cba8..85d79d17 100644 --- a/test/bindings/http/receiver_binary_0_2_tests.js +++ b/test/bindings/http/receiver_binary_0_2_tests.js @@ -353,6 +353,34 @@ describe("HTTP Transport Binding Binary Receiver for CloudEvents v0.2", () => { expect(actual) .to.be.an("object"); + expect(actual) + .to.have.property("format"); + }); + + it("Should accept 'extension1'", () => { + // setup + var extension1 = "mycuston-ext1"; + var payload = { + "data" : "dataString" + }; + var attributes = { + "ce-type" : "type", + "ce-specversion" : "0.2", + "ce-source" : "source", + "ce-id" : "id", + "ce-time" : "2019-06-16T11:42:00Z", + "ce-schemaurl" : "http://schema.registry/v1", + "Content-Type" : "application/json", + "ce-extension1" : extension1 + }; + + // act + var actual = receiver.parse(payload, attributes); + var actualExtensions = actual.getExtensions(); + + // assert + expect(actualExtensions["extension1"]) + .to.equal(extension1); }); }); }); From f96845a96396ae50265c0c03f6466769cd9c26ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 10:52:27 -0300 Subject: [PATCH 092/110] Fix the sanity logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/commons.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/bindings/http/commons.js b/lib/bindings/http/commons.js index 5b7dd605..e7e9a23f 100644 --- a/lib/bindings/http/commons.js +++ b/lib/bindings/http/commons.js @@ -1,8 +1,9 @@ function sanity_and_clone(headers) { - var sanity_headers = JSON.parse(JSON.stringify(headers)); + //var sanity_headers = JSON.parse(JSON.stringify(headers)); + var sanity_headers = {}; - for(header in sanity_headers){ - sanity_headers[header.toLowerCase()] = sanity_headers[header]; + for(header in headers){ + sanity_headers[header.toLowerCase()] = headers[header]; } return sanity_headers; From 2cb26395ebd1bcfca992c86e254acb0f1b26d57c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 10:52:55 -0300 Subject: [PATCH 093/110] Add structured attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/constants.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/bindings/http/constants.js b/lib/bindings/http/constants.js index 6097bb0c..aa4f5c0f 100644 --- a/lib/bindings/http/constants.js +++ b/lib/bindings/http/constants.js @@ -16,5 +16,16 @@ module.exports = { TIME : "ce-time", SCHEMA_URL : "ce-schemaurl", EXTENSIONS_PREFIX : "ce-" + }, + + STRUCTURED_ATTRS_02 : { + TYPE : "type", + SPEC_VERSION : "specversion", + SOURCE : "source", + ID : "id", + TIME : "time", + SCHEMA_URL : "schemaurl", + CONTENT_TYPE : "contenttype", + DATA : "data" } }; From f850c9a4a38b71a9852937b7f8b19d56e7cec930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 10:53:44 -0300 Subject: [PATCH 094/110] Extension processing and cloudevent right parse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/receiver_structured_0_2.js | 69 ++++++++++++++++++-- 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/lib/bindings/http/receiver_structured_0_2.js b/lib/bindings/http/receiver_structured_0_2.js index dd7e044c..773cde78 100644 --- a/lib/bindings/http/receiver_structured_0_2.js +++ b/lib/bindings/http/receiver_structured_0_2.js @@ -15,6 +15,40 @@ parser_by_mime[Constants.MIME_CE_JSON] = jsonParserSpec02; const allowed_content_types = []; allowed_content_types.push(Constants.MIME_CE_JSON); +const setter_reflections = {}; +setter_reflections[Constants.STRUCTURED_ATTRS_02.TYPE] = { + name : "type", + parser : (v) => v +}; +setter_reflections[Constants.STRUCTURED_ATTRS_02.SPEC_VERSION] = { + name : "specversion", + parser : (v) => v +}; +setter_reflections[Constants.STRUCTURED_ATTRS_02.SOURCE] = { + name : "source", + parser: (v) => v +}; +setter_reflections[Constants.STRUCTURED_ATTRS_02.ID] = { + name : "id", + parser : (v) => v +}; +setter_reflections[Constants.STRUCTURED_ATTRS_02.TIME] = { + name : "time", + parser : (v) => new Date(Date.parse(v)) +}; +setter_reflections[Constants.STRUCTURED_ATTRS_02.SCHEMA_URL] = { + name: "schemaurl", + parser: (v) => v +}; +setter_reflections[Constants.STRUCTURED_ATTRS_02.CONTENT_TYPE] = { + name: "contenttype", + parser: (v) => v +}; +setter_reflections[Constants.STRUCTURED_ATTRS_02.DATA] = { + name: "data", + parser: (v) => v +}; + function validate_args(payload, attributes) { if(!payload){ throw {message: "payload is null or undefined"}; @@ -25,8 +59,10 @@ function validate_args(payload, attributes) { } if((typeof payload) !== "object" && (typeof payload) !== "string"){ - throw {message: "payload must be an object or string", - erros: [typeof payload]}; + throw { + message: "payload must be an object or string", + errors: [typeof payload] + }; } } @@ -42,8 +78,10 @@ Receiver.prototype.check = function(payload, headers) { // Validation Level 1 if(!allowed_content_types .includes(sanity_headers[Constants.HEADER_CONTENT_TYPE])){ - throw {message: "invalid content type", - errors: [sanity_headers[Constants.HEADER_CONTENT_TYPE]]}; + throw { + message: "invalid content type", + errors: [sanity_headers[Constants.HEADER_CONTENT_TYPE]] + }; } // No erros! Its contains the minimum required attributes @@ -57,11 +95,28 @@ Receiver.prototype.parse = function(payload, headers) { var contentType = sanity_headers[Constants.HEADER_CONTENT_TYPE]; var parser = parser_by_mime[contentType]; + var event = parser.parse(payload); + spec02.check(event); + + var processed_attributes = []; + var cloudevent = new Cloudevent(Spec02); + for(attribute in setter_reflections) { + var setter_name = setter_reflections[attribute].name; + var parser_fn = setter_reflections[attribute].parser; - var cloudevent = parser.parse(payload); + // invoke the setter function + cloudevent[setter_name](parser_fn(event[attribute])); + + // to use ahead, for extensions processing + processed_attributes.push(attribute); + } - // Must follow the spec - spec02.check(cloudevent); + // Every unprocessed attribute should be an extension + Array.from(Object.keys(event)) + .filter(attribute => !processed_attributes.includes(attribute)) + .forEach(extension => + cloudevent.addExtension(extension, event[extension]) + ); return cloudevent; } From 3f50e71953c9d483dd7b7759c32bd0f8b4c358d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 10:54:03 -0300 Subject: [PATCH 095/110] Test the extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- .../http/receiver_strutured_0_2_test.js | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/test/bindings/http/receiver_strutured_0_2_test.js b/test/bindings/http/receiver_strutured_0_2_test.js index 25eb9f6b..4f5b41e5 100644 --- a/test/bindings/http/receiver_strutured_0_2_test.js +++ b/test/bindings/http/receiver_strutured_0_2_test.js @@ -117,16 +117,17 @@ describe("HTTP Transport Binding Structured Receiver for CloudEvents v0.2", () = it("Should accept event that follow the spec 0.2", () => { // setup + var id = "id-x0dk"; var payload = new Cloudevent(Cloudevent.specs["0.2"]) .type(type) .source(source) + .id(id) .contenttype(ceContentType) .time(now) .schemaurl(schemaurl) .data(data) .toString(); - var headers = { "content-type":"application/cloudevents+json" }; @@ -137,6 +138,39 @@ describe("HTTP Transport Binding Structured Receiver for CloudEvents v0.2", () = // assert expect(actual) .to.be.an("object"); + + expect(actual) + .to.have.property("format"); + + expect(actual.getId()) + .to.equals(id); + }); + + it("Should accept 'extension1'", () => { + // setup + var extension1 = "mycuston-ext1" + var payload = + new Cloudevent(Cloudevent.specs["0.2"]) + .type(type) + .source(source) + .contenttype(ceContentType) + .time(now) + .schemaurl(schemaurl) + .data(data) + .addExtension("extension1", extension1) + .toString(); + + var headers = { + "content-type":"application/cloudevents+json" + }; + + // act + var actual = receiver.parse(payload, headers); + var actualExtensions = actual.getExtensions(); + + // assert + expect(actualExtensions["extension1"]) + .to.equal(extension1); }); }); }); From 6c5b7e2c86c3a9c493ab6e3b3204a373c4b928a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 10:54:39 -0300 Subject: [PATCH 096/110] When incorrect, reply the errors too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/express-ex/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/express-ex/index.js b/examples/express-ex/index.js index ad993b07..2b5e783d 100644 --- a/examples/express-ex/index.js +++ b/examples/express-ex/index.js @@ -25,6 +25,10 @@ app.post('/', function (req, res) { try { var event = unmarshaller.unmarshall(req.body, req.headers); + // pretty print + console.log("Accepted event:"); + console.log(JSON.stringify(event.format(), null, 2)); + res.status(201) .send("Event Accepted"); }catch(e) { From b39a32152fff669b8f5c608cca8ad528cf1e19d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 11:02:14 -0300 Subject: [PATCH 097/110] Double quotes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/express-ex/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/express-ex/index.js b/examples/express-ex/index.js index 2b5e783d..b612d4b5 100644 --- a/examples/express-ex/index.js +++ b/examples/express-ex/index.js @@ -41,5 +41,5 @@ app.post('/', function (req, res) { }); app.listen(3000, function () { - console.log('Example app listening on port 3000!'); + console.log("Example app listening on port 3000!"); }); From b12c6d75d4bc71279d029b546540b44af2f76a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 11:05:00 -0300 Subject: [PATCH 098/110] fix type, ex with extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/express-ex/README.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/examples/express-ex/README.md b/examples/express-ex/README.md index 353fd248..1d166bc2 100644 --- a/examples/express-ex/README.md +++ b/examples/express-ex/README.md @@ -1,12 +1,12 @@ # Express Example -## To Start +## How To Start ```bash npm start ``` -## To Post an Event +## How To Post an Event __A Structured One__ @@ -30,6 +30,22 @@ curl -X POST \ -H'ce-time:2019-06-21T17:31:00Z' \ http://localhost:3000/ ``` + +__A Binary One with Extension__ + +```bash +curl -X POST \ + -d'@../payload/data-0.json' \ + -H'Content-Type:application/json' \ + -H'ce-specversion:0.2' \ + -H'ce-type:com.github.pull.create' \ + -H'ce-source:https://github.com/cloudevents/spec/pull/123' \ + -H'ce-id:45c83279-c8a1-4db6-a703-b3768db93887' \ + -H'ce-time:2019-06-21T17:31:00Z' \ + -H'ce-my-extension:extension value' \ + http://localhost:3000/ +``` + __A Batch One__ TODO From 1497934bedee6b65e6f80289d08f4d16c5eb639b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 11:07:56 -0300 Subject: [PATCH 099/110] Example of payload with extenstion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/payload/v02/structured-event-1.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 examples/payload/v02/structured-event-1.json diff --git a/examples/payload/v02/structured-event-1.json b/examples/payload/v02/structured-event-1.json new file mode 100644 index 00000000..f69eed44 --- /dev/null +++ b/examples/payload/v02/structured-event-1.json @@ -0,0 +1,14 @@ +{ + "specversion":"0.2", + "type":"com.github.pull.create", + "source":"https://github.com/cloudevents/spec/pull/123", + "id":"45c83279-c8a1-4db6-a703-b3768db93887", + "time":"2019-06-21T17:31:00Z", + "contenttype":"application/json", + "data":{ + "much":"wow" + }, + "my-extension" : { + "some" : "thing" + } +} From c7341baf961e1dcc9f87b2c9e9db63dcca793a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 11:08:09 -0300 Subject: [PATCH 100/110] Example for structured with extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/express-ex/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/examples/express-ex/README.md b/examples/express-ex/README.md index 1d166bc2..132864bd 100644 --- a/examples/express-ex/README.md +++ b/examples/express-ex/README.md @@ -10,6 +10,8 @@ npm start __A Structured One__ +> Payload [example](../payload/v02/structured-event-0.json) + ```bash curl -X POST \ -d'@../payload/v02/structured-event-0.json' \ @@ -17,6 +19,17 @@ curl -X POST \ http://localhost:3000/ ``` +__A Structured One with Extension__ + +> Payload [example](../payload/v02/structured-event-1.json) + +```bash +curl -X POST \ + -d'@../payload/v02/structured-event-1.json' \ + -H'Content-Type:application/cloudevents+json' \ + http://localhost:3000/ +``` + __A Binary One__ ```bash From a9962d76ecfe9cd643c802aa2ab2ffdb07fb0996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 11:10:13 -0300 Subject: [PATCH 101/110] Fix example anchor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 647e0234..005f3eb2 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Before create an awesome PR, please read our [guidelines](./CONTRIBUTING.md). ## Examples -To see working examples, point to [examples](./examplpes). +To see working examples, point to [examples](./examples). ## Versioning From 038c786e6c9956f3371a958614f2407666181caa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 11:17:37 -0300 Subject: [PATCH 102/110] Document the use of unmarshaller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 005f3eb2..e7a94cb1 100644 --- a/README.md +++ b/README.md @@ -168,14 +168,41 @@ binding.emit(cloudevent) console.error(err); }); ``` -#### Receiving Events Using Express +#### Receiving Events -See how to listen to events using -[express](https://github.com/expressjs/express). +You can choose any http framework for port binding, but use the Unmarshaller +to process the HTTP Payload and HTTP Headers to extract the CloudEvents. + +__Checkout the full working example [here](./examples/express-ex)__ ```js +// some parts weres removed // + var Unmarshaller02 = require("cloudevents-sdk/http/unmarshaller/v02"); +// some parts were removed // + +app.post('/', function (req, res) { + try { + // Using the Unmarshaller + var cloudevent = + unmarshaller.unmarshall(req.body, req.headers); + + // pretty print + console.log("Event Accepted:"); + + res.status(201) + .send("Event Accepted"); + }catch(e) { + console.error(e); + + res.status(400) + .header("Content-Type", "application/json") + .send(JSON.stringify(e)); + } +}); + + ``` ## Repository Structure From c0cd46de098e63a97114827ed32d1eecebb48080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 11:23:01 -0300 Subject: [PATCH 103/110] Fix type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e7a94cb1..c7c2ff50 100644 --- a/README.md +++ b/README.md @@ -170,13 +170,13 @@ binding.emit(cloudevent) ``` #### Receiving Events -You can choose any http framework for port binding, but use the Unmarshaller -to process the HTTP Payload and HTTP Headers to extract the CloudEvents. +You can choose any http framework for port binding. But, use the Unmarshaller +to process the HTTP Payload and HTTP Headers, extracting the CloudEvents. -__Checkout the full working example [here](./examples/express-ex)__ +__:smiley: Checkout the full working example [here](./examples/express-ex)__ ```js -// some parts weres removed // +// some parts were removed // var Unmarshaller02 = require("cloudevents-sdk/http/unmarshaller/v02"); From 542efe2a6c3771e54c99a54a30b4d5a849c470e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 11:24:09 -0300 Subject: [PATCH 104/110] Fix type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c7c2ff50..490d8006 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ binding.emit(cloudevent) You can choose any http framework for port binding. But, use the Unmarshaller to process the HTTP Payload and HTTP Headers, extracting the CloudEvents. -__:smiley: Checkout the full working example [here](./examples/express-ex)__ +__:smiley: Checkout the full working example: [here](./examples/express-ex).__ ```js // some parts were removed // From 335531745f93d6bcc3513117d18bc7cf4cbeb42d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 12:01:33 -0300 Subject: [PATCH 105/110] Apply promise in the unmarshaller impl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- lib/bindings/http/unmarshaller_0_2.js | 28 ++++---- test/bindings/http/unmarshaller_0_2_tests.js | 67 ++++++++++++-------- 2 files changed, 57 insertions(+), 38 deletions(-) diff --git a/lib/bindings/http/unmarshaller_0_2.js b/lib/bindings/http/unmarshaller_0_2.js index 11080868..27b05901 100644 --- a/lib/bindings/http/unmarshaller_0_2.js +++ b/lib/bindings/http/unmarshaller_0_2.js @@ -54,22 +54,28 @@ var Unmarshaller = function() { } Unmarshaller.prototype.unmarshall = function(payload, headers) { - validate_args(payload, headers); + return new Promise((resolve, reject) => { + try { + validate_args(payload, headers); - var sanity_headers = Commons.sanity_and_clone(headers); + var sanity_headers = Commons.sanity_and_clone(headers); - // Validation level 1 - if(!sanity_headers[Constants.HEADER_CONTENT_TYPE]){ - throw {message: "content-type header not found"}; - } + // Validation level 1 + if(!sanity_headers[Constants.HEADER_CONTENT_TYPE]){ + throw {message: "content-type header not found"}; + } - // Resolve the binding - var binding_name = resolve_binding_name(payload, sanity_headers); + // Resolve the binding + var binding_name = resolve_binding_name(payload, sanity_headers); - var cloudevent = - receiver_by_binding[binding_name].parse(payload, sanity_headers); + var cloudevent = + receiver_by_binding[binding_name].parse(payload, sanity_headers); - return cloudevent; + resolve(cloudevent); + }catch(e){ + reject(e); + } + }); } module.exports = Unmarshaller; diff --git a/test/bindings/http/unmarshaller_0_2_tests.js b/test/bindings/http/unmarshaller_0_2_tests.js index 08469160..17df61f9 100644 --- a/test/bindings/http/unmarshaller_0_2_tests.js +++ b/test/bindings/http/unmarshaller_0_2_tests.js @@ -23,8 +23,10 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.2", () => { var un = new Unmarshaller(); // act and assert - expect(un.unmarshall.bind(un, payload)) - .to.throw("payload is null or undefined"); + return un.unmarshall(payload) + .then(actual => {throw {message: "failed"}}) + .catch(err => + expect(err.message).to.equal("payload is null or undefined")); }); it("Throw error when headers is null", () => { @@ -34,8 +36,10 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.2", () => { var un = new Unmarshaller(); // act and assert - expect(un.unmarshall.bind(un, payload, headers)) - .to.throw("headers is null or undefined"); + return un.unmarshall(payload, headers) + .then(actual => {throw {message: "failed"}}) + .catch(err => + expect(err.message).to.equal("headers is null or undefined")); }); it("Throw error when there is no content-type header", () => { @@ -45,8 +49,10 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.2", () => { var un = new Unmarshaller(); // act and assert - expect(un.unmarshall.bind(un, payload, headers)) - .to.throw("content-type header not found"); + un.unmarshall(payload, headers) + .then(actual => {throw {message: "failed"}}) + .catch(err => + expect(err.message).to.equal("content-type header not found")); }); it("Throw error when content-type is not allowed", () => { @@ -58,8 +64,10 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.2", () => { var un = new Unmarshaller(); // act and assert - expect(un.unmarshall.bind(un, payload, headers)) - .to.throw("content type not allowed"); + un.unmarshall(payload, headers) + .then(actual => {throw {message: "failed"}}) + .catch(err => + expect(err.message).to.equal("content type not allowed")); }); describe("Structured", () => { @@ -72,8 +80,10 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.2", () => { var un = new Unmarshaller(); // act and assert - expect(un.unmarshall.bind(un, payload, headers)) - .to.throw("structured+type not allowed"); + un.unmarshall(payload, headers) + .then(actual => {throw {message: "failed"}}) + .catch(err => + expect(err.message).to.equal("structured+type not allowed")); }); it("Throw error when the event does not follow the spec 0.2", () => { @@ -95,8 +105,10 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.2", () => { var un = new Unmarshaller(); // act and assert - expect(un.unmarshall.bind(un, payload, headers)) - .to.throw("invalid payload"); + un.unmarshall(payload, headers) + .then(actual => {throw {message: "failed"}}) + .catch(err => + expect(err.message).to.equal("invalid payload")); }); it("Should accept event that follow the spec 0.2", () => { @@ -117,12 +129,11 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.2", () => { var un = new Unmarshaller(); - // act - var actual = un.unmarshall(payload, headers); + // act and assert + un.unmarshall(payload, headers) + .then(actual => + expect(actual).to.be.an("object")); - // assert - expect(actual) - .to.be.an("object"); }); }); @@ -145,8 +156,11 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.2", () => { var un = new Unmarshaller(); // act and assert - expect(un.unmarshall.bind(un, payload, attributes)) - .to.throw("content type not allowed"); + un.unmarshall(payload, attributes) + .then(actual => {throw {message: "failed"}}) + .catch(err => + expect(err.message).to.equal("content type not allowed")); + }); it("Throw error when the event does not follow the spec 0.2", () => { @@ -167,8 +181,10 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.2", () => { var un = new Unmarshaller(); // act and assert - expect(un.unmarshall.bind(un, payload, attributes)) - .to.throw(); + un.unmarshall(payload, attributes) + .then(actual => {throw {message: "failed"}}) + .catch(err => + expect(err.message).to.not.empty()); }); it("No error when all attributes are in place", () => { @@ -188,12 +204,9 @@ describe("HTTP Transport Binding Unmarshaller for CloudEvents v0.2", () => { var un = new Unmarshaller(); - // act - var actual = un.unmarshall(payload, attributes); - - // assert - expect(actual) - .to.be.an("object"); + // act and assert + un.unmarshall(payload, attributes) + .then(actual => expect(actual).to.be.an("object")); }); }); From e1b04bdcdbba5abb3ebf6f12e07d2a9de3a4b498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 12:05:02 -0300 Subject: [PATCH 106/110] Change to use promise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/express-ex/index.js | 28 ++++++++++++++-------------- examples/express-ex/package.json | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/examples/express-ex/index.js b/examples/express-ex/index.js index b612d4b5..b18a32d4 100644 --- a/examples/express-ex/index.js +++ b/examples/express-ex/index.js @@ -22,22 +22,22 @@ app.post('/', function (req, res) { console.log(req.headers); console.log(req.body); - try { - var event = unmarshaller.unmarshall(req.body, req.headers); - - // pretty print - console.log("Accepted event:"); - console.log(JSON.stringify(event.format(), null, 2)); - - res.status(201) - .send("Event Accepted"); - }catch(e) { - console.error(e); - + unmarshaller.unmarshall(req.body, req.headers) + .then(event => { + // pretty print + console.log("Accepted event:"); + console.log(JSON.stringify(event.format(), null, 2)); + + res.status(201) + .send("Event Accepted"); + }) + .catch(err => { + console.error(err); res.status(400) .header("Content-Type", "application/json") - .send(JSON.stringify(e)); - } + .send(JSON.stringify(err)); + }); + }); app.listen(3000, function () { diff --git a/examples/express-ex/package.json b/examples/express-ex/package.json index 71fc7e8d..9845276c 100644 --- a/examples/express-ex/package.json +++ b/examples/express-ex/package.json @@ -15,6 +15,6 @@ "license": "Apache-2.0", "dependencies": { "express": "^4.17.1", - "cloudevents-sdk": "cloudevents/sdk-javascript#receive" + "cloudevents-sdk": "cloudevents/sdk-javascript#develop" } } From 852cad08323392a66e496d798f927bb3f114968f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 12:08:04 -0300 Subject: [PATCH 107/110] Fix the examples and use the same names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- examples/express-ex/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/express-ex/index.js b/examples/express-ex/index.js index b18a32d4..025fa2b7 100644 --- a/examples/express-ex/index.js +++ b/examples/express-ex/index.js @@ -23,10 +23,10 @@ app.post('/', function (req, res) { console.log(req.body); unmarshaller.unmarshall(req.body, req.headers) - .then(event => { + .then(cloudevent => { // pretty print console.log("Accepted event:"); - console.log(JSON.stringify(event.format(), null, 2)); + console.log(JSON.stringify(cloudevent.format(), null, 2)); res.status(201) .send("Event Accepted"); From fb58f9c210a54392be4bf31393240bf49add03bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 12:08:20 -0300 Subject: [PATCH 108/110] Fix the examples and use the same names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 490d8006..1958142b 100644 --- a/README.md +++ b/README.md @@ -183,23 +183,20 @@ var Unmarshaller02 = require("cloudevents-sdk/http/unmarshaller/v02"); // some parts were removed // app.post('/', function (req, res) { - try { - // Using the Unmarshaller - var cloudevent = - unmarshaller.unmarshall(req.body, req.headers); + unmarshaller.unmarshall(req.body, req.headers) + .then(cloudevent => { - // pretty print - console.log("Event Accepted:"); - - res.status(201) - .send("Event Accepted"); - }catch(e) { - console.error(e); + // TODO use the cloudevent + res.status(201) + .send("Event Accepted"); + }) + .catch(err => { + console.error(err); res.status(400) .header("Content-Type", "application/json") - .send(JSON.stringify(e)); - } + .send(JSON.stringify(err)); + }); }); From cc1af54a8a8d579b0e4daf66fbad9dc53ac19768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 12:34:37 -0300 Subject: [PATCH 109/110] Doc clarifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1958142b..69e5169a 100644 --- a/README.md +++ b/README.md @@ -170,9 +170,12 @@ binding.emit(cloudevent) ``` #### Receiving Events -You can choose any http framework for port binding. But, use the Unmarshaller +You can choose any framework for port binding. But, use the Unmarshaller to process the HTTP Payload and HTTP Headers, extracting the CloudEvents. +The Unmarshaller will parse the HTTP Request and decides if it is a binary +or a structured version of transport binding. + __:smiley: Checkout the full working example: [here](./examples/express-ex).__ ```js From 06fc7887184d383f5e21fa05a6699fb0393f1485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabio=20Jos=C3=A9?= Date: Tue, 25 Jun 2019 12:43:04 -0300 Subject: [PATCH 110/110] Set version to 0.2.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabio José --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8a472d67..2c85beea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudevents-sdk", - "version": "0.2.1", + "version": "0.2.2", "description": "CloudEvents SDK for JavaScript", "main": "index.js", "scripts": {