Expand description
Matches the end of a route.
Note that not including end()
may result in shorter paths like
/math
unintentionally matching /math/sum
.
Example
use warp::Filter;
// Matches '/'
let hello = warp::path::end()
.map(|| "Hello, World!");
Examples found in repository?
More examples
examples/file.rs (line 10)
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
async fn main() {
pretty_env_logger::init();
let readme = warp::get()
.and(warp::path::end())
.and(warp::fs::file("./README.md"));
// dir already requires GET...
let examples = warp::path("ex").and(warp::fs::dir("./examples/"));
// GET / => README.md
// GET /ex/... => ./examples/..
let routes = readme.or(examples);
warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}
examples/websockets_chat.rs (line 44)
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
async fn main() {
pretty_env_logger::init();
// Keep track of all connected users, key is usize, value
// is a websocket sender.
let users = Users::default();
// Turn our "state" into a new Filter...
let users = warp::any().map(move || users.clone());
// GET /chat -> websocket upgrade
let chat = warp::path("chat")
// The `ws()` filter will prepare Websocket handshake...
.and(warp::ws())
.and(users)
.map(|ws: warp::ws::Ws, users| {
// This will call our function if the handshake succeeds.
ws.on_upgrade(move |socket| user_connected(socket, users))
});
// GET / -> index html
let index = warp::path::end().map(|| warp::reply::html(INDEX_HTML));
let routes = index.or(chat);
warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}
examples/handlebars_template.rs (line 50)
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
async fn main() {
let template = "<!DOCTYPE html>
<html>
<head>
<title>Warp Handlebars template example</title>
</head>
<body>
<h1>Hello {{user}}!</h1>
</body>
</html>";
let mut hb = Handlebars::new();
// register the template
hb.register_template_string("template.html", template)
.unwrap();
// Turn Handlebars instance into a Filter so we can combine it
// easily with others...
let hb = Arc::new(hb);
// Create a reusable closure to render template
let handlebars = move |with_template| render(with_template, hb.clone());
//GET /
let route = warp::get()
.and(warp::path::end())
.map(|| WithTemplate {
name: "template.html",
value: json!({"user" : "Warp"}),
})
.map(handlebars);
warp::serve(route).run(([127, 0, 0, 1], 3030)).await;
}
examples/sse_chat.rs (line 47)
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 13)
≺ ≻
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;
}