Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change Router::with_state and impl Service for Router<()> #1552

Merged
merged 11 commits into from Nov 24, 2022
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion axum-extra/src/extract/cookie/private.rs
Expand Up @@ -68,7 +68,7 @@ use std::{convert::Infallible, fmt, marker::PhantomData};
/// .route("/set", post(set_secret))
/// .route("/get", get(get_secret))
/// .with_state(state);
/// # let _: axum::routing::RouterService = app;
/// # let _: axum::Router = app;
/// ```
///
/// If you have been using `Arc<AppState>` you cannot implement `FromRef<Arc<AppState>> for Key`.
Expand Down
2 changes: 1 addition & 1 deletion axum-extra/src/extract/cookie/signed.rs
Expand Up @@ -86,7 +86,7 @@ use std::{convert::Infallible, fmt, marker::PhantomData};
/// .route("/sessions", post(create_session))
/// .route("/me", get(me))
/// .with_state(state);
/// # let _: axum::routing::RouterService = app;
/// # let _: axum::Router = app;
/// ```
/// If you have been using `Arc<AppState>` you cannot implement `FromRef<Arc<AppState>> for Key`.
/// You can use a new type instead:
Expand Down
6 changes: 3 additions & 3 deletions axum-extra/src/routing/resource.rs
Expand Up @@ -147,7 +147,7 @@ impl<B> From<Resource<B>> for Router<B> {
mod tests {
#[allow(unused_imports)]
use super::*;
use axum::{extract::Path, http::Method, routing::RouterService, Router};
use axum::{extract::Path, http::Method, Router};
use http::Request;
use tower::{Service, ServiceExt};

Expand All @@ -162,7 +162,7 @@ mod tests {
.update(|Path(id): Path<u64>| async move { format!("users#update id={}", id) })
.destroy(|Path(id): Path<u64>| async move { format!("users#destroy id={}", id) });

let mut app = Router::new().merge(users).into_service();
let mut app = Router::new().merge(users);

assert_eq!(
call_route(&mut app, Method::GET, "/users").await,
Expand Down Expand Up @@ -205,7 +205,7 @@ mod tests {
);
}

async fn call_route(app: &mut RouterService, method: Method, uri: &str) -> String {
async fn call_route(app: &mut Router, method: Method, uri: &str) -> String {
let res = app
.ready()
.await
Expand Down
2 changes: 1 addition & 1 deletion axum-extra/src/routing/spa.rs
Expand Up @@ -270,7 +270,7 @@ mod tests {

#[allow(dead_code)]
fn works_with_router_with_state() {
let _: axum::RouterService = Router::new()
let _: Router = Router::new()
.merge(SpaRouter::new("/assets", "test_files"))
.route("/", get(|_: axum::extract::State<String>| async {}))
.with_state(String::new());
Expand Down
2 changes: 1 addition & 1 deletion axum-macros/src/lib.rs
Expand Up @@ -606,7 +606,7 @@ pub fn derive_typed_path(input: TokenStream) -> TokenStream {
/// let app = Router::new()
/// .route("/", get(handler).post(other_handler))
/// .with_state(state);
/// # let _: axum::routing::RouterService = app;
/// # let _: axum::Router = app;
/// ```
///
/// [`FromRef`]: https://docs.rs/axum/latest/axum/extract/trait.FromRef.html
Expand Down
2 changes: 1 addition & 1 deletion axum-macros/tests/from_ref/pass/basic.rs
Expand Up @@ -14,7 +14,7 @@ fn main() {
auth_token: Default::default(),
};

let _: axum::routing::RouterService = Router::new()
let _: axum::Router = Router::new()
.route("/", get(handler))
.with_state(state);
}
2 changes: 1 addition & 1 deletion axum-macros/tests/from_request/pass/state_enum_via.rs
Expand Up @@ -6,7 +6,7 @@ use axum::{
use axum_macros::FromRequest;

fn main() {
let _: axum::routing::RouterService = Router::new()
let _: axum::Router = Router::new()
.route("/a", get(|_: AppState| async {}))
.route("/b", get(|_: InnerState| async {}))
.with_state(AppState::default());
Expand Down
Expand Up @@ -6,7 +6,7 @@ use axum::{
use axum_macros::FromRequestParts;

fn main() {
let _: axum::routing::RouterService = Router::new()
let _: axum::Router = Router::new()
.route("/a", get(|_: AppState| async {}))
.route("/b", get(|_: InnerState| async {}))
.route("/c", get(|_: AppState, _: InnerState| async {}))
Expand Down
2 changes: 1 addition & 1 deletion axum-macros/tests/from_request/pass/state_explicit.rs
Expand Up @@ -6,7 +6,7 @@ use axum::{
};

fn main() {
let _: axum::routing::RouterService = Router::new()
let _: axum::Router = Router::new()
.route("/b", get(|_: Extractor| async {}))
.with_state(AppState::default());
}
Expand Down
Expand Up @@ -7,7 +7,7 @@ use axum::{
use std::collections::HashMap;

fn main() {
let _: axum::routing::RouterService = Router::new()
let _: axum::Router = Router::new()
.route("/b", get(|_: Extractor| async {}))
.with_state(AppState::default());
}
Expand Down
Expand Up @@ -6,7 +6,7 @@ use axum::{
use axum_macros::FromRequest;

fn main() {
let _: axum::routing::RouterService = Router::new()
let _: axum::Router = Router::new()
.route("/", get(|_: Extractor| async {}))
.with_state(AppState::default());
}
Expand Down
2 changes: 1 addition & 1 deletion axum-macros/tests/from_request/pass/state_field_infer.rs
Expand Up @@ -6,7 +6,7 @@ use axum::{
use axum_macros::FromRequest;

fn main() {
let _: axum::routing::RouterService = Router::new()
let _: axum::Router = Router::new()
.route("/", get(|_: Extractor| async {}))
.with_state(AppState::default());
}
Expand Down
2 changes: 1 addition & 1 deletion axum-macros/tests/from_request/pass/state_via.rs
Expand Up @@ -6,7 +6,7 @@ use axum::{
use axum_macros::FromRequest;

fn main() {
let _: axum::routing::RouterService = Router::new()
let _: axum::Router = Router::new()
.route("/b", get(|_: (), _: AppState| async {}))
.route("/c", get(|_: (), _: InnerState| async {}))
.with_state(AppState::default());
Expand Down
2 changes: 1 addition & 1 deletion axum-macros/tests/from_request/pass/state_via_infer.rs
Expand Up @@ -6,7 +6,7 @@ use axum::{
use axum_macros::FromRequest;

fn main() {
let _: axum::routing::RouterService = Router::new()
let _: axum::Router = Router::new()
.route("/b", get(|_: AppState| async {}))
.with_state(AppState::default());
}
Expand Down
2 changes: 1 addition & 1 deletion axum-macros/tests/from_request/pass/state_via_parts.rs
Expand Up @@ -6,7 +6,7 @@ use axum::{
use axum_macros::FromRequestParts;

fn main() {
let _: axum::routing::RouterService = Router::new()
let _: axum::Router = Router::new()
.route("/a", get(|_: AppState, _: InnerState, _: String| async {}))
.route("/b", get(|_: AppState, _: String| async {}))
.route("/c", get(|_: InnerState, _: String| async {}))
Expand Down
Expand Up @@ -8,7 +8,7 @@ use axum::{
use axum_macros::FromRequest;

fn main() {
let _: axum::routing::RouterService = Router::new()
let _: axum::Router = Router::new()
.route("/a", get(|_: Extractor| async {}))
.with_state(AppState::default());
}
Expand Down
5 changes: 5 additions & 0 deletions axum/CHANGELOG.md
Expand Up @@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# Unreleased

- **added:** Add `RouterService::{layer, route_layer}` ([#1550])
davidpdrsn marked this conversation as resolved.
Show resolved Hide resolved
- **breaking:** `RouterService` has been removed since `Router` now implements
`Service` when the state is `()`. Use `Router::with_state` to provide the
state and get a `Router<()>` ([#1552])

[#1552]: https://github.com/tokio-rs/axum/pull/1552

[#1550]: https://github.com/tokio-rs/axum/pull/1550

Expand Down
43 changes: 16 additions & 27 deletions axum/benches/benches.rs
@@ -1,7 +1,7 @@
use axum::{
extract::State,
routing::{get, post},
Extension, Json, Router, RouterService, Server,
Extension, Json, Router, Server,
};
use hyper::server::conn::AddrIncoming;
use serde::{Deserialize, Serialize};
Expand All @@ -17,13 +17,9 @@ fn main() {
ensure_rewrk_is_installed();
}

benchmark("minimal").run(|| Router::new().into_service());
benchmark("minimal").run(Router::new);

benchmark("basic").run(|| {
Router::new()
.route("/", get(|| async { "Hello, World!" }))
.into_service()
});
benchmark("basic").run(|| Router::new().route("/", get(|| async { "Hello, World!" })));

benchmark("routing").path("/foo/bar/baz").run(|| {
let mut app = Router::new();
Expand All @@ -34,32 +30,26 @@ fn main() {
}
}
}
app.route("/foo/bar/baz", get(|| async {})).into_service()
app.route("/foo/bar/baz", get(|| async {}))
});

benchmark("receive-json")
.method("post")
.headers(&[("content-type", "application/json")])
.body(r#"{"n": 123, "s": "hi there", "b": false}"#)
.run(|| {
Router::new()
.route("/", post(|_: Json<Payload>| async {}))
.into_service()
});
.run(|| Router::new().route("/", post(|_: Json<Payload>| async {})));

benchmark("send-json").run(|| {
Router::new()
.route(
"/",
get(|| async {
Json(Payload {
n: 123,
s: "hi there".to_owned(),
b: false,
})
}),
)
.into_service()
Router::new().route(
"/",
get(|| async {
Json(Payload {
n: 123,
s: "hi there".to_owned(),
b: false,
})
}),
)
});

let state = AppState {
Expand All @@ -75,7 +65,6 @@ fn main() {
Router::new()
.route("/", get(|_: Extension<AppState>| async {}))
.layer(Extension(state.clone()))
.into_service()
});

benchmark("state").run(|| {
Expand Down Expand Up @@ -133,7 +122,7 @@ impl BenchmarkBuilder {

fn run<F>(self, f: F)
where
F: FnOnce() -> RouterService,
F: FnOnce() -> Router<()>,
{
// support only running some benchmarks with
// ```
Expand Down
51 changes: 45 additions & 6 deletions axum/src/boxed.rs
@@ -1,6 +1,14 @@
use std::{convert::Infallible, fmt};

use crate::{body::HttpBody, handler::Handler, routing::Route, Router};
use http::Request;
use tower::Service;

use crate::{
body::HttpBody,
handler::Handler,
routing::{future::RouteFuture, Route},
Router,
};

pub(crate) struct BoxedIntoRoute<S, B, E>(Box<dyn ErasedIntoRoute<S, B, E>>);

Expand All @@ -13,6 +21,7 @@ where
where
H: Handler<T, S, B>,
T: 'static,
B: HttpBody,
{
Self(Box::new(MakeErasedHandler {
handler,
Expand All @@ -30,6 +39,14 @@ where
into_route: |router, state| Route::new(router.with_state(state)),
}))
}

pub(crate) fn call_with_state(
self,
request: Request<B>,
state: S,
) -> RouteFuture<B, Infallible> {
self.0.call_with_state(request, state)
}
}

impl<S, B, E> BoxedIntoRoute<S, B, E> {
Expand All @@ -39,7 +56,7 @@ impl<S, B, E> BoxedIntoRoute<S, B, E> {
B: 'static,
E: 'static,
F: FnOnce(Route<B, E>) -> Route<B2, E2> + Clone + Send + 'static,
B2: 'static,
B2: HttpBody + 'static,
E2: 'static,
{
BoxedIntoRoute(Box::new(Map {
Expand Down Expand Up @@ -69,6 +86,8 @@ pub(crate) trait ErasedIntoRoute<S, B, E>: Send {
fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, B, E>>;

fn into_route(self: Box<Self>, state: S) -> Route<B, E>;

fn call_with_state(self: Box<Self>, request: Request<B>, state: S) -> RouteFuture<B, E>;
}

pub(crate) struct MakeErasedHandler<H, S, B> {
Expand All @@ -80,7 +99,7 @@ impl<H, S, B> ErasedIntoRoute<S, B, Infallible> for MakeErasedHandler<H, S, B>
where
H: Clone + Send + 'static,
S: 'static,
B: 'static,
B: HttpBody + 'static,
{
fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, B, Infallible>> {
Box::new(self.clone())
Expand All @@ -89,6 +108,14 @@ where
fn into_route(self: Box<Self>, state: S) -> Route<B> {
(self.into_route)(self.handler, state)
}

fn call_with_state(
self: Box<Self>,
request: Request<B>,
state: S,
) -> RouteFuture<B, Infallible> {
self.into_route(state).call(request)
}
}

impl<H, S, B> Clone for MakeErasedHandler<H, S, B>
Expand All @@ -110,8 +137,8 @@ pub(crate) struct MakeErasedRouter<S, B> {

impl<S, B> ErasedIntoRoute<S, B, Infallible> for MakeErasedRouter<S, B>
where
S: Clone + Send + 'static,
B: 'static,
S: Clone + Send + Sync + 'static,
B: HttpBody + Send + 'static,
{
fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, B, Infallible>> {
Box::new(self.clone())
Expand All @@ -120,6 +147,14 @@ where
fn into_route(self: Box<Self>, state: S) -> Route<B> {
(self.into_route)(self.router, state)
}

fn call_with_state(
mut self: Box<Self>,
request: Request<B>,
state: S,
) -> RouteFuture<B, Infallible> {
self.router.call_with_state(request, state)
}
}

impl<S, B> Clone for MakeErasedRouter<S, B>
Expand All @@ -144,7 +179,7 @@ where
S: 'static,
B: 'static,
E: 'static,
B2: 'static,
B2: HttpBody + 'static,
E2: 'static,
{
fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, B2, E2>> {
Expand All @@ -157,6 +192,10 @@ where
fn into_route(self: Box<Self>, state: S) -> Route<B2, E2> {
(self.layer)(self.inner.into_route(state))
}

fn call_with_state(self: Box<Self>, request: Request<B2>, state: S) -> RouteFuture<B2, E2> {
(self.layer)(self.inner.into_route(state)).call(request)
}
}

pub(crate) trait LayerFn<B, E, B2, E2>: FnOnce(Route<B, E>) -> Route<B2, E2> + Send {
Expand Down