-
Notifications
You must be signed in to change notification settings - Fork 91
Decode application/x-www-form-urlencoded bodies #363
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
Conversation
ahl
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What should our approach be with regard to the OpenAPI description of APIs? Currently we claim they accept application/json only. I don't really want to say that they accept application/x-www-form-urlencoded as well, only because it uglies things up (and will fuck up progenitor, but that's my problem). I'm fine with just having it be un-expressed in OpenAPI, but wanted to get your opinion.
Does this make every endpoint accept I think the TS generator will be unaffected because we're specifically looking for the |
The current implementation does indeed make every endpoint accept |
I think we have some options. I don't know what endpoints are going to use this behavior--do we want them in the OpenAPI spec? How much do we care that an endpoint must use In short: I think we can be a little loosey goosey here without significant consequence... especially in light of competing priorities. |
If elided, defaults to "application/json". The requested content type is verified against the specified one by the handler.
|
I took updating this as a background task, and after a few tries I think I have something (c903eb8) that satisfies the desiderata. I'm not wild about needing to pass the content-type into the |
ahl
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking good. thanks for making the changes
two questions?
Are we going to use this in a place where we'll want progenitor support?
How does this work for nested structs? Looking briefly at the serde_urlencoded crate I think it produces a runtime error. Might we want to look at the schema for bodies to give a friendly error when the server starts?
| /// // Specifies the media type used to encode the request body | ||
| /// content_type = { "application/json" | "application/x-www-form-urlencoded" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is the best approach. The alternative I could think of is to have a wrapper type so that endpoints look something like..
async fn demo_handler_args_2urlencoded(
_rqctx: RequestCtx,
body: TypedBody<DemoJsonBody, FormUrlEncodedMarkerTypeOrWhatever>,
) -> Result<Response<Body>, HttpError> {
// ...
}I don't think that's actually better--it just moves the metadata from the macro to the type. It would be both messier and harder to see.
@davepacheco do you have any thoughts here?
| let content_type = | ||
| metadata.content_type.unwrap_or_else(|| "application/json".to_string()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we validate that this is application/x-www-form-urlencoded? What do you think about a trybuild test (the bad_endpointNNN.rs tests) to catch an invalid content type at build time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, ApiEndpointBodyContentType::from_mime_type raises an error on mime types that it doesn't recognize, but you're right that it's not at build time. I thought we should have only one place that knows which types are acceptable, but was hesitant to move ApiEndpointBodyContentType and the associated constants into dropshot_endpoint. fdc22c8 adds a simple check at build time and a new bad_endpoint16.rs test, but does duplicate the list of acceptable types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good; two small nits, but up to you if you want to change them
| /** application/x-www-form-urlencoded */ | ||
| UrlEncoded, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we care that the user says "application/x-www-form-urlencoded" or could we just let them give us any string and have the variant be Yolo(String)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In all but the UntypedBody case, we do care because we need to know how to decode the body.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry: I know we care what it is for decoding, but can we stuff that into a string rather than having Json and UrlEncoded as the two enumerated options?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mmm, we could, but I'm not sure I see the advantage. We could certainly add another Yolo variant for arbitrary types, but since these are the ones that we handle specially I think it makes sense to have variants for them. Otherwise why not just use strings for content type everywhere?
In the immediate use case I have, we won't need progenitor to handle the urlencoded endpoints (since it's for OAuth, for which we'll use third-party libs). So... maybe?
That's an excellent question; I hadn't thought of that at all. Is there an easy way to check for those? And could we take that as a follow-up? |
I'm fine with this being just filed as an issue for future work. I think the way to do it would be to look at the JsonSchema and make sure it's an object whose properties are all scalars. |
Yep, we sure can; thanks! Fixed in d1963f7. |
Indeed not, thank you. Also fixed in d1963f7. |
This is useful for compatibility with protocols such as OAuth 2.0 and SAML, which frequently use this encoding for request bodies. It is possible to work around this by using
UntypedBodyand decoding at the application level, but handling it in dropshot seems safer and less error-prone.