Skip to content

Commit 3c8273f

Browse files
authored
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>
1 parent 129ec48 commit 3c8273f

File tree

4 files changed

+20
-7
lines changed

4 files changed

+20
-7
lines changed

Diff for: src/event/cloudevent.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
CloudEventV1OptionalAttributes,
1010
} from "./interfaces";
1111
import { validateV1, validateV03 } from "./spec";
12-
import { ValidationError, isBinary, asBase64 } from "./validation";
12+
import { ValidationError, isBinary, asBase64, isValidType } from "./validation";
1313
import CONSTANTS from "../constants";
1414
import { isString } from "util";
1515

@@ -108,6 +108,13 @@ export class CloudEvent implements CloudEventV1, CloudEventV03 {
108108
if (!key.match(/^[a-z0-9]{1,20}$/)) {
109109
throw new ValidationError("invalid extension name");
110110
}
111+
112+
// Value should be spec compliant
113+
// https://github.com/cloudevents/spec/blob/master/spec.md#type-system
114+
if (!isValidType(value)) {
115+
throw new ValidationError("invalid extension value");
116+
}
117+
111118
this[key] = value;
112119
}
113120

Diff for: src/event/validation.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,5 @@ export const asData = (data: unknown, contentType: string): string => {
8181
return isBinary(maybeJson) ? asBase64(maybeJson) : maybeJson;
8282
};
8383

84-
export const isValidType = (v: boolean | number | string | Date | Uint32Array): boolean =>
85-
isBoolean(v) || isInteger(v) || isString(v) || isDate(v) || isBinary(v);
84+
export const isValidType = (v: boolean | number | string | Date | Uint32Array | unknown): boolean =>
85+
isBoolean(v) || isInteger(v) || isString(v) || isDate(v) || isBinary(v) || isObject(v);

Diff for: test/integration/http_emitter_test.ts

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ const ext1Name = "lunch";
1515
const ext1Value = "tacos";
1616
const ext2Name = "supper";
1717
const ext2Value = "sushi";
18+
const ext3Name = "snack";
19+
const ext3Value = { value: "chips" };
1820

1921
const data = {
2022
lunchBreak: "noon",
@@ -45,6 +47,7 @@ describe("HTTP Transport Binding Emitter for CloudEvents", () => {
4547
data,
4648
[ext1Name]: ext1Value,
4749
[ext2Name]: ext2Value,
50+
[ext3Name]: ext3Value,
4851
});
4952

5053
it("Sends a binary 1.0 CloudEvent by default", () => {
@@ -59,6 +62,7 @@ describe("HTTP Transport Binding Emitter for CloudEvents", () => {
5962
// Ensure extensions are handled properly
6063
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext1Name}`]).to.equal(ext1Value);
6164
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext2Name}`]).to.equal(ext2Value);
65+
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext3Name}`].value).to.equal(ext3Value.value);
6266
})
6367
.catch(expect.fail);
6468
});
@@ -142,6 +146,7 @@ describe("HTTP Transport Binding Emitter for CloudEvents", () => {
142146
data,
143147
[ext1Name]: ext1Value,
144148
[ext2Name]: ext2Value,
149+
[ext3Name]: ext3Value,
145150
});
146151

147152
it("Sends a binary 0.3 CloudEvent", () => {
@@ -156,6 +161,7 @@ describe("HTTP Transport Binding Emitter for CloudEvents", () => {
156161
// Ensure extensions are handled properly
157162
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext1Name}`]).to.equal(ext1Value);
158163
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext2Name}`]).to.equal(ext2Value);
164+
expect(response.data[`${CONSTANTS.EXTENSIONS_PREFIX}${ext3Name}`].value).to.equal(ext3Value.value);
159165
})
160166
.catch(expect.fail);
161167
});

Diff for: test/integration/spec_1_tests.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,13 @@ describe("CloudEvents Spec v1.0", () => {
8787
expect(cloudevent.cloneWith({ extdate: myDate }).validate()).to.equal(true);
8888
});
8989

90-
// even though the spec doesn't allow object types for
91-
// extensions, it could be JSON. And before a JS CE
92-
// is transmitted across the wire, this value will be
93-
// converted to JSON
9490
it("should be ok when the type is an object", () => {
9591
expect(cloudevent.cloneWith({ objectextension: { some: "object" } }).validate()).to.equal(true);
9692
});
93+
94+
it("should be ok when the type is an string converted from an object", () => {
95+
expect(cloudevent.cloneWith({ objectextension: JSON.stringify({ some: "object" }) }).validate()).to.equal(true);
96+
});
9797
});
9898

9999
describe("The Constraints check", () => {

0 commit comments

Comments
 (0)