-
Notifications
You must be signed in to change notification settings - Fork 29
(feat) Add body parsing for POST requests. #24
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
This is really good work! Thank you very much. I'm going to leave a few comments in the source also, but here's some overall feedback. Ideally I could enable both behaviors (i.e. you check the url and then check the body or vise-versa) with a single |
let data = match *self { | ||
UrlParser => { | ||
// Parse the query string from the '?' character onwards | ||
match req.url.as_slice().find('?') { |
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 worry that this is pretty fragile for parsing. Using a more heavy-duty parser, if available, from the servo url crate would be better.
If you have an argument for why this won't break unexpectedly, then I'm fine with it.
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 agree that it's a bit dodgy, yeah. Servo's URL library has a function for parsing a URL and extracting the 'query' field, but to use it we would have to transform Request::url
into a full URL. We could do this by adding a .url()
function to Request
which is guaranteed to return a full, valid URL. Alternatively, we could construct a complete URL by adding a bogus domain, although I think this is just as dodgy as the current approach. I think the .url()
option is vastly better, and could be useful elsewhere (plus it insulates us from rust-http
).
@michaelsproul Thanks for your contribution. I left you a few comments, if you don't mind taking a look. If you don't want to/don't have time to make the changes, just let me know and we can take care of it. |
server.chain.link(UrlEncodedParser::for_body()); | ||
server.chain.link(FromFn::new(log_params)); | ||
server.listen(Ipv4Addr(127, 0, 0, 1), 3000); | ||
} |
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.
This is a really great addition to urlencoded that I overlooked, thanks
@reem: Regarding the overall structure, I'm very open to change. This is the other structure I was considering: Allow parsing of the URL and body independently by inserting values with different types into the struct UrlEncodedParser {
parse_url: bool,
parse_body: bool
} |
@michaelsproul I sort of like the way you only parse either the url or body but it may be too opinionated. How about storing: struct UrlEncodedParsed {
querystring: Option<HashMap<String, String>,
body: Option<HashMap<String, String>
} or something similar. The recent changes to Request and Response allow me to add new fields to them, and I'm thinking of moving Alloy to instead be a field of Request, meaning that you could instead write a mixin Trait and just add methods to Request, which better hides all of this complexity from the user. |
Yeah, looking into it a bit further I think we should allow users to parse parameters from both the URL and the body. Your idea about mixin traits for Requests is interesting. Adding methods like |
It's a tiny bit of conceptual overhead (methods come in scope with their traits) for a huge payoff in usability - no more mucking about in with If you could make the change we described in the last few posts (allow both with one declaration, store a type containing two Options) I'll merge this in. If you'd like to make later changes, I'll @mention you in an issue about it when I finish cleaning up the Request API. |
Ok, all done. I'm pretty happy with it now. Let me know if there's anything I can do on the main bit of Iron. I'd love to get involved. My timezone is UTC + 10h, but I'll be on IRC tomorrow morning (afternoon for you guys). |
Also removed use of soon to be deprecated `liburl` in favour of `servo/rust-url`.
Typo fixed. |
This looks good. Thank you again for contributing. If you're up for it, providing a nicer interface for Request::url (i.e. returning a Url struct that is a parsed version of the url with host, uri, port, querystring, etc.) would be awesome. Just go ahead and start hacking on it on a PR in iron/iron if you want to. |
(feat) Add body parsing for POST requests.
@michaelsproul It looks like |
Yeah, |
@reem that's essentially what we do in nickel.rs as well (putting the anymap on the request) and I think it pays of quite well. |
I've added a way to create middleware that parses either the url or body of a request for urlencoded data.
I've also removed use of soon to be deprecated
liburl
in favour of servo/rust-url, as per rust-lang/rust#15874.My approach intentionally doesn't permit parsing of requests with data in both the URL and the body, as this is a violation of HTTP convention (as far as I can ascertain, I'm willing to be wrong).
Close #21.