Skip to content

Commit 7f6b658

Browse files
authored
fix: throw on validation if extensions are improperly named (#420)
Also fixes the case where UPPERCASED extension names were silently changed to lowercase and then set as undefined. Even though uppercased extension names are invalid, we should still accept them in incoming messsages and only throw when validating the event. Fixes: #380 Signed-off-by: Lance Ball <[email protected]>
1 parent 80d987c commit 7f6b658

File tree

4 files changed

+34
-6
lines changed

4 files changed

+34
-6
lines changed

src/event/spec.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,21 @@ export function validateCloudEvent(event: CloudEventV03 | CloudEventV1): boolean
2828
if (!isValidAgainstSchemaV1(event)) {
2929
throw new ValidationError("invalid payload", isValidAgainstSchemaV1.errors);
3030
}
31-
return true;
3231
} else if (event.specversion === Version.V03) {
3332
if (!isValidAgainstSchemaV03(event)) {
3433
throw new ValidationError("invalid payload", isValidAgainstSchemaV03.errors);
3534
}
36-
return checkDataContentEncoding(event);
35+
checkDataContentEncoding(event);
36+
} else {
37+
return false;
3738
}
38-
return false;
39+
// attribute names must all be lowercase
40+
for (const key in event) {
41+
if (key !== key.toLowerCase()) {
42+
throw new ValidationError(`invalid attribute name: ${key}`);
43+
}
44+
}
45+
return true;
3946
}
4047

4148
function checkDataContentEncoding(event: CloudEventV03): boolean {

src/event/validation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export class ValidationError extends TypeError {
1919
// @ts-ignore
2020
errors?.reduce(
2121
(accum: string, err: Record<string, string>) =>
22-
(accum as string).concat(`
22+
accum.concat(`
2323
${err instanceof Object ? JSON.stringify(err) : err}`),
2424
message,
2525
)

src/message/http/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ function getVersion(mode: Mode, headers: Headers, body: string | Record<string,
151151
* @throws {ValidationError} of the event does not conform to the spec
152152
*/
153153
function parseBinary(message: Message, version: Version): CloudEvent {
154-
const headers = message.headers;
154+
const headers = { ...message.headers };
155155
let body = message.body;
156156

157157
if (!headers) throw new ValidationError("headers is null or undefined");
@@ -167,11 +167,12 @@ function parseBinary(message: Message, version: Version): CloudEvent {
167167
const mappedParser: MappedParser = parserMap[header];
168168
eventObj[mappedParser.name] = mappedParser.parser.parse(sanitizedHeaders[header]);
169169
delete sanitizedHeaders[header];
170+
delete headers[header];
170171
}
171172
}
172173

173174
// Every unprocessed header can be an extension
174-
for (const header in sanitizedHeaders) {
175+
for (const header in headers) {
175176
if (header.startsWith(CONSTANTS.EXTENSIONS_PREFIX)) {
176177
eventObj[header.substring(CONSTANTS.EXTENSIONS_PREFIX.length)] = headers[header];
177178
}

test/integration/message_test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,26 @@ describe("HTTP transport", () => {
6464
expect(HTTP.isEvent(message)).to.be.true;
6565
});
6666

67+
it("Respects extension attribute casing (even if against spec)", () => {
68+
// Now create a message that is an event
69+
const message = {
70+
body: `{ "greeting": "hello" }`,
71+
headers: {
72+
[CONSTANTS.CE_HEADERS.ID]: "1234",
73+
[CONSTANTS.CE_HEADERS.SOURCE]: "test",
74+
[CONSTANTS.CE_HEADERS.TYPE]: "test.event",
75+
[CONSTANTS.CE_HEADERS.SPEC_VERSION]: Version.V1,
76+
"ce-LUNCH": "tacos",
77+
},
78+
};
79+
expect(HTTP.isEvent(message)).to.be.true;
80+
const event: CloudEvent = HTTP.toEvent(message);
81+
expect(event.LUNCH).to.equal("tacos");
82+
expect(function () {
83+
event.validate();
84+
}).to.throw("invalid attribute name: LUNCH");
85+
});
86+
6787
it("Can detect CloudEvent binary Messages with weird versions", () => {
6888
// Now create a message that is an event
6989
const message = {

0 commit comments

Comments
 (0)