Replace route with Router::new().route() (#215)

This way there is now only one way to create a router:

```rust
use axum::{Router, handler::get};

let app = Router::new()
    .route("/foo", get(handler))
    .route("/foo", get(handler));
```

`nest` was changed in the same way:

```rust
use axum::Router;

let app = Router::new().nest("/foo", service);
```
This commit is contained in:
David Pedersen
2021-08-19 22:37:48 +02:00
committed by GitHub
parent 97b53768ba
commit ca4d9a2bb9
49 changed files with 652 additions and 625 deletions
+2 -2
View File
@@ -7,7 +7,7 @@ mod for_handlers {
#[tokio::test]
async fn get_handles_head() {
let app = route(
let app = Router::new().route(
"/",
get(|| async {
let mut headers = HeaderMap::new();
@@ -43,7 +43,7 @@ mod for_services {
#[tokio::test]
async fn get_handles_head() {
let app = route(
let app = Router::new().route(
"/",
get(service_fn(|_req: Request<Body>| async move {
let res = Response::builder()
+18 -13
View File
@@ -41,7 +41,7 @@ fn handle_error<E>(_: E) -> Result<StatusCode, Infallible> {
#[tokio::test]
async fn handler() {
let app = route(
let app = Router::new().route(
"/",
get(forever
.layer(timeout())
@@ -62,7 +62,7 @@ async fn handler() {
#[tokio::test]
async fn handler_multiple_methods_first() {
let app = route(
let app = Router::new().route(
"/",
get(forever
.layer(timeout())
@@ -84,7 +84,7 @@ async fn handler_multiple_methods_first() {
#[tokio::test]
async fn handler_multiple_methods_middle() {
let app = route(
let app = Router::new().route(
"/",
delete(unit)
.get(
@@ -109,7 +109,7 @@ async fn handler_multiple_methods_middle() {
#[tokio::test]
async fn handler_multiple_methods_last() {
let app = route(
let app = Router::new().route(
"/",
delete(unit).get(
forever
@@ -132,21 +132,22 @@ async fn handler_multiple_methods_last() {
#[test]
fn service_propagates_errors() {
let app = route::<_, Body>("/echo", service::post(Svc));
let app = Router::new().route::<_, Body>("/echo", service::post(Svc));
check_make_svc::<_, _, _, hyper::Error>(app.into_make_service());
}
#[test]
fn service_nested_propagates_errors() {
let app = route::<_, Body>("/echo", nest("/foo", service::post(Svc)));
let app =
Router::new().route::<_, Body>("/echo", Router::new().nest("/foo", service::post(Svc)));
check_make_svc::<_, _, _, hyper::Error>(app.into_make_service());
}
#[test]
fn service_handle_on_method() {
let app = route::<_, Body>(
let app = Router::new().route::<_, Body>(
"/echo",
service::get(Svc).handle_error(handle_error::<hyper::Error>),
);
@@ -156,7 +157,7 @@ fn service_handle_on_method() {
#[test]
fn service_handle_on_method_multiple() {
let app = route::<_, Body>(
let app = Router::new().route::<_, Body>(
"/echo",
service::get(Svc)
.post(Svc)
@@ -168,15 +169,17 @@ fn service_handle_on_method_multiple() {
#[test]
fn service_handle_on_router() {
let app =
route::<_, Body>("/echo", service::get(Svc)).handle_error(handle_error::<hyper::Error>);
let app = Router::new()
.route::<_, Body>("/echo", service::get(Svc))
.handle_error(handle_error::<hyper::Error>);
check_make_svc::<_, _, _, Infallible>(app.into_make_service());
}
#[test]
fn service_handle_on_router_still_impls_routing_dsl() {
let app = route::<_, Body>("/echo", service::get(Svc))
let app = Router::new()
.route::<_, Body>("/echo", service::get(Svc))
.handle_error(handle_error::<hyper::Error>)
.route("/", get(unit));
@@ -185,7 +188,8 @@ fn service_handle_on_router_still_impls_routing_dsl() {
#[test]
fn layered() {
let app = route::<_, Body>("/echo", get(unit))
let app = Router::new()
.route::<_, Body>("/echo", get(unit))
.layer(timeout())
.handle_error(handle_error::<BoxError>);
@@ -194,7 +198,8 @@ fn layered() {
#[tokio::test] // async because of `.boxed()`
async fn layered_boxed() {
let app = route::<_, Body>("/echo", get(unit))
let app = Router::new()
.route::<_, Body>("/echo", get(unit))
.layer(timeout())
.boxed()
.handle_error(handle_error::<BoxError>);
+60 -53
View File
@@ -4,10 +4,8 @@ use crate::{
extract,
handler::{any, delete, get, on, patch, post, Handler},
response::IntoResponse,
route,
routing::nest,
routing::MethodFilter,
service,
service, Router,
};
use bytes::Bytes;
use futures_util::future::Ready;
@@ -46,7 +44,9 @@ async fn hello_world() {
"users#create"
}
let app = route("/", get(root).post(foo)).route("/users", post(users_create));
let app = Router::new()
.route("/", get(root).post(foo))
.route("/users", post(users_create));
let addr = run_in_background(app).await;
@@ -75,7 +75,7 @@ async fn hello_world() {
#[tokio::test]
async fn consume_body() {
let app = route("/", get(|body: String| async { body }));
let app = Router::new().route("/", get(|body: String| async { body }));
let addr = run_in_background(app).await;
@@ -98,7 +98,7 @@ async fn deserialize_body() {
foo: String,
}
let app = route(
let app = Router::new().route(
"/",
post(|input: extract::Json<Input>| async { input.0.foo }),
);
@@ -124,7 +124,7 @@ async fn consume_body_to_json_requires_json_content_type() {
foo: String,
}
let app = route(
let app = Router::new().route(
"/",
post(|input: extract::Json<Input>| async { input.0.foo }),
);
@@ -156,7 +156,7 @@ async fn body_with_length_limit() {
const LIMIT: u64 = 8;
let app = route(
let app = Router::new().route(
"/",
post(|_body: extract::ContentLengthLimit<Bytes, LIMIT>| async {}),
);
@@ -202,16 +202,17 @@ async fn body_with_length_limit() {
#[tokio::test]
async fn routing() {
let app = route(
"/users",
get(|_: Request<Body>| async { "users#index" })
.post(|_: Request<Body>| async { "users#create" }),
)
.route("/users/:id", get(|_: Request<Body>| async { "users#show" }))
.route(
"/users/:id/action",
get(|_: Request<Body>| async { "users#action" }),
);
let app = Router::new()
.route(
"/users",
get(|_: Request<Body>| async { "users#index" })
.post(|_: Request<Body>| async { "users#create" }),
)
.route("/users/:id", get(|_: Request<Body>| async { "users#show" }))
.route(
"/users/:id/action",
get(|_: Request<Body>| async { "users#action" }),
);
let addr = run_in_background(app).await;
@@ -255,7 +256,7 @@ async fn routing() {
#[tokio::test]
async fn extracting_url_params() {
let app = route(
let app = Router::new().route(
"/users/:id",
get(|extract::Path(id): extract::Path<i32>| async move {
assert_eq!(id, 42);
@@ -288,7 +289,7 @@ async fn extracting_url_params() {
#[tokio::test]
async fn extracting_url_params_multiple_times() {
let app = route(
let app = Router::new().route(
"/users/:id",
get(|_: extract::Path<i32>, _: extract::Path<String>| async {}),
);
@@ -307,17 +308,18 @@ async fn extracting_url_params_multiple_times() {
#[tokio::test]
async fn boxing() {
let app = route(
"/",
on(MethodFilter::GET, |_: Request<Body>| async {
"hi from GET"
})
.on(MethodFilter::POST, |_: Request<Body>| async {
"hi from POST"
}),
)
.layer(tower_http::compression::CompressionLayer::new())
.boxed();
let app = Router::new()
.route(
"/",
on(MethodFilter::GET, |_: Request<Body>| async {
"hi from GET"
})
.on(MethodFilter::POST, |_: Request<Body>| async {
"hi from POST"
}),
)
.layer(tower_http::compression::CompressionLayer::new())
.boxed();
let addr = run_in_background(app).await;
@@ -345,22 +347,23 @@ async fn routing_between_services() {
"handler"
}
let app = route(
"/one",
service::get(service_fn(|_: Request<Body>| async {
Ok::<_, Infallible>(Response::new(Body::from("one get")))
}))
.post(service_fn(|_: Request<Body>| async {
Ok::<_, Infallible>(Response::new(Body::from("one post")))
}))
.on(
MethodFilter::PUT,
service_fn(|_: Request<Body>| async {
Ok::<_, Infallible>(Response::new(Body::from("one put")))
}),
),
)
.route("/two", service::on(MethodFilter::GET, any(handle)));
let app = Router::new()
.route(
"/one",
service::get(service_fn(|_: Request<Body>| async {
Ok::<_, Infallible>(Response::new(Body::from("one get")))
}))
.post(service_fn(|_: Request<Body>| async {
Ok::<_, Infallible>(Response::new(Body::from("one post")))
}))
.on(
MethodFilter::PUT,
service_fn(|_: Request<Body>| async {
Ok::<_, Infallible>(Response::new(Body::from("one put")))
}),
),
)
.route("/two", service::on(MethodFilter::GET, any(handle)));
let addr = run_in_background(app).await;
@@ -408,7 +411,7 @@ async fn middleware_on_single_route() {
"Hello, World!"
}
let app = route(
let app = Router::new().route(
"/",
get(handle.layer(
ServiceBuilder::new()
@@ -432,7 +435,7 @@ async fn service_in_bottom() {
Ok(Response::new(hyper::Body::empty()))
}
let app = route("/", service::get(service_fn(handler)));
let app = Router::new().route("/", service::get(service_fn(handler)));
run_in_background(app).await;
}
@@ -466,7 +469,7 @@ async fn test_extractor_middleware() {
async fn handler() {}
let app = route(
let app = Router::new().route(
"/",
get(handler.layer(extract::extractor_middleware::<RequireAuth>())),
);
@@ -493,7 +496,9 @@ async fn test_extractor_middleware() {
#[tokio::test]
async fn wrong_method_handler() {
let app = route("/", get(|| async {}).post(|| async {})).route("/foo", patch(|| async {}));
let app = Router::new()
.route("/", get(|| async {}).post(|| async {}))
.route("/foo", patch(|| async {}));
let addr = run_in_background(app).await;
@@ -547,7 +552,9 @@ async fn wrong_method_service() {
}
}
let app = route("/", service::get(Svc).post(Svc)).route("/foo", service::patch(Svc));
let app = Router::new()
.route("/", service::get(Svc).post(Svc))
.route("/foo", service::patch(Svc));
let addr = run_in_background(app).await;
@@ -588,7 +595,7 @@ async fn multiple_methods_for_one_handler() {
"Hello, World!"
}
let app = route("/", on(MethodFilter::GET | MethodFilter::POST, root));
let app = Router::new().route("/", on(MethodFilter::GET | MethodFilter::POST, root));
let addr = run_in_background(app).await;
+50 -45
View File
@@ -4,36 +4,39 @@ use std::collections::HashMap;
#[tokio::test]
async fn nesting_apps() {
let api_routes = route(
"/users",
get(|| async { "users#index" }).post(|| async { "users#create" }),
)
.route(
"/users/:id",
get(
|params: extract::Path<HashMap<String, String>>| async move {
format!(
"{}: users#show ({})",
params.get("version").unwrap(),
params.get("id").unwrap()
)
},
),
)
.route(
"/games/:id",
get(
|params: extract::Path<HashMap<String, String>>| async move {
format!(
"{}: games#show ({})",
params.get("version").unwrap(),
params.get("id").unwrap()
)
},
),
);
let api_routes = Router::new()
.route(
"/users",
get(|| async { "users#index" }).post(|| async { "users#create" }),
)
.route(
"/users/:id",
get(
|params: extract::Path<HashMap<String, String>>| async move {
format!(
"{}: users#show ({})",
params.get("version").unwrap(),
params.get("id").unwrap()
)
},
),
)
.route(
"/games/:id",
get(
|params: extract::Path<HashMap<String, String>>| async move {
format!(
"{}: games#show ({})",
params.get("version").unwrap(),
params.get("id").unwrap()
)
},
),
);
let app = route("/", get(|| async { "hi" })).nest("/:version/api", api_routes);
let app = Router::new()
.route("/", get(|| async { "hi" }))
.nest("/:version/api", api_routes);
let addr = run_in_background(app).await;
@@ -74,8 +77,8 @@ async fn nesting_apps() {
#[tokio::test]
async fn wrong_method_nest() {
let nested_app = route("/", get(|| async {}));
let app = crate::routing::nest("/", nested_app);
let nested_app = Router::new().route("/", get(|| async {}));
let app = Router::new().nest("/", nested_app);
let addr = run_in_background(app).await;
@@ -101,7 +104,7 @@ async fn wrong_method_nest() {
#[tokio::test]
async fn nesting_at_root() {
let app = nest("/", get(|uri: Uri| async move { uri.to_string() }));
let app = Router::new().nest("/", get(|uri: Uri| async move { uri.to_string() }));
let addr = run_in_background(app).await;
@@ -130,14 +133,16 @@ async fn nesting_at_root() {
#[tokio::test]
async fn nested_url_extractor() {
let app = nest(
let app = Router::new().nest(
"/foo",
nest(
Router::new().nest(
"/bar",
route("/baz", get(|uri: Uri| async move { uri.to_string() })).route(
"/qux",
get(|req: Request<Body>| async move { req.uri().to_string() }),
),
Router::new()
.route("/baz", get(|uri: Uri| async move { uri.to_string() }))
.route(
"/qux",
get(|req: Request<Body>| async move { req.uri().to_string() }),
),
),
);
@@ -164,11 +169,11 @@ async fn nested_url_extractor() {
#[tokio::test]
async fn nested_url_original_extractor() {
let app = nest(
let app = Router::new().nest(
"/foo",
nest(
Router::new().nest(
"/bar",
route(
Router::new().route(
"/baz",
get(|uri: extract::OriginalUri| async move { uri.0.to_string() }),
),
@@ -190,11 +195,11 @@ async fn nested_url_original_extractor() {
#[tokio::test]
async fn nested_service_sees_stripped_uri() {
let app = nest(
let app = Router::new().nest(
"/foo",
nest(
Router::new().nest(
"/bar",
route(
Router::new().route(
"/baz",
service_fn(|req: Request<Body>| async move {
let body = box_body(Body::from(req.uri().to_string()));
@@ -219,7 +224,7 @@ async fn nested_service_sees_stripped_uri() {
#[tokio::test]
async fn nest_static_file_server() {
let app = nest(
let app = Router::new().nest(
"/static",
service::get(tower_http::services::ServeDir::new(".")).handle_error(|error| {
Ok::<_, Infallible>((
+64 -46
View File
@@ -7,8 +7,10 @@ use super::*;
#[tokio::test]
async fn basic() {
let one = route("/foo", get(|| async {})).route("/bar", get(|| async {}));
let two = route("/baz", get(|| async {}));
let one = Router::new()
.route("/foo", get(|| async {}))
.route("/bar", get(|| async {}));
let two = Router::new().route("/baz", get(|| async {}));
let app = one.or(two);
let addr = run_in_background(app).await;
@@ -46,10 +48,10 @@ async fn basic() {
#[tokio::test]
async fn multiple_ors_balanced_differently() {
let one = route("/one", get(|| async { "one" }));
let two = route("/two", get(|| async { "two" }));
let three = route("/three", get(|| async { "three" }));
let four = route("/four", get(|| async { "four" }));
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",
@@ -105,8 +107,10 @@ async fn multiple_ors_balanced_differently() {
#[tokio::test]
async fn or_nested_inside_other_thing() {
let inner = route("/bar", get(|| async {})).or(route("/baz", get(|| async {})));
let app = nest("/foo", inner);
let inner = Router::new()
.route("/bar", get(|| async {}))
.or(Router::new().route("/baz", get(|| async {})));
let app = Router::new().nest("/foo", inner);
let addr = run_in_background(app).await;
@@ -129,8 +133,8 @@ async fn or_nested_inside_other_thing() {
#[tokio::test]
async fn or_with_route_following() {
let one = route("/one", get(|| async { "one" }));
let two = route("/two", get(|| async { "two" }));
let one = Router::new().route("/one", get(|| async { "one" }));
let two = Router::new().route("/two", get(|| async { "two" }));
let app = one.or(two).route("/three", get(|| async { "three" }));
let addr = run_in_background(app).await;
@@ -161,8 +165,10 @@ async fn or_with_route_following() {
#[tokio::test]
async fn layer() {
let one = route("/foo", get(|| async {}));
let two = route("/bar", get(|| async {})).layer(ConcurrencyLimitLayer::new(10));
let one = Router::new().route("/foo", get(|| async {}));
let two = Router::new()
.route("/bar", get(|| async {}))
.layer(ConcurrencyLimitLayer::new(10));
let app = one.or(two);
let addr = run_in_background(app).await;
@@ -186,8 +192,9 @@ async fn layer() {
#[tokio::test]
async fn layer_and_handle_error() {
let one = route("/foo", get(|| async {}));
let two = route("/time-out", get(futures::future::pending::<()>))
let one = Router::new().route("/foo", get(|| async {}));
let two = Router::new()
.route("/time-out", get(futures::future::pending::<()>))
.layer(TimeoutLayer::new(Duration::from_millis(10)))
.handle_error(|_| Ok(StatusCode::REQUEST_TIMEOUT));
let app = one.or(two);
@@ -206,8 +213,8 @@ async fn layer_and_handle_error() {
#[tokio::test]
async fn nesting() {
let one = route("/foo", get(|| async {}));
let two = nest("/bar", route("/baz", get(|| async {})));
let one = Router::new().route("/foo", get(|| async {}));
let two = Router::new().nest("/bar", Router::new().route("/baz", get(|| async {})));
let app = one.or(two);
let addr = run_in_background(app).await;
@@ -224,8 +231,8 @@ async fn nesting() {
#[tokio::test]
async fn boxed() {
let one = route("/foo", get(|| async {})).boxed();
let two = route("/bar", get(|| async {})).boxed();
let one = Router::new().route("/foo", get(|| async {})).boxed();
let two = Router::new().route("/bar", get(|| async {})).boxed();
let app = one.or(two);
let addr = run_in_background(app).await;
@@ -242,13 +249,14 @@ async fn boxed() {
#[tokio::test]
async fn many_ors() {
let app = route("/r1", get(|| async {}))
.or(route("/r2", get(|| async {})))
.or(route("/r3", get(|| async {})))
.or(route("/r4", get(|| async {})))
.or(route("/r5", get(|| async {})))
.or(route("/r6", get(|| async {})))
.or(route("/r7", get(|| async {})));
let app = Router::new()
.route("/r1", get(|| async {}))
.or(Router::new().route("/r2", get(|| async {})))
.or(Router::new().route("/r3", get(|| async {})))
.or(Router::new().route("/r4", get(|| async {})))
.or(Router::new().route("/r5", get(|| async {})))
.or(Router::new().route("/r6", get(|| async {})))
.or(Router::new().route("/r7", get(|| async {})));
let addr = run_in_background(app).await;
@@ -273,18 +281,19 @@ async fn many_ors() {
#[tokio::test]
async fn services() {
let app = route(
"/foo",
crate::service::get(service_fn(|_: Request<Body>| async {
Ok::<_, Infallible>(Response::new(Body::empty()))
})),
)
.or(route(
"/bar",
crate::service::get(service_fn(|_: Request<Body>| async {
Ok::<_, Infallible>(Response::new(Body::empty()))
})),
));
let app = Router::new()
.route(
"/foo",
crate::service::get(service_fn(|_: Request<Body>| async {
Ok::<_, Infallible>(Response::new(Body::empty()))
})),
)
.or(Router::new().route(
"/bar",
crate::service::get(service_fn(|_: Request<Body>| async {
Ok::<_, Infallible>(Response::new(Body::empty()))
})),
));
let addr = run_in_background(app).await;
@@ -319,8 +328,8 @@ async fn all_the_uris(
#[tokio::test]
async fn nesting_and_seeing_the_right_uri() {
let one = nest("/foo", route("/bar", get(all_the_uris)));
let two = route("/foo", get(all_the_uris));
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 addr = run_in_background(one.or(two)).await;
@@ -359,8 +368,11 @@ async fn nesting_and_seeing_the_right_uri() {
#[tokio::test]
async fn nesting_and_seeing_the_right_uri_at_more_levels_of_nesting() {
let one = nest("/foo", nest("/bar", route("/baz", get(all_the_uris))));
let two = route("/foo", get(all_the_uris));
let one = Router::new().nest(
"/foo",
Router::new().nest("/bar", Router::new().route("/baz", get(all_the_uris))),
);
let two = Router::new().route("/foo", get(all_the_uris));
let addr = run_in_background(one.or(two)).await;
@@ -399,9 +411,12 @@ async fn nesting_and_seeing_the_right_uri_at_more_levels_of_nesting() {
#[tokio::test]
async fn nesting_and_seeing_the_right_uri_ors_with_nesting() {
let one = nest("/foo", nest("/bar", route("/baz", get(all_the_uris))));
let two = nest("/foo", route("/qux", get(all_the_uris)));
let three = route("/foo", get(all_the_uris));
let one = Router::new().nest(
"/foo",
Router::new().nest("/bar", Router::new().route("/baz", get(all_the_uris))),
);
let two = Router::new().nest("/foo", Router::new().route("/qux", get(all_the_uris)));
let three = Router::new().route("/foo", get(all_the_uris));
let addr = run_in_background(one.or(two).or(three)).await;
@@ -455,8 +470,11 @@ async fn nesting_and_seeing_the_right_uri_ors_with_nesting() {
#[tokio::test]
async fn nesting_and_seeing_the_right_uri_ors_with_multi_segment_uris() {
let one = nest("/foo", nest("/bar", route("/baz", get(all_the_uris))));
let two = route("/foo/bar", get(all_the_uris));
let one = Router::new().nest(
"/foo",
Router::new().nest("/bar", Router::new().route("/baz", get(all_the_uris))),
);
let two = Router::new().route("/foo/bar", get(all_the_uris));
let addr = run_in_background(one.or(two)).await;