-
Notifications
You must be signed in to change notification settings - Fork 361
[RFC] Ergonomic improvements to payload deserialization for HTTP use cases #917
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
Comments
I would vote for option 2. I'd rather not introduce new extensions. I believe not many people know about them and that you can implement your own. Regarding error types, why do we need new error types for that |
Sounds good.
Good question -- the goal is that users should only be forced to handle errors that are thrown by their intended content-type deserializer. If we flip that decision to the server with this new API, we can strongly guarantee that only related error types will be thrown by using a more specific error type; so, when I'm calling
I'm open to feedback on this. This was basically my thought process:
|
That makes sense. I have no naming preference for the error types, tbh. Feel free to open a PR with these changes and we can discuss it further in code review. |
PR above is ready for review. (Sorry for the mention spam there, that was because of git amends + pushes to work on different laptops lol) |
BREAKING CHANGE: adds additional methods to the `RequestPayloadExt` trait. implements RFC #917
This issue is now closed. Comments on closed issues are hard for our team to see. |
Summary
This RFC proposes ergonomic improvements to payload deserialization for HTTP usecases.
Motivation
The
RequestPayloadExt
trait is used inlambda_http
to simplify extracting aRequest
's body intoa user-provided struct. The current version of the
RequestPayloadExt::payload
has the following docstring:The interpretation of how
payload
should behave when the content-type header is missing/unsupported is somewhat ambiguous. For example, there's no mention of what happens when the content-type header is missing. According to RFC 9110: HTTP Semantics,so, it's not unreasonable to assume that a generic
payload
function on an HTTPRequest
struct would also do a best-effort estimation of the content-type. The signature ofpayload
asks to handle multiplePayloadError
variants for different content types which may reinforce that assumption.The actual behavior is that when the content-type header is either missing or unsupported, the implementation assumes there is no content and returns
Ok(None)
; however, the docstring only calls outOk(None)
being returned "if no body is provided" which can lead to frustration when trying to figure out why the payload is not being recognized.The documentation needs an update to disambiguate the scenario where the content-type is missing or unsupported. Additionally, I've written a proposal for API ergonomics improvements when handling different content types below.
Proposal: Intent-Driven API Additions
We can use this as an opportunity to introduce a fix via intent-driven additions. For example, we can add
json()
andx_www_form_urlencoded()
methods to the Request that make it clear what the expected format should be:Option 1. (Preferred) Introduce a new extension trait,
RequestPayloadIntentExt
, with initial implementationsThe extension trait would have the following interface:
And initial implementations would go here:
Advantages
json()
andx_www_form_urlencoded()
.Drawbacks
RequestPayloadExt
: users may be confused why the two implementations exist, and surprised when they behave differentlyOption 2: Extend RequestPayloadExt trait with methods
json()
andx_www_form_urlencoded()
The trait could be modified as follows:
Advantages
payload
can reuse the implementations forjson
andxx_www_form_urlencoded
and share in improvements.Drawbacks
json
andx_www_form_urlencoded
.self.payload
to mimic the previous behavior.PayloadError::Json
andJsonPayloadError
coexisting in the same module.payload
and new methodsAlternative: Try all content types deserializers before returning None
Since both current (and I'm assuming future) content-type deserialization implementations leverage Serde's
Deserialize
trait as inputs, we can try both deserializers on the input when the content-type header is missing. For example, we can start with JSON, catch errors, then try x-www-form-urlencoded, etc...Advantages
Drawbacks
None
when the "content-type" header is empty, they may start handling requests that they expected to reject when the header is missing; consequently, they may be surprised at the new behavior and/or be forced to implement a different mechanism for denying requests without a content-type header.The text was updated successfully, but these errors were encountered: