HELP: filters inside .then never get executed
jarvjani opened this issue · 1 comments
Sorry, i could not access discord, registration fails due to some server errors, so i created issue here
Version
[dependencies]
warp = {version = "0.3.3",features = ["tls"], default-features = false}
tokio = { version = "1.24.2", features = ["full"] }
Platform
Ubuntu 20.04 WSL2
Description
I am trying to create a API with very few filters, since i experiences very slow build times when i implemented all the endpoints with own filters.Currently having +60 handlers in my project. Build times increased to upwards of 5 minutes. I am now using match to execute different handlers for endpoints that use similiar kind of http requests. The problem comes when i try to add any kind of new handler, the code gets increasinly more complex. I provided most simple example of my approach that doesn't work. The question is, how can i make this work?
Main.rs:
use std::collections::HashMap;
use warp::{self, Filter};
use warp::http::Method;
use warp::http::Response;
#[tokio::main]
async fn main() {
let route = warp::path("api")
.and(warp::path::param())
.and(warp::method())
.then( |param:String,method| async move{
match method{
Method::GET=>{
match param.as_str(){
/* test command:
curl --verbose http://localhost:8001/api/user
*/
"user"=> {
return Response::builder()
.status(200)
.body(String::from("Heres your users"))
},
_=>{
return Response::builder()
.status(501)
.body(String::from("Not implemented"))
}
}
},
Method::POST=>{
match param.as_str(){
/* test command:
curl --verbose --data "{\"user_id\":\"123\",\"name\":\"john\"}" http://localhost:8001/api/user
*/
"user"=> {
warp::body::json()
.then(|json:HashMap<String,String>|async move{
/* why this one never gets executed? */
println!("{:?}",json);
return Response::builder()
.status(200)
.body(format!("inserting user!"))
});
return Response::builder()
.status(400)
.body(String::from("invalid request :("))
},
_=>{
return Response::builder()
.status(501)
.body(String::from("Not implemented"))
}
}
}
_=> return Response::builder()
.status(400)
.body(String::from("Method not supported"))
}
}
);
warp::serve(route)
.run(([0, 0, 0, 0],8001)).await;
}
i don't understand how and why this works in the multipart.rs example:
https://github.com/seanmonstar/warp/blob/master/examples/multipart.rs
i want to do like in multipart.rs example, extract something from the request inside a filter:
https://github.com/seanmonstar/warp/blob/master/examples/multipart.rs
use bytes::BufMut;
use futures_util::TryStreamExt;
use warp::multipart::FormData;
use warp::Filter;
#[tokio::main]
async fn main() {
// Running curl -F file=@.gitignore 'localhost:3030/' should print [("file", ".gitignore", "\n/target\n**/*.rs.bk\nCargo.lock\n.idea/\nwarp.iml\n")]
let route = warp::multipart::form().and_then(|form: FormData| async move {
let field_names: Vec<_> = form
.and_then(|mut field| async move {
let mut bytes: Vec<u8> = Vec::new();
// field.data() only returns a piece of the content, you should call over it until it replies None
while let Some(content) = field.data().await {
let content = content.unwrap();
bytes.put(content);
}
Ok((
field.name().to_string(),
field.filename().unwrap().to_string(),
String::from_utf8_lossy(&*bytes).to_string(),
))
})
.try_collect()
.await
.unwrap();
Ok::<_, warp::Rejection>(format!("{:?}", field_names))
});
warp::serve(route).run(([127, 0, 0, 1], 3030)).await;
}
i don't understand how awaiting on the filter actually works, and why i cannot await on .then or .and_then? is it just FormData thing?
I run the curl command : curl --data "{"user_id":"123","name":"john"}" http://localhost:8001/api/user
I expected to see this happen:
inserting user!
Instead, this happened:
invalid request :(
Ended up using peek() to get the path parameter, so i don't have to do nested filters.