Http receiver binary for spec 1.0
Signed-off-by: Fabio José <fabiojose@gmail.com>
This commit is contained in:
parent
7d8ef84365
commit
645001af0f
|
@ -0,0 +1,106 @@
|
||||||
|
const Constants = require("./constants.js");
|
||||||
|
const Spec = require("../../specs/spec_1.js");
|
||||||
|
|
||||||
|
const JSONParser = require("../../formats/json/parser.js");
|
||||||
|
const Base64Parser = require("../../formats/base64.js");
|
||||||
|
|
||||||
|
const BinaryHTTPReceiver = require("./receiver_binary.js");
|
||||||
|
|
||||||
|
const {
|
||||||
|
isDefinedOrThrow,
|
||||||
|
isStringOrObjectOrThrow
|
||||||
|
} = require("../../utils/fun.js");
|
||||||
|
|
||||||
|
const parserByType = {};
|
||||||
|
parserByType[Constants.MIME_JSON] = new JSONParser();
|
||||||
|
parserByType[Constants.MIME_OCTET_STREAM] = {
|
||||||
|
parse(payload) { return payload; }
|
||||||
|
};
|
||||||
|
|
||||||
|
const parsersByEncoding = {};
|
||||||
|
parsersByEncoding[null] = parserByType;
|
||||||
|
parsersByEncoding[undefined] = parserByType;
|
||||||
|
|
||||||
|
// base64
|
||||||
|
parsersByEncoding[Constants.ENCODING_BASE64] = {};
|
||||||
|
parsersByEncoding[Constants.ENCODING_BASE64][Constants.MIME_JSON] =
|
||||||
|
new JSONParser(new Base64Parser());
|
||||||
|
parsersByEncoding[Constants.ENCODING_BASE64][Constants.MIME_OCTET_STREAM] = {
|
||||||
|
parse(payload) { return payload; }
|
||||||
|
};
|
||||||
|
|
||||||
|
const allowedContentTypes = [];
|
||||||
|
allowedContentTypes.push(Constants.MIME_JSON);
|
||||||
|
allowedContentTypes.push(Constants.MIME_OCTET_STREAM);
|
||||||
|
|
||||||
|
const allowedEncodings = [];
|
||||||
|
allowedEncodings.push(Constants.ENCODING_BASE64);
|
||||||
|
|
||||||
|
const requiredHeaders = [];
|
||||||
|
requiredHeaders.push(Constants.BINARY_HEADERS_1.TYPE);
|
||||||
|
requiredHeaders.push(Constants.BINARY_HEADERS_1.SPEC_VERSION);
|
||||||
|
requiredHeaders.push(Constants.BINARY_HEADERS_1.SOURCE);
|
||||||
|
requiredHeaders.push(Constants.BINARY_HEADERS_1.ID);
|
||||||
|
|
||||||
|
const setterByHeader = {};
|
||||||
|
setterByHeader[Constants.BINARY_HEADERS_1.TYPE] = {
|
||||||
|
name : "type",
|
||||||
|
parser : (v) => v
|
||||||
|
};
|
||||||
|
setterByHeader[Constants.BINARY_HEADERS_1.SPEC_VERSION] = {
|
||||||
|
name : "specversion",
|
||||||
|
parser : (v) => "1.0"
|
||||||
|
};
|
||||||
|
setterByHeader[Constants.BINARY_HEADERS_1.SOURCE] = {
|
||||||
|
name : "source",
|
||||||
|
parser: (v) => v
|
||||||
|
};
|
||||||
|
setterByHeader[Constants.BINARY_HEADERS_1.ID] = {
|
||||||
|
name : "id",
|
||||||
|
parser : (v) => v
|
||||||
|
};
|
||||||
|
setterByHeader[Constants.BINARY_HEADERS_1.TIME] = {
|
||||||
|
name : "time",
|
||||||
|
parser : (v) => new Date(Date.parse(v))
|
||||||
|
};
|
||||||
|
setterByHeader[Constants.BINARY_HEADERS_1.DATA_SCHEMA] = {
|
||||||
|
name: "dataschema",
|
||||||
|
parser: (v) => v
|
||||||
|
};
|
||||||
|
setterByHeader[Constants.HEADER_CONTENT_TYPE] = {
|
||||||
|
name: "dataContentType",
|
||||||
|
parser: (v) => v
|
||||||
|
};
|
||||||
|
setterByHeader[Constants.BINARY_HEADERS_1.SUBJECT] = {
|
||||||
|
name: "subject",
|
||||||
|
parser: (v) => v
|
||||||
|
};
|
||||||
|
|
||||||
|
function checkDecorator(payload, headers) {
|
||||||
|
}
|
||||||
|
|
||||||
|
function Receiver(configuration) {
|
||||||
|
this.receiver = new BinaryHTTPReceiver(
|
||||||
|
parsersByEncoding,
|
||||||
|
setterByHeader,
|
||||||
|
allowedContentTypes,
|
||||||
|
requiredHeaders,
|
||||||
|
Spec,
|
||||||
|
Constants.SPEC_V1,
|
||||||
|
Constants.BINARY_HEADERS_1.EXTENSIONS_PREFIX,
|
||||||
|
checkDecorator
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Receiver.prototype.check = function(payload, headers) {
|
||||||
|
this.receiver.check(payload, headers);
|
||||||
|
};
|
||||||
|
|
||||||
|
Receiver.prototype.parse = function(payload, headers) {
|
||||||
|
// firstly specific local checks
|
||||||
|
this.check(payload, headers);
|
||||||
|
|
||||||
|
return this.receiver.parse(payload, headers);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Receiver;
|
|
@ -0,0 +1,428 @@
|
||||||
|
var expect = require("chai").expect;
|
||||||
|
|
||||||
|
var HTTPBinaryReceiver =
|
||||||
|
require("../../../lib/bindings/http/receiver_binary_1.js");
|
||||||
|
|
||||||
|
var receiver = new HTTPBinaryReceiver();
|
||||||
|
|
||||||
|
describe("HTTP Transport Binding Binary Receiver for CloudEvents v1.0", () => {
|
||||||
|
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 or string", () => {
|
||||||
|
// setup
|
||||||
|
var payload = 1.2;
|
||||||
|
var attributes = {};
|
||||||
|
|
||||||
|
// act and assert
|
||||||
|
expect(receiver.check.bind(receiver, payload, attributes))
|
||||||
|
.to.throw("payload must be an object or a string");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Throw error when headers has no 'ce-type'", () => {
|
||||||
|
// setup
|
||||||
|
var payload = {};
|
||||||
|
var attributes = {
|
||||||
|
"ce-specversion" : "specversion",
|
||||||
|
"ce-source" : "source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// act and assert
|
||||||
|
expect(receiver.check.bind(receiver, payload, attributes))
|
||||||
|
.to.throw("header 'ce-id' not found");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Throw error when spec is not 1.0", () => {
|
||||||
|
// setup
|
||||||
|
var payload = {};
|
||||||
|
var attributes = {
|
||||||
|
"ce-type" : "type",
|
||||||
|
"ce-specversion" : "0.2",
|
||||||
|
"ce-source" : "source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// act and assert
|
||||||
|
expect(receiver.parse.bind(receiver, payload, attributes))
|
||||||
|
.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 = {};
|
||||||
|
var attributes = {
|
||||||
|
"ce-type" : "type",
|
||||||
|
"ce-specversion" : "1.0",
|
||||||
|
"ce-source" : "source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// act and assert
|
||||||
|
expect(receiver.check.bind(receiver, payload, attributes))
|
||||||
|
.to.not.throw();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Parse", () => {
|
||||||
|
it("Cloudevent contains 'type'", () => {
|
||||||
|
// setup
|
||||||
|
var payload = {
|
||||||
|
"data" : "dataString"
|
||||||
|
};
|
||||||
|
var attributes = {
|
||||||
|
"ce-type" : "type",
|
||||||
|
"ce-specversion" : "1.0",
|
||||||
|
"ce-source" : "source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"ce-time" : "2019-06-16T11:42:00Z",
|
||||||
|
"ce-dataschema" : "http://schema.registry/v1",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
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" : "1.0",
|
||||||
|
"ce-source" : "source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"ce-time" : "2019-06-16T11:42:00Z",
|
||||||
|
"ce-dataschema" : "http://schema.registry/v1",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
var actual = receiver.parse(payload, attributes);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
expect(actual.getSpecversion())
|
||||||
|
.to.equal("1.0");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Cloudevent contains 'source'", () => {
|
||||||
|
// setup
|
||||||
|
var payload = {
|
||||||
|
"data" : "dataString"
|
||||||
|
};
|
||||||
|
var attributes = {
|
||||||
|
"ce-type" : "type",
|
||||||
|
"ce-specversion" : "1.0",
|
||||||
|
"ce-source" : "/source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"ce-time" : "2019-06-16T11:42:00Z",
|
||||||
|
"ce-dataschema" : "http://schema.registry/v1",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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" : "1.0",
|
||||||
|
"ce-source" : "/source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"ce-time" : "2019-06-16T11:42:00Z",
|
||||||
|
"ce-dataschema" : "http://schema.registry/v1",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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" : "1.0",
|
||||||
|
"ce-source" : "/source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"ce-time" : "2019-06-16T11:42:00.000Z",
|
||||||
|
"ce-dataschema" : "http://schema.registry/v1",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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" : "1.0",
|
||||||
|
"ce-source" : "/source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"ce-time" : "2019-06-16T11:42:00Z",
|
||||||
|
"ce-dataschema" : "http://schema.registry/v1",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
var actual = receiver.parse(payload, attributes);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
expect(actual.getDataschema())
|
||||||
|
.to.equal("http://schema.registry/v1");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Cloudevent contains 'contenttype' (application/json)", () => {
|
||||||
|
// setup
|
||||||
|
var payload = {
|
||||||
|
"data" : "dataString"
|
||||||
|
};
|
||||||
|
var attributes = {
|
||||||
|
"ce-type" : "type",
|
||||||
|
"ce-specversion" : "1.0",
|
||||||
|
"ce-source" : "/source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"ce-time" : "2019-06-16T11:42:00Z",
|
||||||
|
"ce-dataschema" : "http://schema.registry/v1",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
var actual = receiver.parse(payload, attributes);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
expect(actual.getDataContentType())
|
||||||
|
.to.equal("application/json");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Cloudevent contains 'contenttype' (application/octet-stream)", () => {
|
||||||
|
// setup
|
||||||
|
var payload = "The payload is binary data";
|
||||||
|
var attributes = {
|
||||||
|
"ce-type" : "type",
|
||||||
|
"ce-specversion" : "1.0",
|
||||||
|
"ce-source" : "/source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"ce-time" : "2019-06-16T11:42:00Z",
|
||||||
|
"ce-dataschema" : "http://schema.registry/v1",
|
||||||
|
"Content-Type" : "application/octet-stream"
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
var actual = receiver.parse(payload, attributes);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
expect(actual.getDataContentType())
|
||||||
|
.to.equal("application/octet-stream");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Cloudevent contains 'data' (application/json)", () => {
|
||||||
|
// setup
|
||||||
|
var payload = {
|
||||||
|
"data" : "dataString"
|
||||||
|
};
|
||||||
|
var attributes = {
|
||||||
|
"ce-type" : "type",
|
||||||
|
"ce-specversion" : "1.0",
|
||||||
|
"ce-source" : "/source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"ce-time" : "2019-06-16T11:42:00Z",
|
||||||
|
"ce-dataschema" : "http://schema.registry/v1",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
var actual = receiver.parse(payload, attributes);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
expect(actual.getData())
|
||||||
|
.to.deep.equal(payload);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Cloudevent contains 'data' (application/octet-stream)", () => {
|
||||||
|
// setup
|
||||||
|
var payload = "The payload is binary data";
|
||||||
|
var attributes = {
|
||||||
|
"ce-type" : "type",
|
||||||
|
"ce-specversion" : "1.0",
|
||||||
|
"ce-source" : "/source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"ce-time" : "2019-06-16T11:42:00Z",
|
||||||
|
"ce-dataschema" : "http://schema.registry/v1",
|
||||||
|
"Content-Type" : "application/octet-stream"
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
var actual = receiver.parse(payload, attributes);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
expect(actual.getData())
|
||||||
|
.to.deep.equal(payload);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("No error when all attributes are in place", () => {
|
||||||
|
// setup
|
||||||
|
var payload = {
|
||||||
|
"data" : "dataString"
|
||||||
|
};
|
||||||
|
var attributes = {
|
||||||
|
"ce-type" : "type",
|
||||||
|
"ce-specversion" : "1.0",
|
||||||
|
"ce-source" : "source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"ce-time" : "2019-06-16T11:42:00Z",
|
||||||
|
"ce-dataschema" : "http://schema.registry/v1",
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
};
|
||||||
|
|
||||||
|
// act
|
||||||
|
var actual = receiver.parse(payload, attributes);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
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" : "1.0",
|
||||||
|
"ce-source" : "source",
|
||||||
|
"ce-id" : "id",
|
||||||
|
"ce-time" : "2019-06-16T11:42:00Z",
|
||||||
|
"ce-dataschema" : "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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue