Type safe state inheritance (#1532)

* Make state type safe

* fix examples

* remove unnecessary `#[track_caller]`s

* Router::into_service -> Router::with_state

* fixup docs

* macro docs

* add missing docs

* fix examples

* format

* changelog

* Update trybuild tests

* Make sure fallbacks are still inherited for opaque services (#1540)

* Document nesting routers with different state

* fix leftover conflicts
This commit is contained in:
David Pedersen
2022-11-18 11:02:58 +00:00
committed by GitHub
parent ba8e9c1b21
commit 64960bb19c
62 changed files with 675 additions and 736 deletions
+3 -1
View File
@@ -34,7 +34,9 @@ async fn main() {
.data(StarWars::new())
.finish();
let app = Router::with_state(schema).route("/", get(graphql_playground).post(graphql_handler));
let app = Router::new()
.route("/", get(graphql_playground).post(graphql_handler))
.with_state(schema);
println!("Playground: http://localhost:3000");
+3 -2
View File
@@ -44,9 +44,10 @@ async fn main() {
let app_state = Arc::new(AppState { user_set, tx });
let app = Router::with_state(app_state)
let app = Router::new()
.route("/", get(index))
.route("/websocket", get(websocket_handler));
.route("/websocket", get(websocket_handler))
.with_state(app_state);
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
tracing::debug!("listening on {}", addr);
@@ -36,9 +36,10 @@ async fn main() {
let user_repo = Arc::new(ExampleUserRepo) as DynUserRepo;
// Build our application with some routes
let app = Router::with_state(user_repo)
let app = Router::new()
.route("/users/:id", get(users_show))
.route("/users", post(users_create));
.route("/users", post(users_create))
.with_state(user_repo);
// Run our application
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
+7 -7
View File
@@ -43,7 +43,7 @@ async fn main() {
let shared_state = SharedState::default();
// Build our application by composing routes
let app = Router::with_state(Arc::clone(&shared_state))
let app = Router::new()
.route(
"/:key",
// Add compression to `kv_get`
@@ -60,7 +60,7 @@ async fn main() {
)
.route("/keys", get(list_keys))
// Nest our admin routes under `/admin`
.nest("/admin", admin_routes(shared_state))
.nest("/admin", admin_routes())
// Add middleware to all routes
.layer(
ServiceBuilder::new()
@@ -69,9 +69,9 @@ async fn main() {
.load_shed()
.concurrency_limit(1024)
.timeout(Duration::from_secs(10))
.layer(TraceLayer::new_for_http())
.into_inner(),
);
.layer(TraceLayer::new_for_http()),
)
.with_state(Arc::clone(&shared_state));
// Run our app with hyper
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
@@ -115,7 +115,7 @@ async fn list_keys(State(state): State<SharedState>) -> String {
.join("\n")
}
fn admin_routes(state: SharedState) -> Router<SharedState> {
fn admin_routes() -> Router<SharedState> {
async fn delete_all_keys(State(state): State<SharedState>) {
state.write().unwrap().db.clear();
}
@@ -124,7 +124,7 @@ fn admin_routes(state: SharedState) -> Router<SharedState> {
state.write().unwrap().db.remove(&key);
}
Router::with_state(state)
Router::new()
.route("/keys", delete(delete_all_keys))
.route("/key/:key", delete(remove_key))
// Require bearer auth for all admin routes
+3 -2
View File
@@ -47,12 +47,13 @@ async fn main() {
oauth_client,
};
let app = Router::with_state(app_state)
let app = Router::new()
.route("/", get(index))
.route("/auth/discord", get(discord_auth))
.route("/auth/authorized", get(login_authorized))
.route("/protected", get(protected))
.route("/logout", get(logout));
.route("/logout", get(logout))
.with_state(app_state);
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
tracing::debug!("listening on {}", addr);
+1 -1
View File
@@ -24,7 +24,7 @@ async fn main() {
let client = Client::new();
let app = Router::with_state(client).route("/", get(handler));
let app = Router::new().route("/", get(handler)).with_state(client);
let addr = SocketAddr::from(([127, 0, 0, 1], 4000));
println!("reverse proxy listening on {}", addr);
+1 -1
View File
@@ -39,7 +39,7 @@ async fn main() {
// `MemoryStore` just used as an example. Don't use this in production.
let store = MemoryStore::new();
let app = Router::with_state(store).route("/", get(handler));
let app = Router::new().route("/", get(handler)).with_state(store);
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
tracing::debug!("listening on {}", addr);
+6 -4
View File
@@ -46,10 +46,12 @@ async fn main() {
.expect("can connect to database");
// build our application with some routes
let app = Router::with_state(pool).route(
"/",
get(using_connection_pool_extractor).post(using_connection_extractor),
);
let app = Router::new()
.route(
"/",
get(using_connection_pool_extractor).post(using_connection_extractor),
)
.with_state(pool);
// run it with hyper
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
+3 -2
View File
@@ -46,7 +46,7 @@ async fn main() {
let db = Db::default();
// Compose the routes
let app = Router::with_state(db)
let app = Router::new()
.route("/todos", get(todos_index).post(todos_create))
.route("/todos/:id", patch(todos_update).delete(todos_delete))
// Add middleware to all routes
@@ -65,7 +65,8 @@ async fn main() {
.timeout(Duration::from_secs(10))
.layer(TraceLayer::new_for_http())
.into_inner(),
);
)
.with_state(db);
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
tracing::debug!("listening on {}", addr);
+6 -4
View File
@@ -33,10 +33,12 @@ async fn main() {
let pool = Pool::builder().build(manager).await.unwrap();
// build our application with some routes
let app = Router::with_state(pool).route(
"/",
get(using_connection_pool_extractor).post(using_connection_extractor),
);
let app = Router::new()
.route(
"/",
get(using_connection_pool_extractor).post(using_connection_extractor),
)
.with_state(pool);
// run it with hyper
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));