Skip to content

Commit e42b5bb

Browse files
committed
chore: clean up event unmarshalling, remove async API calls
The cloudevents sdk has some inconsistencies with how it exposed the unmarshalling. Version 0.3 and earlier had an async API, while 1.0 (smartly) changed that. As a result, the impl in this file was pretty ugly. By using the receivers directly, we can avoid that and clean up this code. These changes are based on: cloudevents/sdk-javascript#120 Once those changes land in a released version of the cloudevents sdk this file can be even simpler as the sdk will handle most of this work. As an aside - dropped support for 0.2. Normally I wouldn't be so casual about dropping support, but upstream sdk has no 0.2 support in the next release and cloud events spec says only the two most recent versions are required to be supported.
1 parent 55ba91f commit e42b5bb

File tree

2 files changed

+59
-72
lines changed

2 files changed

+59
-72
lines changed

lib/event-handler.js

Lines changed: 59 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,95 @@
11
'use strict';
22

3-
const v02 = require('cloudevents-sdk/v02');
4-
const v03 = require('cloudevents-sdk/v03');
5-
const v1 = require('cloudevents-sdk/v1');
3+
const V03Binary = require('cloudevents-sdk/lib/bindings/http/receiver_binary_0_3');
4+
const V03Structured = require('cloudevents-sdk/lib/bindings/http/receiver_structured_0_3.js');
5+
const V1Binary = require('cloudevents-sdk/lib/bindings/http/receiver_binary_1.js');
6+
const V1Structured = require('cloudevents-sdk/lib/bindings/http/receiver_structured_1.js');
7+
68
const Spec = require('./ce-constants.js').Spec;
79

8-
const v02Unmarshaller = new v02.HTTPUnmarshaller();
9-
const v03Unmarshaller = new v03.HTTPUnmarshaller();
10-
const v1BinaryReceiver = new v1.BinaryHTTPReceiver();
11-
const v1StructuredReceiver = new v1.StructuredHTTPReceiver();
10+
const receivers = {
11+
v1: {
12+
structured: new V1Structured(),
13+
binary: new V1Binary()
14+
},
15+
v03: {
16+
structured: new V03Structured(),
17+
binary: new V03Binary()
18+
}
19+
};
1220

1321
function use(fastify, opts, done) {
1422
fastify.addContentTypeParser('application/cloudevents+json',
1523
{ parseAs: 'string' },
1624
function(req, body, done) {
17-
// unmarshallEvent() handles parsing
1825
done(null, body);
1926
});
2027

2128
fastify.decorateRequest('isCloudEvent', function() {
2229
if (Spec.type in this.req.headers) {
2330
return true;
24-
} else {
25-
const contentType = this.req.headers['content-type'];
26-
if (contentType && contentType.match(/application\/cloudevents/)) {
27-
return true;
28-
}
2931
}
30-
return false;
32+
const contentType = this.req.headers['content-type'];
33+
return contentType && contentType.match(/application\/cloudevents/);
3134
});
3235

3336
// Any incoming requests for cloud events will only be
3437
// processed if it's a cloud event spec version we know about
35-
fastify.addHook('preHandler', async(request, reply) => {
38+
fastify.addHook('preHandler', function(request, reply, done) {
3639
if (request.isCloudEvent()) {
37-
const version = request.headers[Spec.version];
38-
// if there is no version in the headers, it is a
39-
// structured event
40-
if (version && !acceptsVersion(version)) {
40+
try {
41+
request.context.cloudevent =
42+
accept(request.headers, request.body).format();
43+
} catch (err) {
4144
reply.code(406);
42-
const error = new Error(
43-
`Unsupported cloud event version detected: ${version}`);
44-
error.code = 406;
45-
throw error;
46-
} else {
47-
try {
48-
await unmarshallEvent(request);
49-
} catch (err) {
50-
throw new Error(err.message ||
51-
`Failed to unmarshall cloud event: ${err}`);
52-
}
45+
done(err);
5346
}
5447
}
48+
done();
5549
});
5650

5751
done();
5852
}
5953

60-
async function unmarshallEvent(request) {
61-
const version = request.headers[Spec.version];
62-
if (!version) {
63-
// it's a structured event and the version is in the body
64-
// currently only v1 structured events are supported
65-
try {
66-
const event = v1StructuredReceiver.parse(request.body, request.headers);
67-
request.context.cloudevent = event.format();
68-
} catch (err) {
69-
return Promise.reject(err);
54+
function accept(headers, body) {
55+
const mode = getMode(headers);
56+
const version = getVersion(mode, headers, body);
57+
switch (version) {
58+
case '1.0':
59+
return receivers.v1[mode].parse(body, headers);
60+
case '0.3':
61+
return receivers.v03[mode].parse(body, headers);
62+
default:
63+
console.error(`Unknown spec version ${version}`);
64+
throw new TypeError(
65+
`Unsupported cloud event version detected: ${version}`);
66+
}
67+
}
68+
69+
function getMode(headers) {
70+
let mode = 'binary';
71+
if (headers['content-type']) {
72+
if (headers['content-type'].startsWith('application/cloudevents')) {
73+
mode = 'structured';
7074
}
71-
} else if (version === '0.2') {
72-
return v02Unmarshaller.unmarshall(request.body, request.headers)
73-
.then(cloudevent => (request.context.cloudevent = cloudevent.format()));
74-
} else if (version === '0.3') {
75-
return v03Unmarshaller.unmarshall(request.body, request.headers)
76-
.then(cloudevent => (request.context.cloudevent = cloudevent.format()));
77-
} else if (version === '1.0') {
78-
const event = v1BinaryReceiver.parse(request.body, request.headers);
79-
request.context.cloudevent = event.format();
8075
}
76+
return mode;
8177
}
8278

83-
function acceptsVersion(version) {
84-
return ['0.2', '0.3', '1.0'].find(elem => version === elem) !== undefined;
79+
function getVersion(mode, headers, body) {
80+
let version = '1.0'; // default to 1.0
81+
82+
if (mode === 'binary') {
83+
// Check the headers for the version
84+
if (headers['ce-specversion']) {
85+
version = headers['ce-specversion'];
86+
}
87+
} else {
88+
// structured mode - the version is in the body
89+
version = typeof body === 'string'
90+
? JSON.parse(body).specversion : body.specversion;
91+
}
92+
return version;
8593
}
8694

8795
module.exports = exports = use;

test/test.js

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -79,27 +79,6 @@ test('Accepts HTTP POST requests', t => {
7979
}, { log: false });
8080
});
8181

82-
test('Responds to 0.2 binary cloud events', t => {
83-
const func = require(`${__dirname}/fixtures/cloud-event/`);
84-
framework(func, server => {
85-
request(server)
86-
.post('/')
87-
.send({ message: 'hello' })
88-
.set(Spec.id, '1')
89-
.set(Spec.source, 'integration-test')
90-
.set(Spec.type, 'dev.knative.example')
91-
.set(Spec.version, '0.2')
92-
.expect(200)
93-
.expect('Content-Type', /json/)
94-
.end((err, res) => {
95-
t.error(err, 'No error');
96-
t.equal(res.body, 'hello');
97-
t.end();
98-
server.close();
99-
});
100-
}, { log: false });
101-
});
102-
10382
test('Responds to 0.3 binary cloud events', t => {
10483
const func = require(`${__dirname}/fixtures/cloud-event/`);
10584
framework(func, server => {

0 commit comments

Comments
 (0)