Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emit Binary, but receives Structured #301

Closed
lholmquist opened this issue Aug 5, 2020 · 10 comments
Closed

Emit Binary, but receives Structured #301

lholmquist opened this issue Aug 5, 2020 · 10 comments
Assignees
Labels
module/transport/http Issues related to the HTTP transport protocol implementation type/bug Something isn't working

Comments

@lholmquist
Copy link
Contributor

lholmquist commented Aug 5, 2020

Describe the Bug

I was playing around with a small example where i Emit a binary cloud event. something like this:

'use strict';

const { Emitter, CloudEvent } = require('cloudevents');

const em = new Emitter({ url: 'http://localhost:3000/cloudeventy' });
const ce = new CloudEvent({
  type: 'com.lholmquist.cloudeventy.fun',
  source: 'fun-with-cloud-events',
  data: 'DATA'
});


em.send(ce)
  .then(response => {
    console.log(response);
  })
  .catch(err => {
    console.log(err);
  });

Then i have a basic express.js application running on port 3000 with the route cloudeventy to receive the event coming in, which looks similar to this:

app.post('/cloudeventy', (req, res) => {
  console.log(req.headers);
  const ce = Receiver.accept(req.headers, req.body);
  res.send('...');
});

However, I get an error saying that "Cannot read property specversion of undefned".

I also console logged out my request headers too.

{
  accept: 'application/json, text/plain, */*',
  'content-type': 'application/cloudevents+json; charset=utf-8',
  'ce-id': '51568118-f04b-4491-9895-a0e1bfa4ac09',
  'ce-type': 'com.lholmquist.cloudeventy.fun',
  'ce-source': 'fun-with-cloud-events',
  'ce-specversion': '1.0',
  'ce-time': '2020-08-04T23:39:35.162Z',
  'user-agent': 'axios/0.19.2',
  'content-length': '4',
  host: 'localhost:3000',
  connection: 'close'
}
TypeError: Cannot read property 'specversion' of undefined
    at getVersion (/home/lucasholmquist/develop/just-playing/fun-with-cloudevents/node_modules/cloudevents/dist/transport/receiver.js:92:79)
    at Function.accept (/home/lucasholmquist/develop/just-playing/fun-with-cloudevents/node_modules/cloudevents/dist/transport/receiver.js:45:25)
    at /home/lucasholmquist/develop/just-playing/fun-with-cloudevents/index.js:14:23
    at Layer.handle [as handle_request] (/home/lucasholmquist/develop/just-playing/fun-with-cloudevents/node_modules/express/lib/router/layer.js:95:5)
    at next (/home/lucasholmquist/develop/just-playing/fun-with-cloudevents/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/home/lucasholmquist/develop/just-playing/fun-with-cloudevents/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/home/lucasholmquist/develop/just-playing/fun-with-cloudevents/node_modules/express/lib/router/layer.js:95:5)
    at /home/lucasholmquist/develop/just-playing/fun-with-cloudevents/node_modules/express/lib/router/index.js:281:22
    at Function.process_params (/home/lucasholmquist/develop/just-playing/fun-with-cloudevents/node_modules/express/lib/router/index.js:335:12)
    at next (/home/lucasholmquist/develop/just-playing/fun-with-cloudevents/node_modules/express/lib/router/index.js:275:10)

When i step through the code on the receiving end, it treats it as a structured event, not a binary event, even though that was how it was sent.

There is code to determine the mode, that parses the content-type header. https://github.com/cloudevents/sdk-javascript/blob/master/src/transport/receiver.ts#L66 and if it sees application/cloudevents then it says it is a "structured" event. The problem is that both the structured and binary emitters add the same content-type header.

Binary Emitter Headers: https://github.com/cloudevents/sdk-javascript/blob/master/src/transport/http/binary_emitter.ts#L23

Structured Emitter Headers: https://github.com/cloudevents/sdk-javascript/blob/master/src/transport/http/structured_emitter.ts#L8

It seems that the check for "Binary Headers" should happen first, unless the headers are wrong for the binary version

Extra Context:

These code examples i gave above i think would make a good example, since we don't have an emitter example yet

@lance @grant thoughts?

@grant
Copy link
Member

grant commented Aug 5, 2020

Edit: Well, I don't know how the emitter works, but I would assume we want the user to specify whether to emit binary or structured.

The code above seems fine.

It seems like we don't specify that message mode when emitting?

@lholmquist
Copy link
Contributor Author

but I would assume we want the user to specify whether to emit binary or structured.

The default with no options is binary, which is here: https://github.com/cloudevents/sdk-javascript/blob/master/src/transport/emitter.ts#L48

I think not specifying is ok, as long as we document that it defaults to something.

It seems like we don't specify that message mode when emitting?

I guess i'm not familiar enough with the spec to know if the headers we add should be different than what we do currently for binary mode

@lance
Copy link
Member

lance commented Aug 5, 2020

Hmm - looks strange

{
  accept: 'application/json, text/plain, */*',
  'content-type': 'application/cloudevents+json; charset=utf-8',
  'ce-id': '51568118-f04b-4491-9895-a0e1bfa4ac09',
  'ce-type': 'com.lholmquist.cloudeventy.fun',
  'ce-source': 'fun-with-cloud-events',
  'ce-specversion': '1.0',
  'ce-time': '2020-08-04T23:39:35.162Z',
  'user-agent': 'axios/0.19.2',
  'content-length': '4',
  host: 'localhost:3000',
  connection: 'close'
}

The content type header here indicates a structured event. However, the inclusion of all of the ce-* headers is what happens for a binary event. So the Receiver is getting confused. What seems wrong here is that the Emitter is sending the wrong content type header. For the binary transport mode this is typically application/json. In this case, your data is just a string so that would work, but so would text/plain.

This appears to be a bug. This line should be:

  const contentType: Headers = { [CONSTANTS.HEADER_CONTENT_TYPE]: CONSTANTS.DEFAULT_CONTENT_TYPE };

Very strange that this hasn't been caught in tests....

@lance
Copy link
Member

lance commented Aug 5, 2020

Follow up...

In our Emitter tests, we are testing the content type for a structured mode event here. But the binary transport mode tests omit checking the header. That test should probably be augmented to check the header value, and the Emitter code noted above should be changed. That should resolve this issue.

@lholmquist
Copy link
Contributor Author

LOL, just wrote that:

i looked at the emitter tests and for binary, we look for the headers that are suppose to be there, not the ones that aren't suppose to be.

And we also never call Receiver.accpet in those tests

And glad this is a bug and i'm not going crazy :)

@lholmquist
Copy link
Contributor Author

Also, is there a place in the spec, that says which headers are suppose to go with which mode?

@lance lance added module/transport/http Issues related to the HTTP transport protocol implementation type/bug Something isn't working labels Aug 5, 2020
@lholmquist
Copy link
Contributor Author

assigning to myself to fix if no one minds

@lance
Copy link
Member

lance commented Aug 5, 2020

Also, is there a place in the spec, that says which headers are suppose to go with which mode?

@lholmquist lholmquist self-assigned this Aug 5, 2020
@lance
Copy link
Member

lance commented Aug 5, 2020

@lholmquist

And we also never call Receiver.accpet in those tests

I don't think we need to call Receiver.accept in the Emitter test. We just need to be validating our expectations. The Receiver is tested separately.

@lholmquist
Copy link
Contributor Author

yup, was just illustrating why we never picked up the issue until now

lholmquist added a commit to lholmquist/sdk-javascript that referenced this issue Aug 5, 2020
lholmquist added a commit to lholmquist/sdk-javascript that referenced this issue Aug 5, 2020
fixes cloudevents#301

Signed-off-by: Lucas Holmquist <lholmqui@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
module/transport/http Issues related to the HTTP transport protocol implementation type/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants