Files
axum/src/tests/handle_error.rs
T
David Pedersen ca4d9a2bb9 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);
```
2021-08-19 22:37:48 +02:00

209 lines
5.1 KiB
Rust

use super::*;
use futures_util::future::{pending, ready};
use tower::{timeout::TimeoutLayer, MakeService};
async fn unit() {}
async fn forever() {
pending().await
}
fn timeout() -> TimeoutLayer {
TimeoutLayer::new(Duration::from_millis(10))
}
#[derive(Clone)]
struct Svc;
impl<R> Service<R> for Svc {
type Response = Response<Body>;
type Error = hyper::Error;
type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, _req: R) -> Self::Future {
ready(Ok(Response::new(Body::empty())))
}
}
fn check_make_svc<M, R, T, E>(_make_svc: M)
where
M: MakeService<(), R, Response = T, Error = E>,
{
}
fn handle_error<E>(_: E) -> Result<StatusCode, Infallible> {
Ok(StatusCode::INTERNAL_SERVER_ERROR)
}
#[tokio::test]
async fn handler() {
let app = Router::new().route(
"/",
get(forever
.layer(timeout())
.handle_error(|_: BoxError| Ok::<_, Infallible>(StatusCode::REQUEST_TIMEOUT))),
);
let addr = run_in_background(app).await;
let client = reqwest::Client::new();
let res = client
.get(format!("http://{}/", addr))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT);
}
#[tokio::test]
async fn handler_multiple_methods_first() {
let app = Router::new().route(
"/",
get(forever
.layer(timeout())
.handle_error(|_: BoxError| Ok::<_, Infallible>(StatusCode::REQUEST_TIMEOUT)))
.post(unit),
);
let addr = run_in_background(app).await;
let client = reqwest::Client::new();
let res = client
.get(format!("http://{}/", addr))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT);
}
#[tokio::test]
async fn handler_multiple_methods_middle() {
let app = Router::new().route(
"/",
delete(unit)
.get(
forever
.layer(timeout())
.handle_error(|_: BoxError| Ok::<_, Infallible>(StatusCode::REQUEST_TIMEOUT)),
)
.post(unit),
);
let addr = run_in_background(app).await;
let client = reqwest::Client::new();
let res = client
.get(format!("http://{}/", addr))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT);
}
#[tokio::test]
async fn handler_multiple_methods_last() {
let app = Router::new().route(
"/",
delete(unit).get(
forever
.layer(timeout())
.handle_error(|_: BoxError| Ok::<_, Infallible>(StatusCode::REQUEST_TIMEOUT)),
),
);
let addr = run_in_background(app).await;
let client = reqwest::Client::new();
let res = client
.get(format!("http://{}/", addr))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT);
}
#[test]
fn service_propagates_errors() {
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 =
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 = 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_method_multiple() {
let app = Router::new().route::<_, Body>(
"/echo",
service::get(Svc)
.post(Svc)
.handle_error(handle_error::<hyper::Error>),
);
check_make_svc::<_, _, _, Infallible>(app.into_make_service());
}
#[test]
fn service_handle_on_router() {
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 = Router::new()
.route::<_, Body>("/echo", service::get(Svc))
.handle_error(handle_error::<hyper::Error>)
.route("/", get(unit));
check_make_svc::<_, _, _, Infallible>(app.into_make_service());
}
#[test]
fn layered() {
let app = Router::new()
.route::<_, Body>("/echo", get(unit))
.layer(timeout())
.handle_error(handle_error::<BoxError>);
check_make_svc::<_, _, _, Infallible>(app.into_make_service());
}
#[tokio::test] // async because of `.boxed()`
async fn layered_boxed() {
let app = Router::new()
.route::<_, Body>("/echo", get(unit))
.layer(timeout())
.boxed()
.handle_error(handle_error::<BoxError>);
check_make_svc::<_, _, _, Infallible>(app.into_make_service());
}