use super::*; use crate::{error_handling::HandleErrorLayer, extract::OriginalUri, response::IntoResponse, Json}; use serde_json::{json, Value}; use tower::{limit::ConcurrencyLimitLayer, timeout::TimeoutLayer}; #[crate::test] async fn basic() { let one = Router::new() .route("/foo", get(|| async {})) .route("/bar", get(|| async {})); let two = Router::new().route("/baz", get(|| async {})); let app = one.merge(two); let client = TestClient::new(app); let res = client.get("/foo").send().await; assert_eq!(res.status(), StatusCode::OK); let res = client.get("/bar").send().await; assert_eq!(res.status(), StatusCode::OK); let res = client.get("/baz").send().await; assert_eq!(res.status(), StatusCode::OK); let res = client.get("/qux").send().await; assert_eq!(res.status(), StatusCode::NOT_FOUND); } #[crate::test] async fn multiple_ors_balanced_differently() { let one = Router::new().route("/one", get(|| async { "one" })); let two = Router::new().route("/two", get(|| async { "two" })); let three = Router::new().route("/three", get(|| async { "three" })); let four = Router::new().route("/four", get(|| async { "four" })); test( "one", one.clone() .merge(two.clone()) .merge(three.clone()) .merge(four.clone()), ) .await; test( "two", one.clone() .merge(two.clone()) .merge(three.clone().merge(four.clone())), ) .await; test( "three", one.clone() .merge(two.clone().merge(three.clone()).merge(four.clone())), ) .await; test("four", one.merge(two.merge(three.merge(four)))).await; async fn test(name: &str, app: Router) { let client = TestClient::new(app); for n in ["one", "two", "three", "four"].iter() { println!("running: {name} / {n}"); let res = client.get(&format!("/{n}")).send().await; assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.text().await, *n); } } } #[crate::test] async fn nested_or() { let bar = Router::new().route("/bar", get(|| async { "bar" })); let baz = Router::new().route("/baz", get(|| async { "baz" })); let bar_or_baz = bar.merge(baz); let client = TestClient::new(bar_or_baz.clone()); assert_eq!(client.get("/bar").send().await.text().await, "bar"); assert_eq!(client.get("/baz").send().await.text().await, "baz"); let client = TestClient::new(Router::new().nest("/foo", bar_or_baz)); assert_eq!(client.get("/foo/bar").send().await.text().await, "bar"); assert_eq!(client.get("/foo/baz").send().await.text().await, "baz"); } #[crate::test] async fn or_with_route_following() { let one = Router::new().route("/one", get(|| async { "one" })); let two = Router::new().route("/two", get(|| async { "two" })); let app = one.merge(two).route("/three", get(|| async { "three" })); let client = TestClient::new(app); let res = client.get("/one").send().await; assert_eq!(res.status(), StatusCode::OK); let res = client.get("/two").send().await; assert_eq!(res.status(), StatusCode::OK); let res = client.get("/three").send().await; assert_eq!(res.status(), StatusCode::OK); } #[crate::test] async fn layer() { let one = Router::new().route("/foo", get(|| async {})); let two = Router::new() .route("/bar", get(|| async {})) .layer(ConcurrencyLimitLayer::new(10)); let app = one.merge(two); let client = TestClient::new(app); let res = client.get("/foo").send().await; assert_eq!(res.status(), StatusCode::OK); let res = client.get("/bar").send().await; assert_eq!(res.status(), StatusCode::OK); } #[crate::test] async fn layer_and_handle_error() { let one = Router::new().route("/foo", get(|| async {})); let two = Router::new() .route("/timeout", get(std::future::pending::<()>)) .layer( ServiceBuilder::new() .layer(HandleErrorLayer::new(|_| async { StatusCode::REQUEST_TIMEOUT })) .layer(TimeoutLayer::new(Duration::from_millis(10))), ); let app = one.merge(two); let client = TestClient::new(app); let res = client.get("/timeout").send().await; assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT); } #[crate::test] async fn nesting() { let one = Router::new().route("/foo", get(|| async {})); let two = Router::new().nest("/bar", Router::new().route("/baz", get(|| async {}))); let app = one.merge(two); let client = TestClient::new(app); let res = client.get("/bar/baz").send().await; assert_eq!(res.status(), StatusCode::OK); } #[crate::test] async fn boxed() { let one = Router::new().route("/foo", get(|| async {})); let two = Router::new().route("/bar", get(|| async {})); let app = one.merge(two); let client = TestClient::new(app); let res = client.get("/bar").send().await; assert_eq!(res.status(), StatusCode::OK); } #[crate::test] async fn many_ors() { let app = Router::new() .route("/r1", get(|| async {})) .merge(Router::new().route("/r2", get(|| async {}))) .merge(Router::new().route("/r3", get(|| async {}))) .merge(Router::new().route("/r4", get(|| async {}))) .merge(Router::new().route("/r5", get(|| async {}))) .merge(Router::new().route("/r6", get(|| async {}))) .merge(Router::new().route("/r7", get(|| async {}))); let client = TestClient::new(app); for n in 1..=7 { let res = client.get(&format!("/r{n}")).send().await; assert_eq!(res.status(), StatusCode::OK); } let res = client.get("/r8").send().await; assert_eq!(res.status(), StatusCode::NOT_FOUND); } #[crate::test] async fn services() { use crate::routing::get_service; let app = Router::new() .route( "/foo", get_service(service_fn(|_: Request
| async { Ok::<_, Infallible>(Response::new(Body::empty())) })), ) .merge(Router::new().route( "/bar", get_service(service_fn(|_: Request| async { Ok::<_, Infallible>(Response::new(Body::empty())) })), )); let client = TestClient::new(app); let res = client.get("/foo").send().await; assert_eq!(res.status(), StatusCode::OK); let res = client.get("/bar").send().await; assert_eq!(res.status(), StatusCode::OK); } async fn all_the_uris( uri: Uri, OriginalUri(original_uri): OriginalUri, req: Request, ) -> impl IntoResponse { Json(json!({ "uri": uri.to_string(), "request_uri": req.uri().to_string(), "original_uri": original_uri.to_string(), })) } #[crate::test] async fn nesting_and_seeing_the_right_uri() { let one = Router::new().nest("/foo/", Router::new().route("/bar", get(all_the_uris))); let two = Router::new().route("/foo", get(all_the_uris)); let client = TestClient::new(one.merge(two)); let res = client.get("/foo/bar").send().await; assert_eq!(res.status(), StatusCode::OK); assert_eq!( res.json::