Files
axum/src/tests/fallback.rs
T
David Pedersen 1634e67e99 Stores routes in a map (#408)
With https://github.com/tokio-rs/axum/pull/404 and https://github.com/tokio-rs/axum/pull/402 all routes now have the same types and thus we don't need to nest them but can instead store them all in a map. This simplifies the routing quite a bit and is faster as well.

High level changes:
- Routes are now stored in a `HashMap<RouteId, Route<B>>`.
- `Router::or` is renamed to `Router::merge` because thats what it does now. It copies all routes from one router to another. This also means overlapping routes will cause a panic which is nice win.
- `Router::merge` now only accepts `Router`s so added `Router::fallback` for adding a global 404 handler.
- The `Or` service has been removed.
- `Router::layer` now only adds layers to the routes you actually have meaning middleware runs _after_ routing. I believe that addresses https://github.com/tokio-rs/axum/issues/380 but will test that on another branch.
2021-10-25 20:49:39 +02:00

97 lines
2.9 KiB
Rust

use super::*;
use crate::handler::Handler;
#[tokio::test]
async fn basic() {
let app = Router::new()
.route("/foo", get(|| async {}))
.fallback((|| async { "fallback" }).into_service());
let client = TestClient::new(app);
assert_eq!(client.get("/foo").send().await.status(), StatusCode::OK);
let res = client.get("/does-not-exist").send().await;
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.text().await, "fallback");
}
#[tokio::test]
async fn nest() {
let app = Router::new()
.nest("/foo", Router::new().route("/bar", get(|| async {})))
.fallback((|| async { "fallback" }).into_service());
let client = TestClient::new(app);
assert_eq!(client.get("/foo/bar").send().await.status(), StatusCode::OK);
let res = client.get("/does-not-exist").send().await;
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.text().await, "fallback");
}
#[tokio::test]
async fn nesting_with_fallback() {
let app = Router::new().nest(
"/foo",
Router::new()
.route("/bar", get(|| async {}))
.fallback((|| async { "fallback" }).into_service()),
);
let client = TestClient::new(app);
assert_eq!(client.get("/foo/bar").send().await.status(), StatusCode::OK);
// this shouldn't exist because the fallback is inside the nested router
let res = client.get("/does-not-exist").send().await;
assert_eq!(res.status(), StatusCode::NOT_FOUND);
// this should work since we get into the nested router
let res = client.get("/foo/does-not-exist").send().await;
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.text().await, "fallback");
}
#[tokio::test]
async fn or() {
let one = Router::new().route("/one", get(|| async {}));
let two = Router::new().route("/two", get(|| async {}));
let app = one
.merge(two)
.fallback((|| async { "fallback" }).into_service());
let client = TestClient::new(app);
assert_eq!(client.get("/one").send().await.status(), StatusCode::OK);
assert_eq!(client.get("/two").send().await.status(), StatusCode::OK);
let res = client.get("/does-not-exist").send().await;
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.text().await, "fallback");
}
#[tokio::test]
async fn fallback_on_or() {
let one = Router::new()
.route("/one", get(|| async {}))
.fallback((|| async { "fallback one" }).into_service());
let two = Router::new()
.route("/two", get(|| async {}))
.fallback((|| async { "fallback two" }).into_service());
let app = one.merge(two);
let client = TestClient::new(app);
assert_eq!(client.get("/one").send().await.status(), StatusCode::OK);
assert_eq!(client.get("/two").send().await.status(), StatusCode::OK);
let res = client.get("/does-not-exist").send().await;
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.text().await, "fallback two");
}