Nesting and more flexible routing dsl

This commit is contained in:
David Pedersen
2021-06-06 20:30:54 +02:00
parent b4e2750d6a
commit 1609191a74
3 changed files with 245 additions and 238 deletions
+65 -138
View File
@@ -1,4 +1,4 @@
use crate::{extract, get, on, post, route, routing::MethodFilter, service, AddRoute, Handler};
use crate::{extract, get, on, post, route, routing::MethodFilter, service, Handler, RoutingDsl};
use http::{Request, Response, StatusCode};
use hyper::{Body, Server};
use serde::Deserialize;
@@ -283,6 +283,7 @@ async fn boxing() {
"hi from POST"
}),
)
.layer(tower_http::compression::CompressionLayer::new())
.boxed();
let addr = run_in_background(app).await;
@@ -485,150 +486,76 @@ async fn layer_on_whole_router() {
assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
}
// TODO(david): layer that changes the response body type to have a different error
#[tokio::test]
async fn disjunction() {
let api_routes = route(
"/users",
get(|_: Request<Body>| async { "users#index" })
.post(|_: Request<Body>| async { "users#create" }),
)
.route(
"/users/:id",
get(
|_: Request<Body>, params: extract::UrlParamsMap| async move {
format!(
"{}: users#show ({})",
params.get("version").unwrap(),
params.get("id").unwrap()
)
},
),
)
.route(
"/games/:id",
get(
|_: Request<Body>, params: extract::UrlParamsMap| async move {
format!(
"{}: games#show ({})",
params.get("version").unwrap(),
params.get("id").unwrap()
)
},
),
);
// // #[tokio::test]
// // async fn nesting() {
// // let api = app()
// // .at("/users")
// // .get(|_: Request<Body>| async { "users#index" })
// // .post(|_: Request<Body>| async { "users#create" })
// // .at("/users/:id")
// // .get(
// // |_: Request<Body>, params: extract::UrlParams<(i32,)>| async move {
// // let (id,) = params.0;
// // format!("users#show {}", id)
// // },
// // );
let app = route("/", get(|_: Request<Body>| async { "hi" })).nest("/:version/api", api_routes);
// // let app = app()
// // .at("/foo")
// // .get(|_: Request<Body>| async { "foo" })
// // .at("/api")
// // .nest(api)
// // .at("/bar")
// // .get(|_: Request<Body>| async { "bar" })
// // .into_service();
let addr = run_in_background(app).await;
// // let addr = run_in_background(app).await;
let client = reqwest::Client::new();
// // let client = reqwest::Client::new();
let res = client
.get(format!("http://{}/", addr))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.text().await.unwrap(), "hi");
// // let res = client
// // .get(format!("http://{}/api/users", addr))
// // .send()
// // .await
// // .unwrap();
// // assert_eq!(res.text().await.unwrap(), "users#index");
let res = client
.get(format!("http://{}/v0/api/users", addr))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.text().await.unwrap(), "users#index");
// // let res = client
// // .post(format!("http://{}/api/users", addr))
// // .send()
// // .await
// // .unwrap();
// // assert_eq!(res.text().await.unwrap(), "users#create");
let res = client
.get(format!("http://{}/v0/api/users/123", addr))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.text().await.unwrap(), "v0: users#show (123)");
// // let res = client
// // .get(format!("http://{}/api/users/42", addr))
// // .send()
// // .await
// // .unwrap();
// // assert_eq!(res.text().await.unwrap(), "users#show 42");
// // let res = client
// // .get(format!("http://{}/foo", addr))
// // .send()
// // .await
// // .unwrap();
// // assert_eq!(res.text().await.unwrap(), "foo");
// // let res = client
// // .get(format!("http://{}/bar", addr))
// // .send()
// // .await
// // .unwrap();
// // assert_eq!(res.text().await.unwrap(), "bar");
// // }
// // #[tokio::test]
// // async fn nesting_with_dynamic_part() {
// // let api = app().at("/users/:id").get(
// // |_: Request<Body>, params: extract::UrlParamsMap| async move {
// // // let (version, id) = params.0;
// // dbg!(&params);
// // let version = params.get("version").unwrap();
// // let id = params.get("id").unwrap();
// // format!("users#show {} {}", version, id)
// // },
// // );
// // let app = app().at("/:version/api").nest(api).into_service();
// // let addr = run_in_background(app).await;
// // let client = reqwest::Client::new();
// // let res = client
// // .get(format!("http://{}/v0/api/users/123", addr))
// // .send()
// // .await
// // .unwrap();
// // let status = res.status();
// // assert_eq!(res.text().await.unwrap(), "users#show v0 123");
// // assert_eq!(status, StatusCode::OK);
// // }
// // #[tokio::test]
// // async fn nesting_more_deeply() {
// // let users_api = app()
// // .at("/:id")
// // .get(|req: Request<Body>| async move {
// // dbg!(&req.uri().path());
// // "users#show"
// // });
// // let games_api = app()
// // .at("/")
// // .post(|req: Request<Body>| async move {
// // dbg!(&req.uri().path());
// // "games#create"
// // });
// // let api = app()
// // .at("/users")
// // .nest(users_api)
// // .at("/games")
// // .nest(games_api);
// // let app = app().at("/:version/api").nest(api).into_service();
// // let addr = run_in_background(app).await;
// // let client = reqwest::Client::new();
// // // let res = client
// // // .get(format!("http://{}/v0/api/users/123", addr))
// // // .send()
// // // .await
// // // .unwrap();
// // // assert_eq!(res.status(), StatusCode::OK);
// // println!("============================");
// // let res = client
// // .post(format!("http://{}/v0/api/games", addr))
// // .send()
// // .await
// // .unwrap();
// // assert_eq!(res.status(), StatusCode::OK);
// // }
// // TODO(david): nesting more deeply
// // TODO(david): composing two apps
// // TODO(david): composing two apps with one at a "sub path"
// // TODO(david): composing two boxed apps
// // TODO(david): composing two apps that have had layers applied
let res = client
.get(format!("http://{}/v0/api/games/123", addr))
.send()
.await
.unwrap();
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.text().await.unwrap(), "v0: games#show (123)");
}
/// Run a `tower::Service` in the background and get a URI for it.
async fn run_in_background<S, ResBody>(svc: S) -> SocketAddr