-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Type-safe path/query parameter handling, using serde #70
Comments
open question: will this obsolete |
For query params, it is already possible:
There are two serve deserialiser that seems to do that: For path parameters, I think that would be quite a bit more complicated to do. Maybe add a |
it is question of ergonomics. how to make it easy to use. also you can extract data from urlencoded or multipart body, in that case you need to deal with bytes stream. i am not sure about |
does anyone want to experiment with this issue? |
I've been thinking about something like this, should be backward compatible. #[derive(Deserialize)]
struct MyQueryParams {
name: String,
}
pub fn my_handler(req: HttpRequest<AppState>, params: MyQueryParams) -> _ {
...
}
let app = Application::new()
.resource("/index.html", |r| r.h(
WithParams::<MyQueryParams>::(my_handler)))
let app = Application::new()
.resource("/index.html", |r| r.h(
WithJson::<MyQueryParams>::(my_handler)))
let app = Application::new()
.resource("/index.html", |r| r.h(
WithFormData::<MyQueryParams>::(my_handler))) |
I'm thinking that the old way to extract query params from request on demand seems less verbose. |
i added HttpRequest::extract() api @radix @DoumanAsh what do you think? |
@fafhrd91 Nice! I assume that the result comes back as an A raw |
by default it returns |
I am not sure about Path/Query types. And should extractor use both path match info and query params at the same time |
Ah, I see. I still think that this is the kind of thing that couldn't hurt to be documented somewhere — a user of the library (like myself) will almost certainly want to return specific types of errors to clients on a bad validation, and it's not obvious that it sends back a 400 without looking at source code.
I'm personally still ramping up to the point where I have any reasonable intuition as to what a good Rust API looks like, but I have to admit that understanding exactly what That said, maybe retooling the API to use methods like
Well the good part about your current implementation is that you could have a |
@brandur you sound reasonable :) I'll add |
I changed api |
@fafhrd91 That looks neat 👌 |
@brandur there is user guide section on error handling in actix-web https://actix.github.io/actix-web/guide/qs_4_5.html |
Wow, that's awesome! A couple questions:
Ah neat. Thanks! By the way, I wrote a post that talks about |
Wow, that's awesome! A couple questions:
Can you specify a with that will take a parameter type can handle a query and path?
It is easy to add new extractor, you just need to implement `HttpRequestExtractor` trait. I need to add `PathAndQuery` type but
I am still thinking about design, maybe it is possible to use curring. In any case I will add path and query extractor in one way or another.
(Maybe stupid question, but) That will take either sync or async handler right? (i.e., You don't need something like the a vs. f distinction.)
`with()` accepts both. I’d like to get rid of `.f()` and `.a()` and replace it with one function, but that may need `impl Trait`.
Ah neat. Thanks!
By the way, I wrote a post that talks about actix-web <https://brandur.org/rust-web> that's getting some attention on HN right now, which you might be interested to read. If you do, let me know if you find any technical inconsistencies.
I already read it :) nice article! I’d probably use error handling differently but that is up to you.
|
Ah I see! Okay, in that case: great.
Thanks! If the error handling is the only thing that I got wrong, then I consider myself quite lucky ;) |
Extractors look great, thanks @fafhrd91 ! |
I simplified extractor a little, Path example. Thoughts? |
I don't know what the previous way of doing this was, but I like how the code looks in the "Path example". |
@fafhrd91 what if you want both a request extractor and the request passed to your handler? e.g. to get the request body while also accessing arguments? shouldn't the handlers take both the info and the request? |
@radix state and request are part of extractor implementation https://actix.github.io/actix-web/actix_web/struct.Path.html#method.request |
@brandur added multiple extractor params, it is not elegant at the moment |
@fafhrd91 Nice!!! IMO, it'd be slightly more elegant if the BTW, I didn't notice the |
you can access request and state with Query::request() and Query::state() methods, same for |
added fn index(req: HttpRequest<S>, path: Path<Params, S>) -> ... {
unimplemented!()
}
fn main() {
let app = Application::with_state(State{}).resource(
"/{username}/index.html",
|r| r.method(Method::GET).with2(index)); // <- use `with2` extractor
} |
do we really need |
Wow! The type system here continues to amaze in what's possible ...
Yeah +1. |
i think this feature is more or less completed it is even possible to use tuples, so you dont need to define type fn index(info: Path<(String, u32)>) -> Result<String> {
Ok(format!("Welcome {}! {}", info.0, info.1))
}
fn main() {
let app = Application::new().resource(
"/{username}/{count}/?index.html", // <- define path parameters
|r| r.method(Method::GET).with(index)); // <- use `with` extractor
} |
@fafhrd91 that is AWESOME! |
one question is about fn index(info: Path<(String, u32)>, state: State<S>) -> Result<String> {
Ok(format!("Welcome {}! {}", info.0, info.1))
}
fn main() {
let app = Application::new().resource(
"/{username}/{count}/index.html", // <- define path parameters
|r| r.method(Method::GET).with2(index)); // <- use `with` extractor
} |
any ideas from what module extractors should be exported? right now there are, |
|
closing, I think most of extractors are implemented. lets create separate issues for extra extractors. here is list of available extractors https://actix.github.io/actix-web/actix_web/trait.FromRequest.html |
I just want to say that I gave this a try today and it is absolutely fantastic! Amazing work. |
Users should be able to define structures that hold parameters that need to be passed to a request handler. We could use the serde
Deserialize
trait. The goal is to make it easier for users to access parameters without having to deal with error-handling themselves, and hopefully to avoid the current situation where making a typo in your handler vs your route means that you get a runtime error instead of a compile-time error.The goal is to somehow allow the user to type this:
and then, define a handler like this:
or, alternatively:
This will require some way to declare the route for my_handler with MyParams.
The text was updated successfully, but these errors were encountered: