Skip to content
New issue

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

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

Already on GitHub? # to your account

feat: add a constructor parameter for loose validation #328

Merged
merged 2 commits into from
Sep 8, 2020

Conversation

lance
Copy link
Member

@lance lance commented Aug 26, 2020

Proposed Changes

  • add a second, optional, boolean parameter called strict to CloudEvent constructor, defaulting to true.
  • add a second, optional, boolean parameter called strict to CloudEvent.cloneWith() defaulting to true
  • skip all validation steps if strict is false
  • add tests for these changes

Description

This commit adds a second, optional boolean parameter to the CloudEvent
constructor. When false is provided, the event constructor will not
perform validation of the event properties, values and extension names.

As I am writing this, I wonder if it will be less error prone to default to false
and call the parameter looseValidation.

@lance lance added type/enhancement New feature or request version/3.x Issues related to the 3.0 release of this library module/lib Related to the main source code labels Aug 26, 2020
@lance lance requested a review from a team August 26, 2020 19:05
@lholmquist
Copy link
Contributor

As I am writing this, I wonder if it will be less error prone to default to false and call the parameter looseValidation.

Or maybe it is just called validate? what ever it is called, Validation should happen in the default state and an action should be needed to turn it off

@grant
Copy link
Member

grant commented Aug 26, 2020

I'd rather not have implicit validation unless explicitly requested by the user.
It would be great if a user could just call a method to validate a CE at any time if they want.

@lholmquist
Copy link
Contributor

I'd rather not have implicit validation unless explicitly requested by the user.

Then what's the point of having a module that is trying to adhere to a spec if it is off by default?

@grant
Copy link
Member

grant commented Aug 26, 2020

I'd rather not have implicit validation unless explicitly requested by the user.

Then what's the point of having a module that is trying to adhere to a spec if it is off by default?

I would expect a separate method for validation. Or at least be optional.
I wouldn't expect it to be coupled with event creation.

Spec: https://github.com/cloudevents/spec/blob/master/SDK.md#compose-an-event

A common way to do this would be:

const ce = new CloudEvent({...});
const isValid = ce.isValid() // true or false
if (!isValid) { 
  console.log('Not a valid CloudEvent');
}
// or...
try {
  ce.validate();
} catch (e) {
  console.error(e);
}

I would not imagine myself doing:

let ce;
try {
  ce = new CloudEvent({...}, true);
} catch (e) {
  console.log(e)
}

There's still lots of reason to use the module like calling calling ce.validate(), ce.toJSON(), etc. Hope the above makes sense.

@lance
Copy link
Member Author

lance commented Aug 26, 2020

Then what's the point of having a module that is trying to adhere to a spec if it is off by default?

I tend to agree with you in principle here @lholmquist.

That said, a close reading of the spec makes me think that it's acceptable to default to not be strict. Specifically, https://github.com/cloudevents/spec/blob/master/SDK.md#validation only mentions that an SDK must make it possible to validate a given Event per a spec. This implies that having invalid events is a possibility, and potentially expected. When I think about possible friction that a developer might experience when starting to work with this SDK, I can see how easy it might be to get confused or frustrated if you're testing things with an invalid event and just don't know it - and strict validation is on by default, but there's no obvious way to know this.

In spite of my tendency to prefer strict adherence to the spec always, I think maybe in this case, making the easy path as easy as possible, while providing for a simple way to remain strict could be a good thing. I don't like what it means for our tests though. By defaulting to loose validation, I think most if not all of our existing tests would need to be modified.

Maybe we can get a discussion going in the #cloudeventssdk slack to see what others think.

@lholmquist
Copy link
Contributor

Maybe we can get a discussion going in the #cloudeventssdk slack to see what others think.

That sounds reasonable

@grant
Copy link
Member

grant commented Aug 26, 2020

Yeah, its not a clear-cut problem. I don't know what the spec says about passing invalid CEs (they should probably work unless there is a fatal issue).

Maybe we can get a discussion going in the #cloudeventssdk slack to see what others think.

Checking others with slack sgtm.

Another rationale for separate validation is because we may have already validated the CloudEvent (maybe from a different sdk, when cloning, already validated in the server, etc).

@lance
Copy link
Member Author

lance commented Aug 27, 2020

OK - I brought this issue to attention at the CE community Zoom call today and got some good feedback. Here's a proposal.

  • Creating a CloudEvent manually using the constructor, e.g. const ce = new CloudEvent({}); should be strict mode
  • Receiving a Message over HTTP or other transport and converting to a CloudEvent via HTTP.toEvent() should be loose mode with no explicit validation
  • Creating a Message from a CloudEvent via HTTP.binary(event) or HTTP.structured(event) should validate before creating the Message instance

This accomplishes a few things

  • Users have to explicitly intend to create a bad CloudEvent manually (note: I think we should improve our error messages in this case, so that it's clear when an exception is being thrown, why exactly something went wrong)
  • Allow receipt of events from external systems that may be generating bad/non-conformant events
  • Prevent a user from sending bad events using this SDK, ensuring that events coming from systems using this SDK are interoperable with other conformant systems

@grant
Copy link
Member

grant commented Aug 27, 2020

Thanks for investigating :) Sounds fine.

My opinion is a little different (validation should be explicitly requested by the user, not done in certain cases), but the above proposal sounds fine so long as folks don't get unexpected errors.

lance added 2 commits August 27, 2020 14:24
This commit adds a second, optional boolean parameter to the `CloudEvent`
constructor. When `false` is provided, the event constructor will not
perform validation of the event properties, values and extension names.

Fixes: cloudevents#325

Signed-off-by: Lance Ball <lball@redhat.com>
This commit modifies the ValidationError class so that the error message
string includes the JSON.stringified version of any schema validation
errors. It also makes the HTTP.toEvent() function create CloudEvent
objects with loose/no validation.

Incorporates comments from cloudevents#328

Signed-off-by: Lance Ball <lball@redhat.com>
@lance lance force-pushed the 325-loose-validation branch from 252555f to 60b22a7 Compare August 28, 2020 00:40
@lance
Copy link
Member Author

lance commented Aug 28, 2020

@cloudevents/sdk-javascript-maintainers I have made the changes noted in the comments. You can see the Message changes tested here: https://github.com/cloudevents/sdk-javascript/pull/328/files#diff-8b36d95f2fcd988540ae11f4206992cfR53-R87 and the CloudEvent changes tested here https://github.com/cloudevents/sdk-javascript/pull/328/files#diff-9f6cd81066208bf471aae16589fa3389R24-R38. I have also modified the ValidationError class to provide much more information in the error message when an event instance is invalid https://github.com/cloudevents/sdk-javascript/pull/328/files#diff-43312dc1cddf7a559d27b62f8d838c03R11-R22. PTAL

@lholmquist
Copy link
Contributor

@lance I think this is ready to be merged?

@lance lance merged commit 1fa3a05 into cloudevents:main Sep 8, 2020
@lance lance deleted the 325-loose-validation branch September 8, 2020 19:32
lholmquist pushed a commit to lholmquist/sdk-javascript that referenced this pull request Sep 8, 2020
* feat: add a constructor parameter for loose validation

This commit adds a second, optional boolean parameter to the `CloudEvent`
constructor. When `false` is provided, the event constructor will not
perform validation of the event properties, values and extension names.

This commit also modifies the ValidationError class so that the error message
string includes the JSON.stringified version of any schema validation
errors. It also makes the HTTP.toEvent() function create CloudEvent
objects with loose/no validation.

Incorporates comments from cloudevents#328

Fixes: cloudevents#325

Signed-off-by: Lance Ball <lball@redhat.com>
lance added a commit that referenced this pull request Sep 9, 2020
* feat: add a constructor parameter for loose validation

This commit adds a second, optional boolean parameter to the `CloudEvent`
constructor. When `false` is provided, the event constructor will not
perform validation of the event properties, values and extension names.

This commit also modifies the ValidationError class so that the error message
string includes the JSON.stringified version of any schema validation
errors. It also makes the HTTP.toEvent() function create CloudEvent
objects with loose/no validation.

Incorporates comments from #328

Fixes: #325

Signed-off-by: Lance Ball <lball@redhat.com>
lance added a commit to lance/sdk-javascript that referenced this pull request Sep 9, 2020
* chore(example): Replaced body parser with express JSON parser (cloudevents#334)

Signed-off-by: Philip Hayes <phayes@redhat.com>

Co-authored-by: Philip Hayes <phayes@redhat.com>

* fix: upgrade cloudevents from 3.0.1 to 3.1.0 (cloudevents#335)

Snyk has created this PR to upgrade cloudevents from 3.0.1 to 3.1.0.

See this package in npm:
https://www.npmjs.com/package/cloudevents

See this project in Snyk:
https://app.snyk.io/org/lance/project/cb2960b0-db0c-4e77-9ab2-e78efded812e?utm_source=github&utm_medium=upgrade-pr

Co-authored-by: snyk-bot <snyk-bot@snyk.io>
Signed-off-by: Lucas Holmquist <lholmqui@redhat.com>

* feat: add a constructor parameter for loose validation (cloudevents#328)

* feat: add a constructor parameter for loose validation

This commit adds a second, optional boolean parameter to the `CloudEvent`
constructor. When `false` is provided, the event constructor will not
perform validation of the event properties, values and extension names.

This commit also modifies the ValidationError class so that the error message
string includes the JSON.stringified version of any schema validation
errors. It also makes the HTTP.toEvent() function create CloudEvent
objects with loose/no validation.

Incorporates comments from cloudevents#328

Fixes: cloudevents#325

Signed-off-by: Lance Ball <lball@redhat.com>

Co-authored-by: Philip Hayes <philip@deewhy.ie>
Co-authored-by: Philip Hayes <phayes@redhat.com>
Co-authored-by: snyk-bot <snyk-bot@snyk.io>
Co-authored-by: Lance Ball <lball@redhat.com>
lance added a commit to lance/sdk-javascript that referenced this pull request Sep 9, 2020
* feat: add a constructor parameter for loose validation

This commit adds a second, optional boolean parameter to the `CloudEvent`
constructor. When `false` is provided, the event constructor will not
perform validation of the event properties, values and extension names.

This commit also modifies the ValidationError class so that the error message
string includes the JSON.stringified version of any schema validation
errors. It also makes the HTTP.toEvent() function create CloudEvent
objects with loose/no validation.

Incorporates comments from cloudevents#328

Fixes: cloudevents#325

Signed-off-by: Lance Ball <lball@redhat.com>
lance added a commit that referenced this pull request Sep 11, 2020
* feat: add a constructor parameter for loose validation

This commit adds a second, optional boolean parameter to the `CloudEvent`
constructor. When `false` is provided, the event constructor will not
perform validation of the event properties, values and extension names.

This commit also modifies the ValidationError class so that the error message
string includes the JSON.stringified version of any schema validation
errors. It also makes the HTTP.toEvent() function create CloudEvent
objects with loose/no validation.

Incorporates comments from #328

Fixes: #325

Signed-off-by: Lance Ball <lball@redhat.com>
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
module/lib Related to the main source code type/enhancement New feature or request version/3.x Issues related to the 3.0 release of this library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Loose event validation
3 participants