feat(src): add ext name validation (#246)
BREAKING CHANGE: * Extension names are now validated during object creation. The values are defined by the specification, and can be lowercase(a-z) or digits(0-9) and must be no longer that 20 characters Signed-off-by: Lucas Holmquist <lholmqui@redhat.com>
This commit is contained in:
parent
de6f0a2945
commit
84f1ed9cfe
|
@ -96,6 +96,11 @@ export class CloudEvent implements CloudEventV1, CloudEventV03 {
|
|||
|
||||
// finally process any remaining properties - these are extensions
|
||||
for (const [key, value] of Object.entries(properties)) {
|
||||
// Extension names should only allow lowercase a-z and 0-9 in the name
|
||||
// names should not exceed 20 characters in length
|
||||
if (!key.match(/^[a-z0-9]{1,20}$/)) {
|
||||
throw new ValidationError("invalid extension name");
|
||||
}
|
||||
this[key] = value;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,18 @@ describe("A CloudEvent", () => {
|
|||
const ce = new CloudEvent(fixture);
|
||||
expect(ce.toString()).to.deep.equal(JSON.stringify(ce));
|
||||
});
|
||||
|
||||
it("Throw a validation error for invalid extension names", () => {
|
||||
expect(() => {
|
||||
new CloudEvent({ "ext-1": "extension1", ...fixture });
|
||||
}).throw("invalid extension name");
|
||||
});
|
||||
|
||||
it("Throw a validation error for invalid extension names, more than 20 chars", () => {
|
||||
expect(() => {
|
||||
new CloudEvent({ "123456789012345678901": "extension1", ...fixture });
|
||||
}).throw("invalid extension name");
|
||||
});
|
||||
});
|
||||
|
||||
describe("A 1.0 CloudEvent", () => {
|
||||
|
@ -92,13 +104,13 @@ describe("A 1.0 CloudEvent", () => {
|
|||
|
||||
it("can be constructed with extensions", () => {
|
||||
const extensions = {
|
||||
"extension-key": "extension-value",
|
||||
extensionkey: "extension-value",
|
||||
};
|
||||
const ce = new CloudEvent({
|
||||
...extensions,
|
||||
...fixture,
|
||||
});
|
||||
expect(ce["extension-key"]).to.equal(extensions["extension-key"]);
|
||||
expect(ce["extensionkey"]).to.equal(extensions["extensionkey"]);
|
||||
});
|
||||
|
||||
it("throws ValidationError if the CloudEvent does not conform to the schema");
|
||||
|
|
|
@ -11,8 +11,6 @@ const source = "urn:event:from:myapi/resourse/123";
|
|||
const time = new Date();
|
||||
const dataschema = "http://cloudevents.io/schema.json";
|
||||
|
||||
const ceContentType = "application/json";
|
||||
|
||||
const data = {
|
||||
foo: "bar",
|
||||
};
|
||||
|
@ -108,7 +106,6 @@ describe("HTTP Transport Binding Structured Receiver for CloudEvents v1.0", () =
|
|||
time,
|
||||
data,
|
||||
dataschema,
|
||||
dataContentType: ceContentType,
|
||||
};
|
||||
const headers = {
|
||||
"content-type": "application/cloudevents+json",
|
||||
|
@ -124,14 +121,13 @@ describe("HTTP Transport Binding Structured Receiver for CloudEvents v1.0", () =
|
|||
|
||||
it("Should accept 'extension1'", () => {
|
||||
// setup
|
||||
const extension1 = "mycustom-ext1";
|
||||
const extension1 = "mycustomext1";
|
||||
const event = {
|
||||
type,
|
||||
source,
|
||||
time,
|
||||
data,
|
||||
dataschema,
|
||||
dataContentType: ceContentType,
|
||||
extension1,
|
||||
};
|
||||
|
||||
|
@ -152,7 +148,6 @@ describe("HTTP Transport Binding Structured Receiver for CloudEvents v1.0", () =
|
|||
time,
|
||||
dataschema,
|
||||
data: data,
|
||||
dataContentType: ceContentType,
|
||||
};
|
||||
|
||||
const headers = {
|
||||
|
@ -173,7 +168,6 @@ describe("HTTP Transport Binding Structured Receiver for CloudEvents v1.0", () =
|
|||
type,
|
||||
source,
|
||||
data: bindata,
|
||||
dataContentType: ceContentType,
|
||||
};
|
||||
|
||||
const headers = {
|
||||
|
|
|
@ -65,26 +65,26 @@ describe("CloudEvents Spec v1.0", () => {
|
|||
|
||||
describe("Extensions Constraints", () => {
|
||||
it("should be ok when type is 'boolean'", () => {
|
||||
expect(cloudevent.cloneWith({ "ext-boolean": true }).validate()).to.equal(true);
|
||||
expect(cloudevent.cloneWith({ extboolean: true }).validate()).to.equal(true);
|
||||
});
|
||||
|
||||
it("should be ok when type is 'integer'", () => {
|
||||
expect(cloudevent.cloneWith({ "ext-integer": 2019 }).validate()).to.equal(true);
|
||||
expect(cloudevent.cloneWith({ extinteger: 2019 }).validate()).to.equal(true);
|
||||
});
|
||||
|
||||
it("should be ok when type is 'string'", () => {
|
||||
expect(cloudevent.cloneWith({ "ext-string": "an-string" }).validate()).to.equal(true);
|
||||
expect(cloudevent.cloneWith({ extstring: "an-string" }).validate()).to.equal(true);
|
||||
});
|
||||
|
||||
it("should be ok when type is 'Uint32Array' for 'Binary'", () => {
|
||||
const myBinary = new Uint32Array(2019);
|
||||
expect(cloudevent.cloneWith({ "ext-binary": myBinary }).validate()).to.equal(true);
|
||||
expect(cloudevent.cloneWith({ extbinary: myBinary }).validate()).to.equal(true);
|
||||
});
|
||||
|
||||
// URI
|
||||
it("should be ok when type is 'Date' for 'Timestamp'", () => {
|
||||
const myDate = new Date();
|
||||
expect(cloudevent.cloneWith({ "ext-date": myDate }).validate()).to.equal(true);
|
||||
expect(cloudevent.cloneWith({ extdate: myDate }).validate()).to.equal(true);
|
||||
});
|
||||
|
||||
// even though the spec doesn't allow object types for
|
||||
|
@ -92,7 +92,7 @@ describe("CloudEvents Spec v1.0", () => {
|
|||
// is transmitted across the wire, this value will be
|
||||
// converted to JSON
|
||||
it("should be ok when the type is an object", () => {
|
||||
expect(cloudevent.cloneWith({ "object-extension": { some: "object" } }).validate()).to.equal(true);
|
||||
expect(cloudevent.cloneWith({ objectextension: { some: "object" } }).validate()).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue