generic HTTPUnmarshaller and spec 0.3 HTTPUnmarshaller
Signed-off-by: Fabio José <fabiojose@gmail.com>
This commit is contained in:
parent
9066741b8e
commit
5ea47c1f4a
|
@ -0,0 +1,84 @@
|
|||
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 receiverByBinding = {
|
||||
structured : new StructuredReceiver(),
|
||||
binary : new BinaryReceiver(),
|
||||
};
|
||||
|
||||
const allowedBinaryContentTypes = [];
|
||||
allowedBinaryContentTypes.push(Constants.MIME_JSON);
|
||||
allowedBinaryContentTypes.push(Constants.MIME_OCTET_STREAM);
|
||||
|
||||
const allowedStructuredContentTypes = [];
|
||||
allowedStructuredContentTypes.push(Constants.MIME_CE_JSON);
|
||||
|
||||
function validateArgs(payload, headers) {
|
||||
if(!payload){
|
||||
throw {message: "payload is null or undefined"};
|
||||
}
|
||||
|
||||
if(!headers){
|
||||
throw {message: "headers is null or undefined"};
|
||||
}
|
||||
}
|
||||
|
||||
// Is it binary or structured?
|
||||
function resolveBindingName(payload, headers) {
|
||||
|
||||
var contentType =
|
||||
Commons.sanityContentType(headers[Constants.HEADER_CONTENT_TYPE]);
|
||||
|
||||
if(contentType.startsWith(Constants.MIME_CE)){
|
||||
// Structured
|
||||
if(allowedStructuredContentTypes.includes(contentType)){
|
||||
return STRUCTURED;
|
||||
} else {
|
||||
throw {message: "structured+type not allowed", errors: [contentType]};
|
||||
}
|
||||
} else {
|
||||
// Binary
|
||||
if(allowedBinaryContentTypes.includes(contentType)){
|
||||
return BINARY;
|
||||
} else {
|
||||
throw {message: "content type not allowed", errors : [contentType]};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var Unmarshaller = function(receiverByBinding) {
|
||||
this.receiverByBinding = receiverByBinding;
|
||||
};
|
||||
|
||||
Unmarshaller.prototype.unmarshall = function(payload, headers) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
validateArgs(payload, headers);
|
||||
|
||||
var sanityHeaders = Commons.sanityAndClone(headers);
|
||||
|
||||
// Validation level 1
|
||||
if(!sanityHeaders[Constants.HEADER_CONTENT_TYPE]){
|
||||
throw {message: "content-type header not found"};
|
||||
}
|
||||
|
||||
// Resolve the binding
|
||||
var bindingName = resolveBindingName(payload, sanityHeaders);
|
||||
|
||||
var cloudevent =
|
||||
this.receiverByBinding[bindingName].parse(payload, sanityHeaders);
|
||||
|
||||
resolve(cloudevent);
|
||||
}catch(e){
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = Unmarshaller;
|
|
@ -0,0 +1,19 @@
|
|||
const GenericUnmarshaller = require("./unmarshaller.js");
|
||||
|
||||
var StructuredReceiver = require("./receiver_structured_0_3.js");
|
||||
var BinaryReceiver = require("./receiver_binary_0_3.js");
|
||||
|
||||
const RECEIVER_BY_BINDING = {
|
||||
structured : new StructuredReceiver(),
|
||||
binary : new BinaryReceiver(),
|
||||
};
|
||||
|
||||
var Unmarshaller = function() {
|
||||
this.unmarshaller = new GenericUnmarshaller(RECEIVER_BY_BINDING);
|
||||
};
|
||||
|
||||
Unmarshaller.prototype.unmarshall = function(payload, headers) {
|
||||
return this.unmarshaller.unmarshall(payload, headers);
|
||||
};
|
||||
|
||||
module.exports = Unmarshaller;
|
|
@ -0,0 +1,214 @@
|
|||
var expect = require("chai").expect;
|
||||
var Unmarshaller = require("../../../lib/bindings/http/unmarshaller_0_3.js");
|
||||
var Cloudevent = require("../../../index.js");
|
||||
var {Spec03} = require("../../../v03/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 for CloudEvents v0.3", () => {
|
||||
|
||||
it("Throw error when payload is null", () => {
|
||||
// setup
|
||||
var payload = null;
|
||||
var un = new Unmarshaller();
|
||||
|
||||
// act and assert
|
||||
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", () => {
|
||||
// setup
|
||||
var payload = {};
|
||||
var headers = null;
|
||||
var un = new Unmarshaller();
|
||||
|
||||
// act and assert
|
||||
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", () => {
|
||||
// setup
|
||||
var payload = {};
|
||||
var headers = {};
|
||||
var un = new Unmarshaller();
|
||||
|
||||
// act and assert
|
||||
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", () => {
|
||||
// setup
|
||||
var payload = {};
|
||||
var headers = {
|
||||
"content-type":"text/xml"
|
||||
};
|
||||
var un = new Unmarshaller();
|
||||
|
||||
// act and assert
|
||||
un.unmarshall(payload, headers)
|
||||
.then(actual => {throw {message: "failed"}})
|
||||
.catch(err =>
|
||||
expect(err.message).to.equal("content type not allowed"));
|
||||
});
|
||||
|
||||
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
|
||||
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.3", () => {
|
||||
// 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
|
||||
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.3", () => {
|
||||
// setup
|
||||
var payload =
|
||||
new Cloudevent(Spec03)
|
||||
.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
|
||||
un.unmarshall(payload, headers)
|
||||
.then(actual =>
|
||||
expect(actual).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.3",
|
||||
"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
|
||||
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.3", () => {
|
||||
// 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
|
||||
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", () => {
|
||||
// setup
|
||||
var payload = {
|
||||
"data" : "dataString"
|
||||
};
|
||||
var attributes = {
|
||||
"ce-type" : "type",
|
||||
"ce-specversion" : "0.3",
|
||||
"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
|
||||
un.unmarshall(payload, attributes)
|
||||
.then(actual => expect(actual).to.be.an("object"));
|
||||
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue