lib: validate extension values (#251)
BREAKING CHANGE: This validates the value of the cloud event extension based on the spec, https://github.com/cloudevents/spec/blob/master/spec.md#type-system Signed-off-by: Lucas Holmquist <lholmqui@redhat.com>
This commit is contained in:
parent
129ec485d9
commit
3c8273f114
|
@ -9,7 +9,7 @@ import {
|
||||||
CloudEventV1OptionalAttributes,
|
CloudEventV1OptionalAttributes,
|
||||||
} from "./interfaces";
|
} from "./interfaces";
|
||||||
import { validateV1, validateV03 } from "./spec";
|
import { validateV1, validateV03 } from "./spec";
|
||||||
import { ValidationError, isBinary, asBase64 } from "./validation";
|
import { ValidationError, isBinary, asBase64, isValidType } from "./validation";
|
||||||
import CONSTANTS from "../constants";
|
import CONSTANTS from "../constants";
|
||||||
import { isString } from "util";
|
import { isString } from "util";
|
||||||
|
|
||||||
|
@ -108,6 +108,13 @@ export class CloudEvent implements CloudEventV1, CloudEventV03 {
|
||||||
if (!key.match(/^[a-z0-9]{1,20}$/)) {
|
if (!key.match(/^[a-z0-9]{1,20}$/)) {
|
||||||
throw new ValidationError("invalid extension name");
|
throw new ValidationError("invalid extension name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Value should be spec compliant
|
||||||
|
// https://github.com/cloudevents/spec/blob/master/spec.md#type-system
|
||||||
|
if (!isValidType(value)) {
|
||||||
|
throw new ValidationError("invalid extension value");
|
||||||
|
}
|
||||||
|
|
||||||
this[key] = value;
|
this[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,5 +81,5 @@ export const asData = (data: unknown, contentType: string): string => {
|
||||||
return isBinary(maybeJson) ? asBase64(maybeJson) : maybeJson;
|
return isBinary(maybeJson) ? asBase64(maybeJson) : maybeJson;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isValidType = (v: boolean | number | string | Date | Uint32Array): boolean =>
|
export const isValidType = (v: boolean | number | string | Date | Uint32Array | unknown): boolean =>
|
||||||
isBoolean(v) || isInteger(v) || isString(v) || isDate(v) || isBinary(v);
|
isBoolean(v) || isInteger(v) || isString(v) || isDate(v) || isBinary(v) || isObject(v);
|
||||||
|
|
|
@ -15,6 +15,8 @@ const ext1Name = "lunch";
|
||||||
const ext1Value = "tacos";
|
const ext1Value = "tacos";
|
||||||
const ext2Name = "supper";
|
const ext2Name = "supper";
|
||||||
const ext2Value = "sushi";
|
const ext2Value = "sushi";
|
||||||
|
const ext3Name = "snack";
|
||||||
|
const ext3Value = { value: "chips" };
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
lunchBreak: "noon",
|
lunchBreak: "noon",
|
||||||
|
@ -45,6 +47,7 @@ describe("HTTP Transport Binding Emitter for CloudEvents", () => {
|
||||||
data,
|
data,
|
||||||
[ext1Name]: ext1Value,
|
[ext1Name]: ext1Value,
|
||||||
[ext2Name]: ext2Value,
|
[ext2Name]: ext2Value,
|
||||||
|
[ext3Name]: ext3Value,
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Sends a binary 1.0 CloudEvent by default", () => {
|
it("Sends a binary 1.0 CloudEvent by default", () => {
|
||||||
|
@ -59,6 +62,7 @@ describe("HTTP Transport Binding Emitter for CloudEvents", () => {
|
||||||
// Ensure extensions are handled properly
|
// Ensure extensions are handled properly
|
||||||
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext1Name}`]).to.equal(ext1Value);
|
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext1Name}`]).to.equal(ext1Value);
|
||||||
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext2Name}`]).to.equal(ext2Value);
|
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext2Name}`]).to.equal(ext2Value);
|
||||||
|
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext3Name}`].value).to.equal(ext3Value.value);
|
||||||
})
|
})
|
||||||
.catch(expect.fail);
|
.catch(expect.fail);
|
||||||
});
|
});
|
||||||
|
@ -142,6 +146,7 @@ describe("HTTP Transport Binding Emitter for CloudEvents", () => {
|
||||||
data,
|
data,
|
||||||
[ext1Name]: ext1Value,
|
[ext1Name]: ext1Value,
|
||||||
[ext2Name]: ext2Value,
|
[ext2Name]: ext2Value,
|
||||||
|
[ext3Name]: ext3Value,
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Sends a binary 0.3 CloudEvent", () => {
|
it("Sends a binary 0.3 CloudEvent", () => {
|
||||||
|
@ -156,6 +161,7 @@ describe("HTTP Transport Binding Emitter for CloudEvents", () => {
|
||||||
// Ensure extensions are handled properly
|
// Ensure extensions are handled properly
|
||||||
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext1Name}`]).to.equal(ext1Value);
|
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext1Name}`]).to.equal(ext1Value);
|
||||||
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext2Name}`]).to.equal(ext2Value);
|
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext2Name}`]).to.equal(ext2Value);
|
||||||
|
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext3Name}`].value).to.equal(ext3Value.value);
|
||||||
})
|
})
|
||||||
.catch(expect.fail);
|
.catch(expect.fail);
|
||||||
});
|
});
|
||||||
|
|
|
@ -87,13 +87,13 @@ describe("CloudEvents Spec v1.0", () => {
|
||||||
expect(cloudevent.cloneWith({ extdate: myDate }).validate()).to.equal(true);
|
expect(cloudevent.cloneWith({ extdate: myDate }).validate()).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// even though the spec doesn't allow object types for
|
|
||||||
// extensions, it could be JSON. And before a JS CE
|
|
||||||
// is transmitted across the wire, this value will be
|
|
||||||
// converted to JSON
|
|
||||||
it("should be ok when the type is an object", () => {
|
it("should be ok when the type is an object", () => {
|
||||||
expect(cloudevent.cloneWith({ objectextension: { some: "object" } }).validate()).to.equal(true);
|
expect(cloudevent.cloneWith({ objectextension: { some: "object" } }).validate()).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should be ok when the type is an string converted from an object", () => {
|
||||||
|
expect(cloudevent.cloneWith({ objectextension: JSON.stringify({ some: "object" }) }).validate()).to.equal(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("The Constraints check", () => {
|
describe("The Constraints check", () => {
|
||||||
|
|
Loading…
Reference in New Issue