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

Add middleware for unwrapping cloud events #93

Merged
merged 3 commits into from
Oct 13, 2019
Merged

Conversation

rynowak
Copy link
Collaborator

@rynowak rynowak commented Oct 13, 2019

Description

Fixes: #74

note: This relies on the fix for dapr/dapr#574 which has been merged.

This change introduces a middleware that can upwrap a structured cloud
event. This is the format used by dapr by default now for pub/sub
messaging. Adding the middleware makes it transparent to the developer
whether the data can from a cloud event or was a basic RPC call.

We're adding the middleware for this first since it's the most general
approach. It has a drawback compared with other approaches, performance.

Users could alternatively use the SDK from CloudEvents to read their
data without the middleware.

We might also want to add an MVC formatter in the future, which could do
the unwrapping and deserialization to a user-type in a single operation.

Issue reference

We strive to have all PR being opened based on an issue, where the problem or feature have been discussed prior to implementation.

Please reference the issue this PR will close: #74

Checklist

Please make sure you've completed the relevant tasks for this PR, out of the following list:

  • Code compiles correctly
  • Created/updated tests
  • Extended the documentation

Fixes: #74

note: This relies on the fix for dapr/dapr#574 which has been merged.

This change introduces a middleware that can upwrap a *structured* cloud
event. This is the format used by dapr by default now for pub/sub
messaging. Adding the middleware makes it transparent to the developer
whether the data can from a cloud event or was a basic RPC call.

We're adding the middleware for this first since it's the most general
approach. It has a drawback compared with other approaches, performance.

Users could alternatively use the SDK from CloudEvents to read their
data without the middleware.

We might also want to add an MVC formatter in the future, which could do
the unwrapping and deserialization to a user-type in a single operation.
@rynowak rynowak requested a review from amanbha October 13, 2019 03:07
return this.ProcessBodyAsync(httpContext, charSet);
}

private async Task ProcessBodyAsync(HttpContext httpContext, string charSet)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be slightly confusing to follow but there are 3-4 special cases that have to be handled here:

  • request body is not-UTF8 (S.T.J doesn't handle that natively)
  • event specifies datacontenttype that carries a charset (will be wiped out)
  • data is empty (super cool, super legal)
  • datacontenttype is empty (assume application/json)

LMK if you think anything here needs more documentation.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gah this is inefficient... I’ll think about it though. Also usually there’s a way to get at the original content type

@rynowak
Copy link
Collaborator Author

rynowak commented Oct 13, 2019

We're adding the middleware for this first since it's the most general
approach. It has a drawback compared with other approaches, performance.

Users could alternatively use the SDK from CloudEvents to read their
data without the middleware.

We might also want to add an MVC formatter in the future, which could do
the unwrapping and deserialization to a user-type in a single operation.

@davidfowl - let's argue 😀

Do we you know of anywhere else we've done this sort of thing in the stack? We had design approaches like this in the webhooks spike from a few years ago.

The most performant way I can think of to do this would be to subclass to:

  • write a formatter
  • use the json reader to advance to the data property
  • invoke the serializer to deserialize from the writer
  • throw away the rest of the payload

no extra allocations needed.

There's a little bit of a layering problem here with using a formatter, because you can't handle different content types differently (based on datacontenttype at that point - you already chose a formatter.


However this only works for MVC.

I think we want the middleware to exist regardless hence why I chose that.

@rynowak rynowak merged commit 2d9be29 into master Oct 13, 2019
@rynowak rynowak deleted the rynowak/cloud-events branch October 13, 2019 03:25
@davidfowl
Copy link

This would have been better as a formatter since dapr integration is pretty much MVC specific, though I don't have any real emotions about this doing crazy unwrapping besides how inefficient it is.

app.UseCloudEvents();
```

`UseCloudEvents()` registers the Cloud Events middleware in the request processing pipeline. This middleware will unwrap requests with Content-Type `application/cloudevents+json` so that application code can access the event payload in the request body directly. This is recommended when using pub/sub unless you have a need to process the event metadata yourself.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The metadata should be available via a feature (as well as the original content type).

}
else
{
using (var reader = new HttpRequestStreamReader(httpContext.Request.Body, Encoding.GetEncoding(charSet)))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nah, I don't want to put that complicated stuff in their code. The sender of event is the dapr runtime so this code is never going to execute. It's here for completeness, and will go away when we add .ReadAsJson to the framework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Handle Cloud Events from dapr in aspnetcore integration
3 participants