pub fn param<T: FromStr + Send + 'static>(
) -> impl Filter<Extract = (T,), Error = Rejection> + Copy
Expand description
Extract a parameter from a path segment.
This will try to parse a value from the current request path
segment, and if successful, the value is returned as the Filter
’s
“extracted” value.
If the value could not be parsed, rejects with a 404 Not Found
.
Example
use warp::Filter;
let route = warp::path::param()
.map(|id: u32| {
format!("You asked for /{}", id)
});
Examples found in repository?
More examples
examples/body.rs (line 20)
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
async fn main() {
pretty_env_logger::init();
// POST /employees/:rate {"name":"Sean","rate":2}
let promote = warp::post()
.and(warp::path("employees"))
.and(warp::path::param::<u32>())
// Only accept bodies smaller than 16kb...
.and(warp::body::content_length_limit(1024 * 16))
.and(warp::body::json())
.map(|rate, mut employee: Employee| {
employee.rate = rate;
warp::reply::json(&employee)
});
warp::serve(promote).run(([127, 0, 0, 1], 3030)).await
}
examples/sse_chat.rs (line 24)
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
async fn main() {
pretty_env_logger::init();
// Keep track of all connected users, key is usize, value
// is an event stream sender.
let users = Arc::new(Mutex::new(HashMap::new()));
// Turn our "state" into a new Filter...
let users = warp::any().map(move || users.clone());
// POST /chat -> send message
let chat_send = warp::path("chat")
.and(warp::post())
.and(warp::path::param::<usize>())
.and(warp::body::content_length_limit(500))
.and(
warp::body::bytes().and_then(|body: bytes::Bytes| async move {
std::str::from_utf8(&body)
.map(String::from)
.map_err(|_e| warp::reject::custom(NotUtf8))
}),
)
.and(users.clone())
.map(|my_id, msg, users| {
user_message(my_id, msg, &users);
warp::reply()
});
// GET /chat -> messages stream
let chat_recv = warp::path("chat").and(warp::get()).and(users).map(|users| {
// reply using server-sent events
let stream = user_connected(users);
warp::sse::reply(warp::sse::keep_alive().stream(stream))
});
// GET / -> index html
let index = warp::path::end().map(|| {
warp::http::Response::builder()
.header("content-type", "text/html; charset=utf-8")
.body(INDEX_HTML)
});
let routes = index.or(chat_recv).or(chat_send);
warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}
examples/routing.rs (line 50)
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
async fn main() {
pretty_env_logger::init();
// We'll start simple, and gradually show how you combine these powers
// into super powers!
// GET /
let hello_world = warp::path::end().map(|| "Hello, World at root!");
// GET /hi
let hi = warp::path("hi").map(|| "Hello, World!");
// How about multiple segments? First, we could use the `path!` macro:
//
// GET /hello/from/warp
let hello_from_warp = warp::path!("hello" / "from" / "warp").map(|| "Hello from warp!");
// Fine, but how do I handle parameters in paths?
//
// GET /sum/:u32/:u32
let sum = warp::path!("sum" / u32 / u32).map(|a, b| format!("{} + {} = {}", a, b, a + b));
// Any type that implements FromStr can be used, and in any order:
//
// GET /:u16/times/:u16
let times =
warp::path!(u16 / "times" / u16).map(|a, b| format!("{} times {} = {}", a, b, a * b));
// Oh shoot, those math routes should be mounted at a different path,
// is that possible? Yep.
//
// GET /math/sum/:u32/:u32
// GET /math/:u16/times/:u16
let math = warp::path("math");
let _sum = math.and(sum);
let _times = math.and(times);
// What! And? What's that do?
//
// It combines the filters in a sort of "this and then that" order. In
// fact, it's exactly what the `path!` macro has been doing internally.
//
// GET /bye/:string
let bye = warp::path("bye")
.and(warp::path::param())
.map(|name: String| format!("Good bye, {}!", name));
// Ah, can filters do things besides `and`?
//
// Why, yes they can! They can also `or`! As you might expect, `or` creates
// a "this or else that" chain of filters. If the first doesn't succeed,
// then it tries the other.
//
// So, those `math` routes could have been mounted all as one, with `or`.
//
// GET /math/sum/:u32/:u32
// GET /math/:u16/times/:u16
let math = warp::path("math").and(sum.or(times));
// We can use the end() filter to match a shorter path
let help = warp::path("math")
// Careful! Omitting the following line would make this filter match
// requests to /math/sum/:u32/:u32 and /math/:u16/times/:u16
.and(warp::path::end())
.map(|| "This is the Math API. Try calling /math/sum/:u32/:u32 or /math/:u16/times/:u16");
let math = help.or(math);
// Let's let people know that the `sum` and `times` routes are under `math`.
let sum = sum.map(|output| format!("(This route has moved to /math/sum/:u16/:u16) {}", output));
let times =
times.map(|output| format!("(This route has moved to /math/:u16/times/:u16) {}", output));
// It turns out, using `or` is how you combine everything together into
// a single API. (We also actually haven't been enforcing that the
// method is GET, so we'll do that too!)
//
// GET /
// GET /hi
// GET /hello/from/warp
// GET /bye/:string
// GET /math/sum/:u32/:u32
// GET /math/:u16/times/:u16
let routes = warp::get().and(
hello_world
.or(hi)
.or(hello_from_warp)
.or(bye)
.or(math)
.or(sum)
.or(times),
);
// Note that composing filters for many routes may increase compile times (because it uses a lot of generics).
// If you wish to use dynamic dispatch instead and speed up compile times while
// making it slightly slower at runtime, you can use Filter::boxed().
warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}