Replace RoutingDsl trait with Router type (#214)

* Remove `RoutingDsl`

* Fix typo
This commit is contained in:
David Pedersen
2021-08-19 21:24:32 +02:00
committed by GitHub
parent 0fd17d4181
commit 97b53768ba
45 changed files with 177 additions and 283 deletions
+3 -5
View File
@@ -10,9 +10,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Overall compile time improvements. If you're having issues with compile time - Overall compile time improvements. If you're having issues with compile time
please file an issue! please file an issue!
- Remove `prelude`. Explicit imports are now required. - Remove `prelude`. Explicit imports are now required.
- Add dedicated `Router` to replace the `RoutingDsl` trait
- Make `FromRequest` default to being generic over `body::Body` ([#146](https://github.com/tokio-rs/axum/pull/146)) - Make `FromRequest` default to being generic over `body::Body` ([#146](https://github.com/tokio-rs/axum/pull/146))
- Implement `std::error::Error` for all rejections ([#153](https://github.com/tokio-rs/axum/pull/153)) - Implement `std::error::Error` for all rejections ([#153](https://github.com/tokio-rs/axum/pull/153))
- Add `RoutingDsl::or` for combining routes ([#108](https://github.com/tokio-rs/axum/pull/108)) - Add `Router::or` for combining routes ([#108](https://github.com/tokio-rs/axum/pull/108))
- Add `handle_error` to `service::OnMethod` ([#160](https://github.com/tokio-rs/axum/pull/160)) - Add `handle_error` to `service::OnMethod` ([#160](https://github.com/tokio-rs/axum/pull/160))
- Add `OriginalUri` for extracting original request URI in nested services ([#197](https://github.com/tokio-rs/axum/pull/197)) - Add `OriginalUri` for extracting original request URI in nested services ([#197](https://github.com/tokio-rs/axum/pull/197))
- Implement `FromRequest` for `http::Extensions` - Implement `FromRequest` for `http::Extensions`
@@ -32,16 +33,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Change WebSocket API to use an extractor ([#121](https://github.com/tokio-rs/axum/pull/121)) - Change WebSocket API to use an extractor ([#121](https://github.com/tokio-rs/axum/pull/121))
- Make WebSocket `Message` an enum ([#116](https://github.com/tokio-rs/axum/pull/116)) - Make WebSocket `Message` an enum ([#116](https://github.com/tokio-rs/axum/pull/116))
- `WebSocket` now uses `Error` as its error type ([#150](https://github.com/tokio-rs/axum/pull/150)) - `WebSocket` now uses `Error` as its error type ([#150](https://github.com/tokio-rs/axum/pull/150))
- Ensure a `HandleError` service created from `ServiceExt::handle_error`
_does not_ implement `RoutingDsl` as that could lead to confusing routing
behavior ([#120](https://github.com/tokio-rs/axum/pull/120)) behavior ([#120](https://github.com/tokio-rs/axum/pull/120))
- Implement `routing::MethodFilter` via [`bitflags`](https://crates.io/crates/bitflags) - Implement `routing::MethodFilter` via [`bitflags`](https://crates.io/crates/bitflags)
- Removed `extract::UrlParams` and `extract::UrlParamsMap`. Use `extract::Path` instead - Removed `extract::UrlParams` and `extract::UrlParamsMap`. Use `extract::Path` instead
- `EmptyRouter` now requires the response body to implement `Send + Sync + 'static'` ([#108](https://github.com/tokio-rs/axum/pull/108)) - `EmptyRouter` now requires the response body to implement `Send + Sync + 'static'` ([#108](https://github.com/tokio-rs/axum/pull/108))
- `ServiceExt` has been removed and its methods have been moved to `RoutingDsl` ([#160](https://github.com/tokio-rs/axum/pull/160))
- `extractor_middleware` now requires `RequestBody: Default` ([#167](https://github.com/tokio-rs/axum/pull/167)) - `extractor_middleware` now requires `RequestBody: Default` ([#167](https://github.com/tokio-rs/axum/pull/167))
- Convert `RequestAlreadyExtracted` to an enum with each possible error variant ([#167](https://github.com/tokio-rs/axum/pull/167)) - Convert `RequestAlreadyExtracted` to an enum with each possible error variant ([#167](https://github.com/tokio-rs/axum/pull/167))
- `RoutingDsl::check_infallible` now returns a `CheckInfallible` service. This - `Router::check_infallible` now returns a `CheckInfallible` service. This
is to improve compile times. is to improve compile times.
- These future types have been moved - These future types have been moved
- `extract::extractor_middleware::ExtractorMiddlewareResponseFuture` moved - `extract::extractor_middleware::ExtractorMiddlewareResponseFuture` moved
+1 -4
View File
@@ -3,10 +3,7 @@ mod starwars;
use async_graphql::http::{playground_source, GraphQLPlaygroundConfig}; use async_graphql::http::{playground_source, GraphQLPlaygroundConfig};
use async_graphql::{EmptyMutation, EmptySubscription, Request, Response, Schema}; use async_graphql::{EmptyMutation, EmptySubscription, Request, Response, Schema};
use axum::response::IntoResponse; use axum::response::IntoResponse;
use axum::{ use axum::{extract::Extension, handler::get, response::Html, route, AddExtensionLayer, Json};
extract::Extension, handler::get, response::Html, route, routing::RoutingDsl,
AddExtensionLayer, Json,
};
use starwars::{QueryRoot, StarWars, StarWarsSchema}; use starwars::{QueryRoot, StarWars, StarWarsSchema};
async fn graphql_handler(schema: Extension<StarWarsSchema>, req: Json<Request>) -> Json<Response> { async fn graphql_handler(schema: Extension<StarWarsSchema>, req: Json<Request>) -> Json<Response> {
-1
View File
@@ -11,7 +11,6 @@ use axum::extract::Extension;
use axum::handler::get; use axum::handler::get;
use axum::response::{Html, IntoResponse}; use axum::response::{Html, IntoResponse};
use axum::route; use axum::route;
use axum::routing::RoutingDsl;
use axum::AddExtensionLayer; use axum::AddExtensionLayer;
use futures::{sink::SinkExt, stream::StreamExt}; use futures::{sink::SinkExt, stream::StreamExt};
use std::collections::HashSet; use std::collections::HashSet;
@@ -14,9 +14,7 @@ use axum::{
handler::{get, post}, handler::{get, post},
http::{Response, StatusCode}, http::{Response, StatusCode},
response::IntoResponse, response::IntoResponse,
route, route, AddExtensionLayer, Json,
routing::RoutingDsl,
AddExtensionLayer, Json,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::json; use serde_json::json;
+1 -1
View File
@@ -4,7 +4,7 @@
//! cargo run -p example-form //! cargo run -p example-form
//! ``` //! ```
use axum::{extract::Form, handler::get, response::Html, route, routing::RoutingDsl}; use axum::{extract::Form, handler::get, response::Html, route};
use serde::Deserialize; use serde::Deserialize;
use std::net::SocketAddr; use std::net::SocketAddr;
-1
View File
@@ -10,7 +10,6 @@ use axum::{
http::{Response, StatusCode}, http::{Response, StatusCode},
response::Html, response::Html,
route, route,
routing::RoutingDsl,
}; };
use std::net::SocketAddr; use std::net::SocketAddr;
use tower::util::MapResponseLayer; use tower::util::MapResponseLayer;
+1 -1
View File
@@ -4,7 +4,7 @@
//! cargo run -p example-hello-world //! cargo run -p example-hello-world
//! ``` //! ```
use axum::{handler::get, route, routing::RoutingDsl}; use axum::{handler::get, route};
use std::net::SocketAddr; use std::net::SocketAddr;
#[tokio::main] #[tokio::main]
+3 -3
View File
@@ -7,13 +7,13 @@
//! ``` //! ```
use axum::{ use axum::{
body::{Body, Bytes}, body::Bytes,
extract::{ContentLengthLimit, Extension, Path}, extract::{ContentLengthLimit, Extension, Path},
handler::{delete, get, Handler}, handler::{delete, get, Handler},
http::StatusCode, http::StatusCode,
response::IntoResponse, response::IntoResponse,
route, route,
routing::{BoxRoute, RoutingDsl}, routing::{BoxRoute, Router},
}; };
use std::{ use std::{
borrow::Cow, borrow::Cow,
@@ -108,7 +108,7 @@ async fn list_keys(Extension(state): Extension<SharedState>) -> String {
.join("\n") .join("\n")
} }
fn admin_routes() -> BoxRoute<Body> { fn admin_routes() -> Router<BoxRoute> {
async fn delete_all_keys(Extension(state): Extension<SharedState>) { async fn delete_all_keys(Extension(state): Extension<SharedState>) {
state.write().unwrap().db.clear(); state.write().unwrap().db.clear();
} }
-1
View File
@@ -9,7 +9,6 @@ use axum::{
handler::get, handler::get,
response::Html, response::Html,
route, route,
routing::RoutingDsl,
}; };
use std::net::SocketAddr; use std::net::SocketAddr;
+1 -3
View File
@@ -14,9 +14,7 @@ use axum::{
handler::get, handler::get,
http::{header::SET_COOKIE, HeaderMap, Response}, http::{header::SET_COOKIE, HeaderMap, Response},
response::{IntoResponse, Redirect}, response::{IntoResponse, Redirect},
route, route, AddExtensionLayer,
routing::RoutingDsl,
AddExtensionLayer,
}; };
use oauth2::{ use oauth2::{
basic::BasicClient, reqwest::async_http_client, AuthUrl, AuthorizationCode, ClientId, basic::BasicClient, reqwest::async_http_client, AuthUrl, AuthorizationCode, ClientId,
+1 -3
View File
@@ -15,9 +15,7 @@ use axum::{
StatusCode, StatusCode,
}, },
response::IntoResponse, response::IntoResponse,
route, route, AddExtensionLayer,
routing::RoutingDsl,
AddExtensionLayer,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::net::SocketAddr; use std::net::SocketAddr;
+1 -1
View File
@@ -9,7 +9,7 @@ use axum::{
handler::get, handler::get,
http::StatusCode, http::StatusCode,
response::sse::{sse, Event, Sse}, response::sse::{sse, Event, Sse},
routing::{nest, RoutingDsl}, routing::nest,
}; };
use futures::stream::{self, Stream}; use futures::stream::{self, Stream};
use std::{convert::Infallible, net::SocketAddr, time::Duration}; use std::{convert::Infallible, net::SocketAddr, time::Duration};
+1 -4
View File
@@ -4,10 +4,7 @@
//! cargo run -p example-static-file-server //! cargo run -p example-static-file-server
//! ``` //! ```
use axum::{ use axum::{http::StatusCode, routing::nest};
http::StatusCode,
routing::{nest, RoutingDsl},
};
use std::net::SocketAddr; use std::net::SocketAddr;
use tower_http::{services::ServeDir, trace::TraceLayer}; use tower_http::{services::ServeDir, trace::TraceLayer};
-1
View File
@@ -12,7 +12,6 @@ use axum::{
http::{Response, StatusCode}, http::{Response, StatusCode},
response::{Html, IntoResponse}, response::{Html, IntoResponse},
route, route,
routing::RoutingDsl,
}; };
use std::{convert::Infallible, net::SocketAddr}; use std::{convert::Infallible, net::SocketAddr};
+3 -3
View File
@@ -5,10 +5,9 @@
//! ``` //! ```
use axum::{ use axum::{
body::Body,
handler::{get, post}, handler::{get, post},
route, route,
routing::{BoxRoute, RoutingDsl}, routing::{BoxRoute, Router},
Json, Json,
}; };
use tower_http::trace::TraceLayer; use tower_http::trace::TraceLayer;
@@ -34,7 +33,7 @@ async fn main() {
/// Having a function that produces our app makes it easy to call it from tests /// Having a function that produces our app makes it easy to call it from tests
/// without having to create an HTTP server. /// without having to create an HTTP server.
#[allow(dead_code)] #[allow(dead_code)]
fn app() -> BoxRoute<Body> { fn app() -> Router<BoxRoute> {
route("/", get(|| async { "Hello, World!" })) route("/", get(|| async { "Hello, World!" }))
.route( .route(
"/json", "/json",
@@ -50,6 +49,7 @@ fn app() -> BoxRoute<Body> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use axum::body::Body;
use axum::http::{self, Request, StatusCode}; use axum::http::{self, Request, StatusCode};
use serde_json::{json, Value}; use serde_json::{json, Value};
use std::net::{SocketAddr, TcpListener}; use std::net::{SocketAddr, TcpListener};
+1 -3
View File
@@ -18,9 +18,7 @@ use axum::{
handler::{get, patch}, handler::{get, patch},
http::StatusCode, http::StatusCode,
response::IntoResponse, response::IntoResponse,
route, route, Json,
routing::RoutingDsl,
Json,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
+1 -3
View File
@@ -9,9 +9,7 @@ use axum::{
extract::{Extension, FromRequest, RequestParts}, extract::{Extension, FromRequest, RequestParts},
handler::get, handler::get,
http::StatusCode, http::StatusCode,
route, route, AddExtensionLayer,
routing::RoutingDsl,
AddExtensionLayer,
}; };
use bb8::{Pool, PooledConnection}; use bb8::{Pool, PooledConnection};
use bb8_postgres::PostgresConnectionManager; use bb8_postgres::PostgresConnectionManager;
+1 -1
View File
@@ -4,7 +4,7 @@
//! cargo run -p example-tracing-aka-logging //! cargo run -p example-tracing-aka-logging
//! ``` //! ```
use axum::{handler::get, response::Html, route, routing::RoutingDsl}; use axum::{handler::get, response::Html, route};
use std::net::SocketAddr; use std::net::SocketAddr;
use tower_http::trace::TraceLayer; use tower_http::trace::TraceLayer;
-1
View File
@@ -10,7 +10,6 @@ use axum::{
handler::get, handler::get,
http::{Method, Request, StatusCode, Uri}, http::{Method, Request, StatusCode, Uri},
route, route,
routing::RoutingDsl,
}; };
use futures::ready; use futures::ready;
use hyper::{ use hyper::{
-1
View File
@@ -12,7 +12,6 @@ use axum::{
http::{Response, StatusCode}, http::{Response, StatusCode},
response::IntoResponse, response::IntoResponse,
route, route,
routing::RoutingDsl,
}; };
use std::collections::HashMap; use std::collections::HashMap;
use std::net::SocketAddr; use std::net::SocketAddr;
+1 -1
View File
@@ -14,7 +14,7 @@ use axum::{
handler::get, handler::get,
http::StatusCode, http::StatusCode,
response::IntoResponse, response::IntoResponse,
routing::{nest, RoutingDsl}, routing::nest,
}; };
use std::net::SocketAddr; use std::net::SocketAddr;
use tower_http::{ use tower_http::{
+10 -10
View File
@@ -1,8 +1,8 @@
//! Extractor for getting connection information from a client. //! Extractor for getting connection information from a client.
//! //!
//! See [`RoutingDsl::into_make_service_with_connect_info`] for more details. //! See [`Router::into_make_service_with_connect_info`] for more details.
//! //!
//! [`RoutingDsl::into_make_service_with_connect_info`]: crate::routing::RoutingDsl::into_make_service_with_connect_info //! [`Router::into_make_service_with_connect_info`]: crate::routing::Router::into_make_service_with_connect_info
use super::{Extension, FromRequest, RequestParts}; use super::{Extension, FromRequest, RequestParts};
use async_trait::async_trait; use async_trait::async_trait;
@@ -19,10 +19,10 @@ use tower_http::add_extension::AddExtension;
/// A [`MakeService`] created from a router. /// A [`MakeService`] created from a router.
/// ///
/// See [`RoutingDsl::into_make_service_with_connect_info`] for more details. /// See [`Router::into_make_service_with_connect_info`] for more details.
/// ///
/// [`MakeService`]: tower::make::MakeService /// [`MakeService`]: tower::make::MakeService
/// [`RoutingDsl::into_make_service_with_connect_info`]: crate::routing::RoutingDsl::into_make_service_with_connect_info /// [`Router::into_make_service_with_connect_info`]: crate::routing::Router::into_make_service_with_connect_info
pub struct IntoMakeServiceWithConnectInfo<S, C> { pub struct IntoMakeServiceWithConnectInfo<S, C> {
svc: S, svc: S,
_connect_info: PhantomData<fn() -> C>, _connect_info: PhantomData<fn() -> C>,
@@ -54,9 +54,9 @@ where
/// The goal for this trait is to allow users to implement custom IO types that /// The goal for this trait is to allow users to implement custom IO types that
/// can still provide the same connection metadata. /// can still provide the same connection metadata.
/// ///
/// See [`RoutingDsl::into_make_service_with_connect_info`] for more details. /// See [`Router::into_make_service_with_connect_info`] for more details.
/// ///
/// [`RoutingDsl::into_make_service_with_connect_info`]: crate::routing::RoutingDsl::into_make_service_with_connect_info /// [`Router::into_make_service_with_connect_info`]: crate::routing::Router::into_make_service_with_connect_info
pub trait Connected<T> { pub trait Connected<T> {
/// The connection information type the IO resources generates. /// The connection information type the IO resources generates.
type ConnectInfo: Clone + Send + Sync + 'static; type ConnectInfo: Clone + Send + Sync + 'static;
@@ -104,12 +104,12 @@ opaque_future! {
/// Extractor for getting connection information produced by a [`Connected`]. /// Extractor for getting connection information produced by a [`Connected`].
/// ///
/// Note this extractor requires you to use /// Note this extractor requires you to use
/// [`RoutingDsl::into_make_service_with_connect_info`] to run your app /// [`Router::into_make_service_with_connect_info`] to run your app
/// otherwise it will fail at runtime. /// otherwise it will fail at runtime.
/// ///
/// See [`RoutingDsl::into_make_service_with_connect_info`] for more details. /// See [`Router::into_make_service_with_connect_info`] for more details.
/// ///
/// [`RoutingDsl::into_make_service_with_connect_info`]: crate::routing::RoutingDsl::into_make_service_with_connect_info /// [`Router::into_make_service_with_connect_info`]: crate::routing::Router::into_make_service_with_connect_info
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct ConnectInfo<T>(pub T); pub struct ConnectInfo<T>(pub T);
@@ -131,7 +131,7 @@ where
mod tests { mod tests {
use super::*; use super::*;
use crate::Server; use crate::Server;
use crate::{handler::get, route, routing::RoutingDsl}; use crate::{handler::get, route};
use std::net::{SocketAddr, TcpListener}; use std::net::{SocketAddr, TcpListener};
#[tokio::test] #[tokio::test]
-1
View File
@@ -13,7 +13,6 @@ use std::ops::Deref;
/// extract::ContentLengthLimit, /// extract::ContentLengthLimit,
/// handler::post, /// handler::post,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// ///
/// async fn handler(body: ContentLengthLimit<String, 1024>) { /// async fn handler(body: ContentLengthLimit<String, 1024>) {
-1
View File
@@ -14,7 +14,6 @@ use std::ops::Deref;
/// extract::Extension, /// extract::Extension,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use std::sync::Arc; /// use std::sync::Arc;
/// ///
-1
View File
@@ -38,7 +38,6 @@ use tower::{BoxError, Layer, Service};
/// extract::{extractor_middleware, FromRequest, RequestParts}, /// extract::{extractor_middleware, FromRequest, RequestParts},
/// handler::{get, post}, /// handler::{get, post},
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use http::StatusCode; /// use http::StatusCode;
/// use async_trait::async_trait; /// use async_trait::async_trait;
-1
View File
@@ -18,7 +18,6 @@ use tower::BoxError;
/// extract::Form, /// extract::Form,
/// handler::post, /// handler::post,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use serde::Deserialize; /// use serde::Deserialize;
/// ///
-7
View File
@@ -12,7 +12,6 @@
//! Json, //! Json,
//! handler::{post, Handler}, //! handler::{post, Handler},
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use serde::Deserialize; //! use serde::Deserialize;
//! //!
@@ -44,7 +43,6 @@
//! extract::{FromRequest, RequestParts}, //! extract::{FromRequest, RequestParts},
//! handler::get, //! handler::get,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use http::{StatusCode, header::{HeaderValue, USER_AGENT}}; //! use http::{StatusCode, header::{HeaderValue, USER_AGENT}};
//! //!
@@ -89,7 +87,6 @@
//! extract::{Path, Query}, //! extract::{Path, Query},
//! handler::get, //! handler::get,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use std::collections::HashMap; //! use std::collections::HashMap;
//! //!
@@ -122,7 +119,6 @@
//! extract::Json, //! extract::Json,
//! handler::post, //! handler::post,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use serde_json::Value; //! use serde_json::Value;
//! //!
@@ -148,7 +144,6 @@
//! extract::{Json, rejection::JsonRejection}, //! extract::{Json, rejection::JsonRejection},
//! handler::post, //! handler::post,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use serde_json::Value; //! use serde_json::Value;
//! //!
@@ -190,7 +185,6 @@
//! extract::Json, //! extract::Json,
//! handler::post, //! handler::post,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use serde_json::Value; //! use serde_json::Value;
//! //!
@@ -224,7 +218,6 @@
//! handler::get, //! handler::get,
//! http::{header::HeaderMap, Request}, //! http::{header::HeaderMap, Request},
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! //!
//! struct MyBody<B>(B); //! struct MyBody<B>(B);
-1
View File
@@ -24,7 +24,6 @@ use tower::BoxError;
/// extract::Multipart, /// extract::Multipart,
/// handler::post, /// handler::post,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use futures::stream::StreamExt; /// use futures::stream::StreamExt;
/// ///
-3
View File
@@ -15,7 +15,6 @@ use std::ops::{Deref, DerefMut};
/// extract::Path, /// extract::Path,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use uuid::Uuid; /// use uuid::Uuid;
/// ///
@@ -38,7 +37,6 @@ use std::ops::{Deref, DerefMut};
/// extract::Path, /// extract::Path,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl,
/// }; /// };
/// use uuid::Uuid; /// use uuid::Uuid;
/// ///
@@ -60,7 +58,6 @@ use std::ops::{Deref, DerefMut};
/// extract::Path, /// extract::Path,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use serde::Deserialize; /// use serde::Deserialize;
/// use uuid::Uuid; /// use uuid::Uuid;
-1
View File
@@ -14,7 +14,6 @@ use std::ops::Deref;
/// extract::Query, /// extract::Query,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use serde::Deserialize; /// use serde::Deserialize;
/// ///
-1
View File
@@ -11,7 +11,6 @@ use std::convert::Infallible;
/// extract::RawQuery, /// extract::RawQuery,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use futures::StreamExt; /// use futures::StreamExt;
/// ///
+1 -3
View File
@@ -93,7 +93,7 @@ where
/// use axum::{ /// use axum::{
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::{nest, RoutingDsl}, /// routing::nest,
/// extract::OriginalUri, /// extract::OriginalUri,
/// http::Uri /// http::Uri
/// }; /// };
@@ -175,7 +175,6 @@ where
/// extract::BodyStream, /// extract::BodyStream,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use futures::StreamExt; /// use futures::StreamExt;
/// ///
@@ -229,7 +228,6 @@ where
/// extract::Body, /// extract::Body,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl,
/// }; /// };
/// use futures::StreamExt; /// use futures::StreamExt;
/// ///
-1
View File
@@ -15,7 +15,6 @@ use std::{convert::Infallible, ops::Deref};
/// extract::TypedHeader, /// extract::TypedHeader,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use headers::UserAgent; /// use headers::UserAgent;
/// ///
-2
View File
@@ -8,7 +8,6 @@
//! handler::get, //! handler::get,
//! response::IntoResponse, //! response::IntoResponse,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! //!
//! let app = route("/ws", get(handler)); //! let app = route("/ws", get(handler));
@@ -115,7 +114,6 @@ impl WebSocketUpgrade {
/// handler::get, /// handler::get,
/// response::IntoResponse, /// response::IntoResponse,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// ///
/// let app = route("/ws", get(handler)); /// let app = route("/ws", get(handler));
+7 -10
View File
@@ -5,7 +5,7 @@ use crate::{
extract::FromRequest, extract::FromRequest,
response::IntoResponse, response::IntoResponse,
routing::{EmptyRouter, MethodFilter}, routing::{EmptyRouter, MethodFilter},
service::{HandleError, HandleErrorFromRouter}, service::HandleError,
util::Either, util::Either,
}; };
use async_trait::async_trait; use async_trait::async_trait;
@@ -34,7 +34,6 @@ pub use self::into_service::IntoService;
/// use axum::{ /// use axum::{
/// handler::any, /// handler::any,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// ///
/// async fn handler() {} /// async fn handler() {}
@@ -80,7 +79,6 @@ where
/// use axum::{ /// use axum::{
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// ///
/// async fn handler() {} /// async fn handler() {}
@@ -170,7 +168,7 @@ where
/// use axum::{ /// use axum::{
/// handler::on, /// handler::on,
/// route, /// route,
/// routing::{MethodFilter, RoutingDsl}, /// routing::MethodFilter,
/// }; /// };
/// ///
/// async fn handler() {} /// async fn handler() {}
@@ -237,7 +235,6 @@ pub trait Handler<B, T>: Clone + Send + Sized + 'static {
/// use axum::{ /// use axum::{
/// handler::{get, Handler}, /// handler::{get, Handler},
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use tower::limit::{ConcurrencyLimitLayer, ConcurrencyLimit}; /// use tower::limit::{ConcurrencyLimitLayer, ConcurrencyLimit};
/// ///
@@ -415,13 +412,13 @@ impl<S, T> Layered<S, T> {
/// This is used to convert errors to responses rather than simply /// This is used to convert errors to responses rather than simply
/// terminating the connection. /// terminating the connection.
/// ///
/// It works similarly to [`routing::RoutingDsl::handle_error`]. See that for more details. /// It works similarly to [`routing::Router::handle_error`]. See that for more details.
/// ///
/// [`routing::RoutingDsl::handle_error`]: crate::routing::RoutingDsl::handle_error /// [`routing::Router::handle_error`]: crate::routing::Router::handle_error
pub fn handle_error<F, ReqBody, ResBody, Res, E>( pub fn handle_error<F, ReqBody, ResBody, Res, E>(
self, self,
f: F, f: F,
) -> Layered<HandleError<S, F, ReqBody, HandleErrorFromRouter>, T> ) -> Layered<HandleError<S, F, ReqBody>, T>
where where
S: Service<Request<ReqBody>, Response = Response<ResBody>>, S: Service<Request<ReqBody>, Response = Response<ResBody>>,
F: FnOnce(S::Error) -> Result<Res, E>, F: FnOnce(S::Error) -> Result<Res, E>,
@@ -514,7 +511,7 @@ impl<H, B, T, F> OnMethod<H, B, T, F> {
/// # Example /// # Example
/// ///
/// ```rust /// ```rust
/// use axum::{handler::post, route, routing::RoutingDsl}; /// use axum::{handler::post, route};
/// ///
/// async fn handler() {} /// async fn handler() {}
/// ///
@@ -607,7 +604,7 @@ impl<H, B, T, F> OnMethod<H, B, T, F> {
/// use axum::{ /// use axum::{
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::{MethodFilter, RoutingDsl} /// routing::MethodFilter
/// }; /// };
/// ///
/// async fn handler() {} /// async fn handler() {}
-2
View File
@@ -31,7 +31,6 @@ use tower::BoxError;
/// extract, /// extract,
/// handler::post, /// handler::post,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use serde::Deserialize; /// use serde::Deserialize;
/// ///
@@ -61,7 +60,6 @@ use tower::BoxError;
/// extract::Path, /// extract::Path,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl,
/// Json, /// Json,
/// }; /// };
/// use serde::Serialize; /// use serde::Serialize;
+10 -24
View File
@@ -49,7 +49,6 @@
//! use axum::{ //! use axum::{
//! handler::get, //! handler::get,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! //!
//! #[tokio::main] //! #[tokio::main]
@@ -107,7 +106,6 @@
//! use axum::{ //! use axum::{
//! handler::get, //! handler::get,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! //!
//! let app = route("/", get(get_slash).post(post_slash)) //! let app = route("/", get(get_slash).post(post_slash))
@@ -132,7 +130,7 @@
//! Routes can also be dynamic like `/users/:id`. See [extractors](#extractors) //! Routes can also be dynamic like `/users/:id`. See [extractors](#extractors)
//! for more details. //! for more details.
//! //!
//! You can also define routes separately and merge them with [`RoutingDsl::or`]. //! You can also define routes separately and merge them with [`Router::or`].
//! //!
//! ## Precedence //! ## Precedence
//! //!
@@ -145,7 +143,6 @@
//! handler::get, //! handler::get,
//! http::Request, //! http::Request,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use tower::{Service, ServiceExt}; //! use tower::{Service, ServiceExt};
//! use http::{Method, Response, StatusCode}; //! use http::{Method, Response, StatusCode};
@@ -212,7 +209,6 @@
//! use axum::{ //! use axum::{
//! route, //! route,
//! handler::{get, post}, //! handler::{get, post},
//! routing::RoutingDsl
//! }; //! };
//! //!
//! // `GET /` and `POST /` are both accepted //! // `GET /` and `POST /` are both accepted
@@ -237,7 +233,6 @@
//! body::Body, //! body::Body,
//! http::Request, //! http::Request,
//! route, //! route,
//! routing::RoutingDsl,
//! service //! service
//! }; //! };
//! use tower_http::services::ServeFile; //! use tower_http::services::ServeFile;
@@ -288,12 +283,12 @@
//! http::Request, //! http::Request,
//! handler::get, //! handler::get,
//! route, //! route,
//! routing::{BoxRoute, RoutingDsl} //! routing::{BoxRoute, Router}
//! }; //! };
//! use tower_http::services::ServeFile; //! use tower_http::services::ServeFile;
//! use http::Response; //! use http::Response;
//! //!
//! fn api_routes() -> BoxRoute<Body> { //! fn api_routes() -> Router<BoxRoute> {
//! route("/users", get(|_: Request<Body>| async { /* ... */ })).boxed() //! route("/users", get(|_: Request<Body>| async { /* ... */ })).boxed()
//! } //! }
//! //!
@@ -322,7 +317,6 @@
//! extract, //! extract,
//! handler::post, //! handler::post,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use serde::Deserialize; //! use serde::Deserialize;
//! //!
@@ -353,7 +347,6 @@
//! extract, //! extract,
//! handler::post, //! handler::post,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use uuid::Uuid; //! use uuid::Uuid;
//! //!
@@ -374,7 +367,6 @@
//! extract, //! extract,
//! handler::get, //! handler::get,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use uuid::Uuid; //! use uuid::Uuid;
//! use serde::Deserialize; //! use serde::Deserialize;
@@ -414,7 +406,6 @@
//! handler::post, //! handler::post,
//! http::Request, //! http::Request,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! //!
//! let app = route("/users/:id", post(handler)); //! let app = route("/users/:id", post(handler));
@@ -447,7 +438,6 @@
//! http::Request, //! http::Request,
//! response::{Html, Json}, //! response::{Html, Json},
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use http::{StatusCode, Response, Uri}; //! use http::{StatusCode, Response, Uri};
//! use serde_json::{Value, json}; //! use serde_json::{Value, json};
@@ -531,7 +521,6 @@
//! use axum::{ //! use axum::{
//! handler::{get, Handler}, //! handler::{get, Handler},
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use tower::limit::ConcurrencyLimitLayer; //! use tower::limit::ConcurrencyLimitLayer;
//! //!
@@ -554,7 +543,6 @@
//! use axum::{ //! use axum::{
//! handler::{get, post}, //! handler::{get, post},
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use tower::limit::ConcurrencyLimitLayer; //! use tower::limit::ConcurrencyLimitLayer;
//! //!
@@ -588,7 +576,6 @@
//! use axum::{ //! use axum::{
//! handler::{get, Handler}, //! handler::{get, Handler},
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use tower::{ //! use tower::{
//! BoxError, timeout::{TimeoutLayer, error::Elapsed}, //! BoxError, timeout::{TimeoutLayer, error::Elapsed},
@@ -631,7 +618,7 @@
//! return `Result<T, E>` where `T` implements //! return `Result<T, E>` where `T` implements
//! [`IntoResponse`](response::IntoResponse). //! [`IntoResponse`](response::IntoResponse).
//! //!
//! See [`routing::RoutingDsl::handle_error`] for more details. //! See [`routing::Router::handle_error`] for more details.
//! //!
//! ## Applying multiple middleware //! ## Applying multiple middleware
//! //!
@@ -643,7 +630,6 @@
//! handler::get, //! handler::get,
//! http::Request, //! http::Request,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use tower::ServiceBuilder; //! use tower::ServiceBuilder;
//! use tower_http::compression::CompressionLayer; //! use tower_http::compression::CompressionLayer;
@@ -680,7 +666,6 @@
//! extract, //! extract,
//! handler::get, //! handler::get,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use std::sync::Arc; //! use std::sync::Arc;
//! //!
@@ -750,7 +735,7 @@
//! [`IntoResponse`]: crate::response::IntoResponse //! [`IntoResponse`]: crate::response::IntoResponse
//! [`Timeout`]: tower::timeout::Timeout //! [`Timeout`]: tower::timeout::Timeout
//! [examples]: https://github.com/tokio-rs/axum/tree/main/examples //! [examples]: https://github.com/tokio-rs/axum/tree/main/examples
//! [`RoutingDsl::or`]: crate::routing::RoutingDsl::or //! [`Router::or`]: crate::routing::Router::or
//! [`axum::Server`]: hyper::server::Server //! [`axum::Server`]: hyper::server::Server
//! [`OriginalUri`]: crate::extract::OriginalUri //! [`OriginalUri`]: crate::extract::OriginalUri
@@ -863,13 +848,14 @@ pub use self::{error::Error, json::Json};
/// # Panics /// # Panics
/// ///
/// Panics if `description` doesn't start with `/`. /// Panics if `description` doesn't start with `/`.
pub fn route<S, B>(description: &str, service: S) -> Route<S, EmptyRouter<S::Error>> pub fn route<S, B>(
description: &str,
service: S,
) -> routing::Router<Route<S, EmptyRouter<S::Error>>>
where where
S: Service<Request<B>> + Clone, S: Service<Request<B>> + Clone,
{ {
use routing::RoutingDsl; routing::Router::new().route(description, service)
routing::EmptyRouter::not_found().route(description, service)
} }
mod sealed { mod sealed {
-1
View File
@@ -14,7 +14,6 @@ use tower::{util::Either, BoxError};
/// ```rust /// ```rust
/// use axum::{ /// use axum::{
/// route, /// route,
/// routing::RoutingDsl,
/// response::{IntoResponse, Headers}, /// response::{IntoResponse, Headers},
/// handler::get, /// handler::get,
/// }; /// };
-1
View File
@@ -45,7 +45,6 @@ pub use self::{
/// handler::get, /// handler::get,
/// response::IntoResponse, /// response::IntoResponse,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use http_body::Body; /// use http_body::Body;
/// use http::{Response, HeaderMap}; /// use http::{Response, HeaderMap};
-1
View File
@@ -13,7 +13,6 @@ use std::convert::TryFrom;
/// handler::get, /// handler::get,
/// response::Redirect, /// response::Redirect,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// ///
/// let app = route("/old", get(|| async { Redirect::permanent("/new".parse().unwrap()) })) /// let app = route("/old", get(|| async { Redirect::permanent("/new".parse().unwrap()) }))
-1
View File
@@ -6,7 +6,6 @@
//! use axum::{ //! use axum::{
//! handler::get, //! handler::get,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use axum::response::sse::{sse, Event, KeepAlive, Sse}; //! use axum::response::sse::{sse, Event, KeepAlive, Sse};
//! use std::{time::Duration, convert::Infallible}; //! use std::{time::Duration, convert::Infallible};
+111 -104
View File
@@ -8,10 +8,9 @@ use crate::{
connect_info::{Connected, IntoMakeServiceWithConnectInfo}, connect_info::{Connected, IntoMakeServiceWithConnectInfo},
OriginalUri, OriginalUri,
}, },
service::{HandleError, HandleErrorFromRouter}, service::HandleError,
util::ByteStr, util::ByteStr,
}; };
use async_trait::async_trait;
use bytes::Bytes; use bytes::Bytes;
use http::{Request, Response, StatusCode, Uri}; use http::{Request, Response, StatusCode, Uri};
use regex::Regex; use regex::Regex;
@@ -31,24 +30,55 @@ use tower_http::map_response_body::MapResponseBodyLayer;
pub mod future; pub mod future;
pub mod or; pub mod or;
pub use self::method_filter::MethodFilter; pub use self::method_filter::MethodFilter;
mod method_filter; mod method_filter;
/// A route that sends requests to one of two [`Service`]s depending on the /// The router type for composing handlers and services.
/// path.
///
/// Created with [`route`](crate::route). See that function for more details.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Route<S, F> { pub struct Router<S> {
pub(crate) pattern: PathPattern, svc: S,
pub(crate) svc: S,
pub(crate) fallback: F,
} }
/// Trait for building routers. impl<E> Router<EmptyRouter<E>> {
#[async_trait] /// Create a new `Router`.
pub trait RoutingDsl: crate::sealed::Sealed + Sized { ///
/// Unless you add additional routes this will respond to `404 Not Found` to
/// all requests.
pub fn new() -> Self {
Self {
svc: EmptyRouter::not_found(),
}
}
}
impl<E> Default for Router<EmptyRouter<E>> {
fn default() -> Self {
Self::new()
}
}
impl<S, R> Service<R> for Router<S>
where
S: Service<R>,
{
type Response = S::Response;
type Error = S::Error;
type Future = S::Future;
#[inline]
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.svc.poll_ready(cx)
}
#[inline]
fn call(&mut self, req: R) -> Self::Future {
self.svc.call(req)
}
}
impl<S> Router<S> {
/// Add another route to the router. /// Add another route to the router.
/// ///
/// # Example /// # Example
@@ -57,7 +87,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// use axum::{ /// use axum::{
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// ///
/// async fn first_handler() { /* ... */ } /// async fn first_handler() { /* ... */ }
@@ -74,29 +103,29 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
/// # }; /// # };
/// ``` /// ```
fn route<T, B>(self, description: &str, svc: T) -> Route<T, Self> pub fn route<T, B>(self, description: &str, svc: T) -> Router<Route<T, S>>
where where
T: Service<Request<B>> + Clone, T: Service<Request<B>> + Clone,
{ {
Route { self.map(|fallback| Route {
pattern: PathPattern::new(description), pattern: PathPattern::new(description),
svc, svc,
fallback: self, fallback,
} })
} }
/// Nest another service inside this router at the given path. /// Nest another service inside this router at the given path.
/// ///
/// See [`nest`] for more details. /// See [`nest`] for more details.
fn nest<T, B>(self, description: &str, svc: T) -> Nested<T, Self> pub fn nest<T, B>(self, description: &str, svc: T) -> Router<Nested<T, S>>
where where
T: Service<Request<B>> + Clone, T: Service<Request<B>> + Clone,
{ {
Nested { self.map(|fallback| Nested {
pattern: PathPattern::new(description), pattern: PathPattern::new(description),
svc, svc,
fallback: self, fallback,
} })
} }
/// Create a boxed route trait object. /// Create a boxed route trait object.
@@ -109,7 +138,7 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// body::Body, /// body::Body,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::{BoxRoute, RoutingDsl} /// routing::{Router, BoxRoute}
/// }; /// };
/// ///
/// async fn first_handler() { /* ... */ } /// async fn first_handler() { /* ... */ }
@@ -118,7 +147,7 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// ///
/// async fn third_handler() { /* ... */ } /// async fn third_handler() { /* ... */ }
/// ///
/// fn app() -> BoxRoute<Body> { /// fn app() -> Router<BoxRoute> {
/// route("/", get(first_handler).post(second_handler)) /// route("/", get(first_handler).post(second_handler))
/// .route("/foo", get(third_handler)) /// .route("/foo", get(third_handler))
/// .boxed() /// .boxed()
@@ -127,22 +156,24 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// ///
/// It also helps with compile times when you have a very large number of /// It also helps with compile times when you have a very large number of
/// routes. /// routes.
fn boxed<ReqBody, ResBody>(self) -> BoxRoute<ReqBody, Self::Error> pub fn boxed<ReqBody, ResBody>(self) -> Router<BoxRoute<ReqBody, S::Error>>
where where
Self: Service<Request<ReqBody>, Response = Response<ResBody>> + Send + 'static, S: Service<Request<ReqBody>, Response = Response<ResBody>> + Send + 'static,
<Self as Service<Request<ReqBody>>>::Error: Into<BoxError> + Send + Sync, S::Error: Into<BoxError> + Send + Sync,
<Self as Service<Request<ReqBody>>>::Future: Send, S::Future: Send,
ReqBody: http_body::Body<Data = Bytes> + Send + Sync + 'static, ReqBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
ReqBody::Error: Into<BoxError> + Send + Sync + 'static, ReqBody::Error: Into<BoxError> + Send + Sync + 'static,
ResBody: http_body::Body<Data = Bytes> + Send + Sync + 'static, ResBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
ResBody::Error: Into<BoxError> + Send + Sync + 'static, ResBody::Error: Into<BoxError> + Send + Sync + 'static,
{ {
ServiceBuilder::new() self.map(|svc| {
.layer_fn(BoxRoute) ServiceBuilder::new()
.layer_fn(MpscBuffer::new) .layer_fn(BoxRoute)
.layer(BoxService::layer()) .layer_fn(MpscBuffer::new)
.layer(MapResponseBodyLayer::new(box_body)) .layer(BoxService::layer())
.service(self) .layer(MapResponseBodyLayer::new(box_body))
.service(svc)
})
} }
/// Apply a [`tower::Layer`] to the router. /// Apply a [`tower::Layer`] to the router.
@@ -165,7 +196,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// use axum::{ /// use axum::{
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use tower::limit::{ConcurrencyLimitLayer, ConcurrencyLimit}; /// use tower::limit::{ConcurrencyLimitLayer, ConcurrencyLimit};
/// ///
@@ -195,7 +225,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// use axum::{ /// use axum::{
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use tower_http::trace::TraceLayer; /// use tower_http::trace::TraceLayer;
/// ///
@@ -213,11 +242,11 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
/// # }; /// # };
/// ``` /// ```
fn layer<L>(self, layer: L) -> Layered<L::Service> pub fn layer<L>(self, layer: L) -> Router<Layered<L::Service>>
where where
L: Layer<Self>, L: Layer<S>,
{ {
Layered::new(layer.layer(self)) self.map(|svc| Layered::new(layer.layer(svc)))
} }
/// Convert this router into a [`MakeService`], that is a [`Service`] who's /// Convert this router into a [`MakeService`], that is a [`Service`] who's
@@ -230,7 +259,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// use axum::{ /// use axum::{
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// ///
/// let app = route("/", get(|| async { "Hi!" })); /// let app = route("/", get(|| async { "Hi!" }));
@@ -244,11 +272,11 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// ``` /// ```
/// ///
/// [`MakeService`]: tower::make::MakeService /// [`MakeService`]: tower::make::MakeService
fn into_make_service(self) -> tower::make::Shared<Self> pub fn into_make_service(self) -> tower::make::Shared<S>
where where
Self: Clone, S: Clone,
{ {
tower::make::Shared::new(self) tower::make::Shared::new(self.svc)
} }
/// Convert this router into a [`MakeService`], that will store `C`'s /// Convert this router into a [`MakeService`], that will store `C`'s
@@ -264,7 +292,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// extract::ConnectInfo, /// extract::ConnectInfo,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use std::net::SocketAddr; /// use std::net::SocketAddr;
/// ///
@@ -291,7 +318,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// extract::connect_info::{ConnectInfo, Connected}, /// extract::connect_info::{ConnectInfo, Connected},
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use hyper::server::conn::AddrStream; /// use hyper::server::conn::AddrStream;
/// ///
@@ -335,14 +361,14 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// [`Connected`]: crate::extract::connect_info::Connected /// [`Connected`]: crate::extract::connect_info::Connected
/// [`ConnectInfo`]: crate::extract::connect_info::ConnectInfo /// [`ConnectInfo`]: crate::extract::connect_info::ConnectInfo
/// [uds]: https://github.com/tokio-rs/axum/blob/main/examples/unix_domain_socket.rs /// [uds]: https://github.com/tokio-rs/axum/blob/main/examples/unix_domain_socket.rs
fn into_make_service_with_connect_info<C, Target>( pub fn into_make_service_with_connect_info<C, Target>(
self, self,
) -> IntoMakeServiceWithConnectInfo<Self, C> ) -> IntoMakeServiceWithConnectInfo<S, C>
where where
Self: Clone, S: Clone,
C: Connected<Target>, C: Connected<Target>,
{ {
IntoMakeServiceWithConnectInfo::new(self) IntoMakeServiceWithConnectInfo::new(self.svc)
} }
/// Merge two routers into one. /// Merge two routers into one.
@@ -354,7 +380,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// use axum::{ /// use axum::{
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// # /// #
/// # async fn users_list() {} /// # async fn users_list() {}
@@ -373,14 +398,11 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
/// # }; /// # };
/// ``` /// ```
fn or<S>(self, other: S) -> or::Or<Self, S> pub fn or<S2>(self, other: S2) -> Router<or::Or<S, S2>> {
where self.map(|first| or::Or {
S: RoutingDsl, first,
{
or::Or {
first: self,
second: other, second: other,
} })
} }
/// Handle errors services in this router might produce, by mapping them to /// Handle errors services in this router might produce, by mapping them to
@@ -395,7 +417,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// handler::get, /// handler::get,
/// http::StatusCode, /// http::StatusCode,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use tower::{BoxError, timeout::TimeoutLayer}; /// use tower::{BoxError, timeout::TimeoutLayer};
/// use std::{time::Duration, convert::Infallible}; /// use std::{time::Duration, convert::Infallible};
@@ -435,7 +456,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// handler::get, /// handler::get,
/// http::StatusCode, /// http::StatusCode,
/// route, /// route,
/// routing::RoutingDsl
/// }; /// };
/// use tower::{BoxError, timeout::TimeoutLayer}; /// use tower::{BoxError, timeout::TimeoutLayer};
/// use std::time::Duration; /// use std::time::Duration;
@@ -457,24 +477,35 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
/// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
/// # }; /// # };
/// ``` /// ```
fn handle_error<ReqBody, F>( pub fn handle_error<ReqBody, F>(self, f: F) -> Router<HandleError<S, F, ReqBody>> {
self, self.map(|svc| HandleError::new(svc, f))
f: F,
) -> HandleError<Self, F, ReqBody, HandleErrorFromRouter> {
HandleError::new(self, f)
} }
/// Check that your service cannot fail. /// Check that your service cannot fail.
/// ///
/// That is, its error type is [`Infallible`]. /// That is, its error type is [`Infallible`].
fn check_infallible(self) -> CheckInfallible<Self> { pub fn check_infallible(self) -> Router<CheckInfallible<S>> {
CheckInfallible(self) self.map(CheckInfallible)
}
fn map<F, S2>(self, f: F) -> Router<S2>
where
F: FnOnce(S) -> S2,
{
Router { svc: f(self.svc) }
} }
} }
impl<S, F> RoutingDsl for Route<S, F> {} /// A route that sends requests to one of two [`Service`]s depending on the
/// path.
impl<S, F> crate::sealed::Sealed for Route<S, F> {} ///
/// Created with [`route`](crate::route). See that function for more details.
#[derive(Debug, Clone)]
pub struct Route<S, F> {
pub(crate) pattern: PathPattern,
pub(crate) svc: S,
pub(crate) fallback: F,
}
impl<S, F, B> Service<Request<B>> for Route<S, F> impl<S, F, B> Service<Request<B>> for Route<S, F>
where where
@@ -560,10 +591,6 @@ impl<E> fmt::Debug for EmptyRouter<E> {
} }
} }
impl<E> RoutingDsl for EmptyRouter<E> {}
impl<E> crate::sealed::Sealed for EmptyRouter<E> {}
impl<B, E> Service<Request<B>> for EmptyRouter<E> impl<B, E> Service<Request<B>> for EmptyRouter<E>
where where
B: Send + Sync + 'static, B: Send + Sync + 'static,
@@ -728,8 +755,8 @@ type Captures = Vec<(String, String)>;
/// A boxed route trait object. /// A boxed route trait object.
/// ///
/// See [`RoutingDsl::boxed`] for more details. /// See [`Router::boxed`] for more details.
pub struct BoxRoute<B, E = Infallible>( pub struct BoxRoute<B = crate::body::Body, E = Infallible>(
MpscBuffer<BoxService<Request<B>, Response<BoxBody>, E>, Request<B>>, MpscBuffer<BoxService<Request<B>, Response<BoxBody>, E>, Request<B>>,
); );
@@ -745,10 +772,6 @@ impl<B, E> fmt::Debug for BoxRoute<B, E> {
} }
} }
impl<B, E> RoutingDsl for BoxRoute<B, E> {}
impl<B, E> crate::sealed::Sealed for BoxRoute<B, E> {}
impl<B, E> Service<Request<B>> for BoxRoute<B, E> impl<B, E> Service<Request<B>> for BoxRoute<B, E>
where where
E: Into<BoxError>, E: Into<BoxError>,
@@ -772,7 +795,7 @@ where
/// A [`Service`] created from a router by applying a Tower middleware. /// A [`Service`] created from a router by applying a Tower middleware.
/// ///
/// Created with [`RoutingDsl::layer`]. See that method for more details. /// Created with [`Router::layer`]. See that method for more details.
pub struct Layered<S> { pub struct Layered<S> {
inner: S, inner: S,
} }
@@ -803,10 +826,6 @@ where
} }
} }
impl<S> RoutingDsl for Layered<S> {}
impl<S> crate::sealed::Sealed for Layered<S> {}
impl<S, R> Service<R> for Layered<S> impl<S, R> Service<R> for Layered<S>
where where
S: Service<R>, S: Service<R>,
@@ -835,7 +854,7 @@ where
/// use axum::{ /// use axum::{
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::{nest, RoutingDsl}, /// routing::nest,
/// }; /// };
/// use http::Uri; /// use http::Uri;
/// ///
@@ -864,7 +883,7 @@ where
/// extract::Path, /// extract::Path,
/// handler::get, /// handler::get,
/// route, /// route,
/// routing::{nest, RoutingDsl}, /// routing::nest,
/// }; /// };
/// use std::collections::HashMap; /// use std::collections::HashMap;
/// ///
@@ -888,7 +907,7 @@ where
/// ///
/// ``` /// ```
/// use axum::{ /// use axum::{
/// routing::{nest, RoutingDsl}, /// routing::nest,
/// service::get, /// service::get,
/// }; /// };
/// use tower_http::services::ServeDir; /// use tower_http::services::ServeDir;
@@ -902,23 +921,19 @@ where
/// # }; /// # };
/// ``` /// ```
/// ///
/// If necessary you can use [`RoutingDsl::boxed`] to box a group of routes /// If necessary you can use [`Router::boxed`] to box a group of routes
/// making the type easier to name. This is sometimes useful when working with /// making the type easier to name. This is sometimes useful when working with
/// `nest`. /// `nest`.
pub fn nest<S, B>(description: &str, svc: S) -> Nested<S, EmptyRouter<S::Error>> pub fn nest<S, B>(description: &str, svc: S) -> Router<Nested<S, EmptyRouter<S::Error>>>
where where
S: Service<Request<B>> + Clone, S: Service<Request<B>> + Clone,
{ {
Nested { Router::new().nest(description, svc)
pattern: PathPattern::new(description),
svc,
fallback: EmptyRouter::not_found(),
}
} }
/// A [`Service`] that has been nested inside a router at some path. /// A [`Service`] that has been nested inside a router at some path.
/// ///
/// Created with [`nest`] or [`RoutingDsl::nest`]. /// Created with [`nest`] or [`Router::nest`].
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Nested<S, F> { pub struct Nested<S, F> {
pattern: PathPattern, pattern: PathPattern,
@@ -926,10 +941,6 @@ pub struct Nested<S, F> {
fallback: F, fallback: F,
} }
impl<S, F> RoutingDsl for Nested<S, F> {}
impl<S, F> crate::sealed::Sealed for Nested<S, F> {}
impl<S, F, B> Service<Request<B>> for Nested<S, F> impl<S, F, B> Service<Request<B>> for Nested<S, F>
where where
S: Service<Request<B>, Response = Response<BoxBody>> + Clone, S: Service<Request<B>, Response = Response<BoxBody>> + Clone,
@@ -1002,7 +1013,7 @@ fn strip_prefix(uri: &Uri, prefix: &str) -> Uri {
/// Middleware that statically verifies that a service cannot fail. /// Middleware that statically verifies that a service cannot fail.
/// ///
/// Created with [`check_infallible`](RoutingDsl::check_infallible). /// Created with [`check_infallible`](Router::check_infallible).
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct CheckInfallible<S>(S); pub struct CheckInfallible<S>(S);
@@ -1025,10 +1036,6 @@ where
} }
} }
impl<S> RoutingDsl for CheckInfallible<S> {}
impl<S> crate::sealed::Sealed for CheckInfallible<S> {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
+3 -7
View File
@@ -1,6 +1,6 @@
//! [`Or`] used to combine two services into one. //! [`Or`] used to combine two services into one.
use super::{FromEmptyRouter, OrDepth, RoutingDsl}; use super::{FromEmptyRouter, OrDepth};
use crate::body::BoxBody; use crate::body::BoxBody;
use futures_util::ready; use futures_util::ready;
use http::{Request, Response}; use http::{Request, Response};
@@ -14,19 +14,15 @@ use tower::{util::Oneshot, Service, ServiceExt};
/// [`tower::Service`] that is the combination of two routers. /// [`tower::Service`] that is the combination of two routers.
/// ///
/// See [`RoutingDsl::or`] for more details. /// See [`Router::or`] for more details.
/// ///
/// [`RoutingDsl::or`]: super::RoutingDsl::or /// [`Router::or`]: super::Router::or
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Or<A, B> { pub struct Or<A, B> {
pub(super) first: A, pub(super) first: A,
pub(super) second: B, pub(super) second: B,
} }
impl<A, B> RoutingDsl for Or<A, B> {}
impl<A, B> crate::sealed::Sealed for Or<A, B> {}
#[allow(warnings)] #[allow(warnings)]
impl<A, B, ReqBody> Service<Request<ReqBody>> for Or<A, B> impl<A, B, ReqBody> Service<Request<ReqBody>> for Or<A, B>
where where
+13 -53
View File
@@ -16,7 +16,6 @@
//! handler::get, //! handler::get,
//! http::Request, //! http::Request,
//! route, //! route,
//! routing::RoutingDsl,
//! service, //! service,
//! }; //! };
//! //!
@@ -68,7 +67,6 @@
//! use axum::{ //! use axum::{
//! handler::get, //! handler::get,
//! route, //! route,
//! routing::RoutingDsl
//! }; //! };
//! use tower::ServiceBuilder; //! use tower::ServiceBuilder;
//! # let some_backpressure_sensitive_middleware = //! # let some_backpressure_sensitive_middleware =
@@ -151,7 +149,6 @@ where
/// use axum::{ /// use axum::{
/// http::Request, /// http::Request,
/// route, /// route,
/// routing::RoutingDsl,
/// service, /// service,
/// }; /// };
/// use http::Response; /// use http::Response;
@@ -249,7 +246,7 @@ where
/// handler::on, /// handler::on,
/// service, /// service,
/// route, /// route,
/// routing::{MethodFilter, RoutingDsl}, /// routing::MethodFilter,
/// }; /// };
/// use http::Response; /// use http::Response;
/// use std::convert::Infallible; /// use std::convert::Infallible;
@@ -344,7 +341,7 @@ impl<S, F, B> OnMethod<S, F, B> {
/// handler::on, /// handler::on,
/// service, /// service,
/// route, /// route,
/// routing::{MethodFilter, RoutingDsl}, /// routing::MethodFilter,
/// }; /// };
/// use http::Response; /// use http::Response;
/// use std::convert::Infallible; /// use std::convert::Infallible;
@@ -447,7 +444,7 @@ impl<S, F, B> OnMethod<S, F, B> {
/// handler::on, /// handler::on,
/// service, /// service,
/// route, /// route,
/// routing::{MethodFilter, RoutingDsl}, /// routing::MethodFilter,
/// }; /// };
/// use http::Response; /// use http::Response;
/// use std::convert::Infallible; /// use std::convert::Infallible;
@@ -483,14 +480,11 @@ impl<S, F, B> OnMethod<S, F, B> {
/// ///
/// Unhandled errors will close the connection without sending a response. /// Unhandled errors will close the connection without sending a response.
/// ///
/// Works similarly to [`RoutingDsl::handle_error`]. See that for more /// Works similarly to [`Router::handle_error`]. See that for more
/// details. /// details.
/// ///
/// [`RoutingDsl::handle_error`]: crate::routing::RoutingDsl::handle_error /// [`Router::handle_error`]: crate::routing::Router::handle_error
pub fn handle_error<ReqBody, H>( pub fn handle_error<ReqBody, H>(self, f: H) -> HandleError<Self, H, ReqBody> {
self,
f: H,
) -> HandleError<Self, H, ReqBody, HandleErrorFromService> {
HandleError::new(self, f) HandleError::new(self, f)
} }
} }
@@ -536,15 +530,15 @@ where
/// ///
/// Created with /// Created with
/// [`handler::Layered::handle_error`](crate::handler::Layered::handle_error) or /// [`handler::Layered::handle_error`](crate::handler::Layered::handle_error) or
/// [`routing::RoutingDsl::handle_error`](crate::routing::RoutingDsl::handle_error). /// [`routing::Router::handle_error`](crate::routing::Router::handle_error).
/// See those methods for more details. /// See those methods for more details.
pub struct HandleError<S, F, B, T> { pub struct HandleError<S, F, B> {
inner: S, inner: S,
f: F, f: F,
_marker: PhantomData<fn() -> (B, T)>, _marker: PhantomData<fn() -> B>,
} }
impl<S, F, B, T> Clone for HandleError<S, F, B, T> impl<S, F, B> Clone for HandleError<S, F, B>
where where
S: Clone, S: Clone,
F: Clone, F: Clone,
@@ -554,23 +548,7 @@ where
} }
} }
/// Marker type used for [`HandleError`] to indicate that it should implement impl<S, F, B> HandleError<S, F, B> {
/// [`RoutingDsl`](crate::routing::RoutingDsl).
#[non_exhaustive]
#[derive(Debug)]
pub struct HandleErrorFromRouter;
/// Marker type used for [`HandleError`] to indicate that it should _not_ implement
/// [`RoutingDsl`](crate::routing::RoutingDsl).
#[non_exhaustive]
#[derive(Debug)]
pub struct HandleErrorFromService;
impl<S, F, B> crate::routing::RoutingDsl for HandleError<S, F, B, HandleErrorFromRouter> {}
impl<S, F, B> crate::sealed::Sealed for HandleError<S, F, B, HandleErrorFromRouter> {}
impl<S, F, B, T> HandleError<S, F, B, T> {
pub(crate) fn new(inner: S, f: F) -> Self { pub(crate) fn new(inner: S, f: F) -> Self {
Self { Self {
inner, inner,
@@ -580,7 +558,7 @@ impl<S, F, B, T> HandleError<S, F, B, T> {
} }
} }
impl<S, F, B, T> fmt::Debug for HandleError<S, F, B, T> impl<S, F, B> fmt::Debug for HandleError<S, F, B>
where where
S: fmt::Debug, S: fmt::Debug,
{ {
@@ -592,7 +570,7 @@ where
} }
} }
impl<S, F, ReqBody, ResBody, Res, E, T> Service<Request<ReqBody>> for HandleError<S, F, ReqBody, T> impl<S, F, ReqBody, ResBody, Res, E> Service<Request<ReqBody>> for HandleError<S, F, ReqBody>
where where
S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone, S: Service<Request<ReqBody>, Response = Response<ResBody>> + Clone,
F: FnOnce(S::Error) -> Result<Res, E> + Clone, F: FnOnce(S::Error) -> Result<Res, E> + Clone,
@@ -615,21 +593,3 @@ where
} }
} }
} }
/// ```compile_fail
/// use crate::{service::ServiceExt};
/// use tower::service_fn;
/// use hyper::Body;
/// use http::{Request, Response, StatusCode};
///
/// let svc = service_fn(|_: Request<Body>| async {
/// Ok::<_, hyper::Error>(Response::new(Body::empty()))
/// })
/// .handle_error::<_, _, hyper::Error>(|_| Ok(StatusCode::INTERNAL_SERVER_ERROR));
///
/// // `.route` should not compile, ie `HandleError` created from any
/// // random service should not implement `RoutingDsl`
/// svc.route::<_, Body>("/", get(|| async {}));
/// ```
#[allow(dead_code)]
fn compile_fail_tests() {}
+1 -1
View File
@@ -6,7 +6,7 @@ use crate::{
response::IntoResponse, response::IntoResponse,
route, route,
routing::nest, routing::nest,
routing::{MethodFilter, RoutingDsl}, routing::MethodFilter,
service, service,
}; };
use bytes::Bytes; use bytes::Bytes;