mirror of
https://github.com/tokio-rs/axum.git
synced 2025-04-26 13:56:22 +02:00
Replace RoutingDsl
trait with Router
type (#214)
* Remove `RoutingDsl` * Fix typo
This commit is contained in:
parent
0fd17d4181
commit
97b53768ba
45 changed files with 177 additions and 283 deletions
CHANGELOG.md
examples
async-graphql/src
chat/src
error-handling-and-dependency-injection/src
form/src
global-404-handler/src
hello-world/src
key-value-store/src
multipart-form/src
oauth/src
sessions/src
sse/src
static-file-server/src
templates/src
testing/src
todos/src
tokio-postgres/src
tracing-aka-logging/src
unix-domain-socket/src
versioning/src
websockets/src
src
|
@ -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
|
||||
please file an issue!
|
||||
- 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))
|
||||
- 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 `OriginalUri` for extracting original request URI in nested services ([#197](https://github.com/tokio-rs/axum/pull/197))
|
||||
- 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))
|
||||
- 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))
|
||||
- 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))
|
||||
- Implement `routing::MethodFilter` via [`bitflags`](https://crates.io/crates/bitflags)
|
||||
- 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))
|
||||
- `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))
|
||||
- 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.
|
||||
- These future types have been moved
|
||||
- `extract::extractor_middleware::ExtractorMiddlewareResponseFuture` moved
|
||||
|
|
|
@ -3,10 +3,7 @@ mod starwars;
|
|||
use async_graphql::http::{playground_source, GraphQLPlaygroundConfig};
|
||||
use async_graphql::{EmptyMutation, EmptySubscription, Request, Response, Schema};
|
||||
use axum::response::IntoResponse;
|
||||
use axum::{
|
||||
extract::Extension, handler::get, response::Html, route, routing::RoutingDsl,
|
||||
AddExtensionLayer, Json,
|
||||
};
|
||||
use axum::{extract::Extension, handler::get, response::Html, route, AddExtensionLayer, Json};
|
||||
use starwars::{QueryRoot, StarWars, StarWarsSchema};
|
||||
|
||||
async fn graphql_handler(schema: Extension<StarWarsSchema>, req: Json<Request>) -> Json<Response> {
|
||||
|
|
|
@ -11,7 +11,6 @@ use axum::extract::Extension;
|
|||
use axum::handler::get;
|
||||
use axum::response::{Html, IntoResponse};
|
||||
use axum::route;
|
||||
use axum::routing::RoutingDsl;
|
||||
use axum::AddExtensionLayer;
|
||||
use futures::{sink::SinkExt, stream::StreamExt};
|
||||
use std::collections::HashSet;
|
||||
|
|
|
@ -14,9 +14,7 @@ use axum::{
|
|||
handler::{get, post},
|
||||
http::{Response, StatusCode},
|
||||
response::IntoResponse,
|
||||
route,
|
||||
routing::RoutingDsl,
|
||||
AddExtensionLayer, Json,
|
||||
route, AddExtensionLayer, Json,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//! 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 std::net::SocketAddr;
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ use axum::{
|
|||
http::{Response, StatusCode},
|
||||
response::Html,
|
||||
route,
|
||||
routing::RoutingDsl,
|
||||
};
|
||||
use std::net::SocketAddr;
|
||||
use tower::util::MapResponseLayer;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//! cargo run -p example-hello-world
|
||||
//! ```
|
||||
|
||||
use axum::{handler::get, route, routing::RoutingDsl};
|
||||
use axum::{handler::get, route};
|
||||
use std::net::SocketAddr;
|
||||
|
||||
#[tokio::main]
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
//! ```
|
||||
|
||||
use axum::{
|
||||
body::{Body, Bytes},
|
||||
body::Bytes,
|
||||
extract::{ContentLengthLimit, Extension, Path},
|
||||
handler::{delete, get, Handler},
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
route,
|
||||
routing::{BoxRoute, RoutingDsl},
|
||||
routing::{BoxRoute, Router},
|
||||
};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
|
@ -108,7 +108,7 @@ async fn list_keys(Extension(state): Extension<SharedState>) -> String {
|
|||
.join("\n")
|
||||
}
|
||||
|
||||
fn admin_routes() -> BoxRoute<Body> {
|
||||
fn admin_routes() -> Router<BoxRoute> {
|
||||
async fn delete_all_keys(Extension(state): Extension<SharedState>) {
|
||||
state.write().unwrap().db.clear();
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ use axum::{
|
|||
handler::get,
|
||||
response::Html,
|
||||
route,
|
||||
routing::RoutingDsl,
|
||||
};
|
||||
use std::net::SocketAddr;
|
||||
|
||||
|
|
|
@ -14,9 +14,7 @@ use axum::{
|
|||
handler::get,
|
||||
http::{header::SET_COOKIE, HeaderMap, Response},
|
||||
response::{IntoResponse, Redirect},
|
||||
route,
|
||||
routing::RoutingDsl,
|
||||
AddExtensionLayer,
|
||||
route, AddExtensionLayer,
|
||||
};
|
||||
use oauth2::{
|
||||
basic::BasicClient, reqwest::async_http_client, AuthUrl, AuthorizationCode, ClientId,
|
||||
|
|
|
@ -15,9 +15,7 @@ use axum::{
|
|||
StatusCode,
|
||||
},
|
||||
response::IntoResponse,
|
||||
route,
|
||||
routing::RoutingDsl,
|
||||
AddExtensionLayer,
|
||||
route, AddExtensionLayer,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::net::SocketAddr;
|
||||
|
|
|
@ -9,7 +9,7 @@ use axum::{
|
|||
handler::get,
|
||||
http::StatusCode,
|
||||
response::sse::{sse, Event, Sse},
|
||||
routing::{nest, RoutingDsl},
|
||||
routing::nest,
|
||||
};
|
||||
use futures::stream::{self, Stream};
|
||||
use std::{convert::Infallible, net::SocketAddr, time::Duration};
|
||||
|
|
|
@ -4,10 +4,7 @@
|
|||
//! cargo run -p example-static-file-server
|
||||
//! ```
|
||||
|
||||
use axum::{
|
||||
http::StatusCode,
|
||||
routing::{nest, RoutingDsl},
|
||||
};
|
||||
use axum::{http::StatusCode, routing::nest};
|
||||
use std::net::SocketAddr;
|
||||
use tower_http::{services::ServeDir, trace::TraceLayer};
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ use axum::{
|
|||
http::{Response, StatusCode},
|
||||
response::{Html, IntoResponse},
|
||||
route,
|
||||
routing::RoutingDsl,
|
||||
};
|
||||
use std::{convert::Infallible, net::SocketAddr};
|
||||
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
//! ```
|
||||
|
||||
use axum::{
|
||||
body::Body,
|
||||
handler::{get, post},
|
||||
route,
|
||||
routing::{BoxRoute, RoutingDsl},
|
||||
routing::{BoxRoute, Router},
|
||||
Json,
|
||||
};
|
||||
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
|
||||
/// without having to create an HTTP server.
|
||||
#[allow(dead_code)]
|
||||
fn app() -> BoxRoute<Body> {
|
||||
fn app() -> Router<BoxRoute> {
|
||||
route("/", get(|| async { "Hello, World!" }))
|
||||
.route(
|
||||
"/json",
|
||||
|
@ -50,6 +49,7 @@ fn app() -> BoxRoute<Body> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use axum::body::Body;
|
||||
use axum::http::{self, Request, StatusCode};
|
||||
use serde_json::{json, Value};
|
||||
use std::net::{SocketAddr, TcpListener};
|
||||
|
|
|
@ -18,9 +18,7 @@ use axum::{
|
|||
handler::{get, patch},
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
route,
|
||||
routing::RoutingDsl,
|
||||
Json,
|
||||
route, Json,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
|
|
|
@ -9,9 +9,7 @@ use axum::{
|
|||
extract::{Extension, FromRequest, RequestParts},
|
||||
handler::get,
|
||||
http::StatusCode,
|
||||
route,
|
||||
routing::RoutingDsl,
|
||||
AddExtensionLayer,
|
||||
route, AddExtensionLayer,
|
||||
};
|
||||
use bb8::{Pool, PooledConnection};
|
||||
use bb8_postgres::PostgresConnectionManager;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//! 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 tower_http::trace::TraceLayer;
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ use axum::{
|
|||
handler::get,
|
||||
http::{Method, Request, StatusCode, Uri},
|
||||
route,
|
||||
routing::RoutingDsl,
|
||||
};
|
||||
use futures::ready;
|
||||
use hyper::{
|
||||
|
|
|
@ -12,7 +12,6 @@ use axum::{
|
|||
http::{Response, StatusCode},
|
||||
response::IntoResponse,
|
||||
route,
|
||||
routing::RoutingDsl,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
|
|
|
@ -14,7 +14,7 @@ use axum::{
|
|||
handler::get,
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
routing::{nest, RoutingDsl},
|
||||
routing::nest,
|
||||
};
|
||||
use std::net::SocketAddr;
|
||||
use tower_http::{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
//! 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 async_trait::async_trait;
|
||||
|
@ -19,10 +19,10 @@ use tower_http::add_extension::AddExtension;
|
|||
|
||||
/// 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
|
||||
/// [`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> {
|
||||
svc: S,
|
||||
_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
|
||||
/// 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> {
|
||||
/// The connection information type the IO resources generates.
|
||||
type ConnectInfo: Clone + Send + Sync + 'static;
|
||||
|
@ -104,12 +104,12 @@ opaque_future! {
|
|||
/// Extractor for getting connection information produced by a [`Connected`].
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// 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)]
|
||||
pub struct ConnectInfo<T>(pub T);
|
||||
|
||||
|
@ -131,7 +131,7 @@ where
|
|||
mod tests {
|
||||
use super::*;
|
||||
use crate::Server;
|
||||
use crate::{handler::get, route, routing::RoutingDsl};
|
||||
use crate::{handler::get, route};
|
||||
use std::net::{SocketAddr, TcpListener};
|
||||
|
||||
#[tokio::test]
|
||||
|
|
|
@ -13,7 +13,6 @@ use std::ops::Deref;
|
|||
/// extract::ContentLengthLimit,
|
||||
/// handler::post,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
///
|
||||
/// async fn handler(body: ContentLengthLimit<String, 1024>) {
|
||||
|
|
|
@ -14,7 +14,6 @@ use std::ops::Deref;
|
|||
/// extract::Extension,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use std::sync::Arc;
|
||||
///
|
||||
|
|
|
@ -38,7 +38,6 @@ use tower::{BoxError, Layer, Service};
|
|||
/// extract::{extractor_middleware, FromRequest, RequestParts},
|
||||
/// handler::{get, post},
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use http::StatusCode;
|
||||
/// use async_trait::async_trait;
|
||||
|
|
|
@ -18,7 +18,6 @@ use tower::BoxError;
|
|||
/// extract::Form,
|
||||
/// handler::post,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use serde::Deserialize;
|
||||
///
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
//! Json,
|
||||
//! handler::{post, Handler},
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use serde::Deserialize;
|
||||
//!
|
||||
|
@ -44,7 +43,6 @@
|
|||
//! extract::{FromRequest, RequestParts},
|
||||
//! handler::get,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use http::{StatusCode, header::{HeaderValue, USER_AGENT}};
|
||||
//!
|
||||
|
@ -89,7 +87,6 @@
|
|||
//! extract::{Path, Query},
|
||||
//! handler::get,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use std::collections::HashMap;
|
||||
//!
|
||||
|
@ -122,7 +119,6 @@
|
|||
//! extract::Json,
|
||||
//! handler::post,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use serde_json::Value;
|
||||
//!
|
||||
|
@ -148,7 +144,6 @@
|
|||
//! extract::{Json, rejection::JsonRejection},
|
||||
//! handler::post,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use serde_json::Value;
|
||||
//!
|
||||
|
@ -190,7 +185,6 @@
|
|||
//! extract::Json,
|
||||
//! handler::post,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use serde_json::Value;
|
||||
//!
|
||||
|
@ -224,7 +218,6 @@
|
|||
//! handler::get,
|
||||
//! http::{header::HeaderMap, Request},
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//!
|
||||
//! struct MyBody<B>(B);
|
||||
|
|
|
@ -24,7 +24,6 @@ use tower::BoxError;
|
|||
/// extract::Multipart,
|
||||
/// handler::post,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use futures::stream::StreamExt;
|
||||
///
|
||||
|
|
|
@ -15,7 +15,6 @@ use std::ops::{Deref, DerefMut};
|
|||
/// extract::Path,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use uuid::Uuid;
|
||||
///
|
||||
|
@ -38,7 +37,6 @@ use std::ops::{Deref, DerefMut};
|
|||
/// extract::Path,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl,
|
||||
/// };
|
||||
/// use uuid::Uuid;
|
||||
///
|
||||
|
@ -60,7 +58,6 @@ use std::ops::{Deref, DerefMut};
|
|||
/// extract::Path,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use serde::Deserialize;
|
||||
/// use uuid::Uuid;
|
||||
|
|
|
@ -14,7 +14,6 @@ use std::ops::Deref;
|
|||
/// extract::Query,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use serde::Deserialize;
|
||||
///
|
||||
|
|
|
@ -11,7 +11,6 @@ use std::convert::Infallible;
|
|||
/// extract::RawQuery,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use futures::StreamExt;
|
||||
///
|
||||
|
|
|
@ -93,7 +93,7 @@ where
|
|||
/// use axum::{
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::{nest, RoutingDsl},
|
||||
/// routing::nest,
|
||||
/// extract::OriginalUri,
|
||||
/// http::Uri
|
||||
/// };
|
||||
|
@ -175,7 +175,6 @@ where
|
|||
/// extract::BodyStream,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use futures::StreamExt;
|
||||
///
|
||||
|
@ -229,7 +228,6 @@ where
|
|||
/// extract::Body,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl,
|
||||
/// };
|
||||
/// use futures::StreamExt;
|
||||
///
|
||||
|
|
|
@ -15,7 +15,6 @@ use std::{convert::Infallible, ops::Deref};
|
|||
/// extract::TypedHeader,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use headers::UserAgent;
|
||||
///
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
//! handler::get,
|
||||
//! response::IntoResponse,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//!
|
||||
//! let app = route("/ws", get(handler));
|
||||
|
@ -115,7 +114,6 @@ impl WebSocketUpgrade {
|
|||
/// handler::get,
|
||||
/// response::IntoResponse,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
///
|
||||
/// let app = route("/ws", get(handler));
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
extract::FromRequest,
|
||||
response::IntoResponse,
|
||||
routing::{EmptyRouter, MethodFilter},
|
||||
service::{HandleError, HandleErrorFromRouter},
|
||||
service::HandleError,
|
||||
util::Either,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
|
@ -34,7 +34,6 @@ pub use self::into_service::IntoService;
|
|||
/// use axum::{
|
||||
/// handler::any,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
///
|
||||
/// async fn handler() {}
|
||||
|
@ -80,7 +79,6 @@ where
|
|||
/// use axum::{
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
///
|
||||
/// async fn handler() {}
|
||||
|
@ -170,7 +168,7 @@ where
|
|||
/// use axum::{
|
||||
/// handler::on,
|
||||
/// route,
|
||||
/// routing::{MethodFilter, RoutingDsl},
|
||||
/// routing::MethodFilter,
|
||||
/// };
|
||||
///
|
||||
/// async fn handler() {}
|
||||
|
@ -237,7 +235,6 @@ pub trait Handler<B, T>: Clone + Send + Sized + 'static {
|
|||
/// use axum::{
|
||||
/// handler::{get, Handler},
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// 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
|
||||
/// 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>(
|
||||
self,
|
||||
f: F,
|
||||
) -> Layered<HandleError<S, F, ReqBody, HandleErrorFromRouter>, T>
|
||||
) -> Layered<HandleError<S, F, ReqBody>, T>
|
||||
where
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>>,
|
||||
F: FnOnce(S::Error) -> Result<Res, E>,
|
||||
|
@ -514,7 +511,7 @@ impl<H, B, T, F> OnMethod<H, B, T, F> {
|
|||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use axum::{handler::post, route, routing::RoutingDsl};
|
||||
/// use axum::{handler::post, route};
|
||||
///
|
||||
/// async fn handler() {}
|
||||
///
|
||||
|
@ -607,7 +604,7 @@ impl<H, B, T, F> OnMethod<H, B, T, F> {
|
|||
/// use axum::{
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::{MethodFilter, RoutingDsl}
|
||||
/// routing::MethodFilter
|
||||
/// };
|
||||
///
|
||||
/// async fn handler() {}
|
||||
|
|
|
@ -31,7 +31,6 @@ use tower::BoxError;
|
|||
/// extract,
|
||||
/// handler::post,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use serde::Deserialize;
|
||||
///
|
||||
|
@ -61,7 +60,6 @@ use tower::BoxError;
|
|||
/// extract::Path,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl,
|
||||
/// Json,
|
||||
/// };
|
||||
/// use serde::Serialize;
|
||||
|
|
34
src/lib.rs
34
src/lib.rs
|
@ -49,7 +49,6 @@
|
|||
//! use axum::{
|
||||
//! handler::get,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//!
|
||||
//! #[tokio::main]
|
||||
|
@ -107,7 +106,6 @@
|
|||
//! use axum::{
|
||||
//! handler::get,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//!
|
||||
//! let app = route("/", get(get_slash).post(post_slash))
|
||||
|
@ -132,7 +130,7 @@
|
|||
//! Routes can also be dynamic like `/users/:id`. See [extractors](#extractors)
|
||||
//! 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
|
||||
//!
|
||||
|
@ -145,7 +143,6 @@
|
|||
//! handler::get,
|
||||
//! http::Request,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use tower::{Service, ServiceExt};
|
||||
//! use http::{Method, Response, StatusCode};
|
||||
|
@ -212,7 +209,6 @@
|
|||
//! use axum::{
|
||||
//! route,
|
||||
//! handler::{get, post},
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//!
|
||||
//! // `GET /` and `POST /` are both accepted
|
||||
|
@ -237,7 +233,6 @@
|
|||
//! body::Body,
|
||||
//! http::Request,
|
||||
//! route,
|
||||
//! routing::RoutingDsl,
|
||||
//! service
|
||||
//! };
|
||||
//! use tower_http::services::ServeFile;
|
||||
|
@ -288,12 +283,12 @@
|
|||
//! http::Request,
|
||||
//! handler::get,
|
||||
//! route,
|
||||
//! routing::{BoxRoute, RoutingDsl}
|
||||
//! routing::{BoxRoute, Router}
|
||||
//! };
|
||||
//! use tower_http::services::ServeFile;
|
||||
//! use http::Response;
|
||||
//!
|
||||
//! fn api_routes() -> BoxRoute<Body> {
|
||||
//! fn api_routes() -> Router<BoxRoute> {
|
||||
//! route("/users", get(|_: Request<Body>| async { /* ... */ })).boxed()
|
||||
//! }
|
||||
//!
|
||||
|
@ -322,7 +317,6 @@
|
|||
//! extract,
|
||||
//! handler::post,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use serde::Deserialize;
|
||||
//!
|
||||
|
@ -353,7 +347,6 @@
|
|||
//! extract,
|
||||
//! handler::post,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use uuid::Uuid;
|
||||
//!
|
||||
|
@ -374,7 +367,6 @@
|
|||
//! extract,
|
||||
//! handler::get,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use uuid::Uuid;
|
||||
//! use serde::Deserialize;
|
||||
|
@ -414,7 +406,6 @@
|
|||
//! handler::post,
|
||||
//! http::Request,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//!
|
||||
//! let app = route("/users/:id", post(handler));
|
||||
|
@ -447,7 +438,6 @@
|
|||
//! http::Request,
|
||||
//! response::{Html, Json},
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use http::{StatusCode, Response, Uri};
|
||||
//! use serde_json::{Value, json};
|
||||
|
@ -531,7 +521,6 @@
|
|||
//! use axum::{
|
||||
//! handler::{get, Handler},
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use tower::limit::ConcurrencyLimitLayer;
|
||||
//!
|
||||
|
@ -554,7 +543,6 @@
|
|||
//! use axum::{
|
||||
//! handler::{get, post},
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use tower::limit::ConcurrencyLimitLayer;
|
||||
//!
|
||||
|
@ -588,7 +576,6 @@
|
|||
//! use axum::{
|
||||
//! handler::{get, Handler},
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use tower::{
|
||||
//! BoxError, timeout::{TimeoutLayer, error::Elapsed},
|
||||
|
@ -631,7 +618,7 @@
|
|||
//! return `Result<T, E>` where `T` implements
|
||||
//! [`IntoResponse`](response::IntoResponse).
|
||||
//!
|
||||
//! See [`routing::RoutingDsl::handle_error`] for more details.
|
||||
//! See [`routing::Router::handle_error`] for more details.
|
||||
//!
|
||||
//! ## Applying multiple middleware
|
||||
//!
|
||||
|
@ -643,7 +630,6 @@
|
|||
//! handler::get,
|
||||
//! http::Request,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use tower::ServiceBuilder;
|
||||
//! use tower_http::compression::CompressionLayer;
|
||||
|
@ -680,7 +666,6 @@
|
|||
//! extract,
|
||||
//! handler::get,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use std::sync::Arc;
|
||||
//!
|
||||
|
@ -750,7 +735,7 @@
|
|||
//! [`IntoResponse`]: crate::response::IntoResponse
|
||||
//! [`Timeout`]: tower::timeout::Timeout
|
||||
//! [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
|
||||
//! [`OriginalUri`]: crate::extract::OriginalUri
|
||||
|
||||
|
@ -863,13 +848,14 @@ pub use self::{error::Error, json::Json};
|
|||
/// # Panics
|
||||
///
|
||||
/// 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
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
use routing::RoutingDsl;
|
||||
|
||||
routing::EmptyRouter::not_found().route(description, service)
|
||||
routing::Router::new().route(description, service)
|
||||
}
|
||||
|
||||
mod sealed {
|
||||
|
|
|
@ -14,7 +14,6 @@ use tower::{util::Either, BoxError};
|
|||
/// ```rust
|
||||
/// use axum::{
|
||||
/// route,
|
||||
/// routing::RoutingDsl,
|
||||
/// response::{IntoResponse, Headers},
|
||||
/// handler::get,
|
||||
/// };
|
||||
|
|
|
@ -45,7 +45,6 @@ pub use self::{
|
|||
/// handler::get,
|
||||
/// response::IntoResponse,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use http_body::Body;
|
||||
/// use http::{Response, HeaderMap};
|
||||
|
|
|
@ -13,7 +13,6 @@ use std::convert::TryFrom;
|
|||
/// handler::get,
|
||||
/// response::Redirect,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
///
|
||||
/// let app = route("/old", get(|| async { Redirect::permanent("/new".parse().unwrap()) }))
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
//! use axum::{
|
||||
//! handler::get,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use axum::response::sse::{sse, Event, KeepAlive, Sse};
|
||||
//! use std::{time::Duration, convert::Infallible};
|
||||
|
|
|
@ -8,10 +8,9 @@ use crate::{
|
|||
connect_info::{Connected, IntoMakeServiceWithConnectInfo},
|
||||
OriginalUri,
|
||||
},
|
||||
service::{HandleError, HandleErrorFromRouter},
|
||||
service::HandleError,
|
||||
util::ByteStr,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use http::{Request, Response, StatusCode, Uri};
|
||||
use regex::Regex;
|
||||
|
@ -31,24 +30,55 @@ use tower_http::map_response_body::MapResponseBodyLayer;
|
|||
|
||||
pub mod future;
|
||||
pub mod or;
|
||||
|
||||
pub use self::method_filter::MethodFilter;
|
||||
|
||||
mod method_filter;
|
||||
|
||||
/// A route that sends requests to one of two [`Service`]s depending on the
|
||||
/// path.
|
||||
///
|
||||
/// Created with [`route`](crate::route). See that function for more details.
|
||||
/// The router type for composing handlers and services.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Route<S, F> {
|
||||
pub(crate) pattern: PathPattern,
|
||||
pub(crate) svc: S,
|
||||
pub(crate) fallback: F,
|
||||
pub struct Router<S> {
|
||||
svc: S,
|
||||
}
|
||||
|
||||
/// Trait for building routers.
|
||||
#[async_trait]
|
||||
pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
||||
impl<E> Router<EmptyRouter<E>> {
|
||||
/// Create a new `Router`.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -57,7 +87,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
|||
/// use axum::{
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
///
|
||||
/// 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();
|
||||
/// # };
|
||||
/// ```
|
||||
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
|
||||
T: Service<Request<B>> + Clone,
|
||||
{
|
||||
Route {
|
||||
self.map(|fallback| Route {
|
||||
pattern: PathPattern::new(description),
|
||||
svc,
|
||||
fallback: self,
|
||||
}
|
||||
fallback,
|
||||
})
|
||||
}
|
||||
|
||||
/// Nest another service inside this router at the given path.
|
||||
///
|
||||
/// 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
|
||||
T: Service<Request<B>> + Clone,
|
||||
{
|
||||
Nested {
|
||||
self.map(|fallback| Nested {
|
||||
pattern: PathPattern::new(description),
|
||||
svc,
|
||||
fallback: self,
|
||||
}
|
||||
fallback,
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a boxed route trait object.
|
||||
|
@ -109,7 +138,7 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
|||
/// body::Body,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::{BoxRoute, RoutingDsl}
|
||||
/// routing::{Router, BoxRoute}
|
||||
/// };
|
||||
///
|
||||
/// async fn first_handler() { /* ... */ }
|
||||
|
@ -118,7 +147,7 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
|||
///
|
||||
/// async fn third_handler() { /* ... */ }
|
||||
///
|
||||
/// fn app() -> BoxRoute<Body> {
|
||||
/// fn app() -> Router<BoxRoute> {
|
||||
/// route("/", get(first_handler).post(second_handler))
|
||||
/// .route("/foo", get(third_handler))
|
||||
/// .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
|
||||
/// routes.
|
||||
fn boxed<ReqBody, ResBody>(self) -> BoxRoute<ReqBody, Self::Error>
|
||||
pub fn boxed<ReqBody, ResBody>(self) -> Router<BoxRoute<ReqBody, S::Error>>
|
||||
where
|
||||
Self: Service<Request<ReqBody>, Response = Response<ResBody>> + Send + 'static,
|
||||
<Self as Service<Request<ReqBody>>>::Error: Into<BoxError> + Send + Sync,
|
||||
<Self as Service<Request<ReqBody>>>::Future: Send,
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>> + Send + 'static,
|
||||
S::Error: Into<BoxError> + Send + Sync,
|
||||
S::Future: Send,
|
||||
ReqBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
||||
ReqBody::Error: Into<BoxError> + Send + Sync + 'static,
|
||||
ResBody: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
||||
ResBody::Error: Into<BoxError> + Send + Sync + 'static,
|
||||
{
|
||||
ServiceBuilder::new()
|
||||
.layer_fn(BoxRoute)
|
||||
.layer_fn(MpscBuffer::new)
|
||||
.layer(BoxService::layer())
|
||||
.layer(MapResponseBodyLayer::new(box_body))
|
||||
.service(self)
|
||||
self.map(|svc| {
|
||||
ServiceBuilder::new()
|
||||
.layer_fn(BoxRoute)
|
||||
.layer_fn(MpscBuffer::new)
|
||||
.layer(BoxService::layer())
|
||||
.layer(MapResponseBodyLayer::new(box_body))
|
||||
.service(svc)
|
||||
})
|
||||
}
|
||||
|
||||
/// Apply a [`tower::Layer`] to the router.
|
||||
|
@ -165,7 +196,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
|||
/// use axum::{
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use tower::limit::{ConcurrencyLimitLayer, ConcurrencyLimit};
|
||||
///
|
||||
|
@ -195,7 +225,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
|||
/// use axum::{
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// 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();
|
||||
/// # };
|
||||
/// ```
|
||||
fn layer<L>(self, layer: L) -> Layered<L::Service>
|
||||
pub fn layer<L>(self, layer: L) -> Router<Layered<L::Service>>
|
||||
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
|
||||
|
@ -230,7 +259,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
|||
/// use axum::{
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
///
|
||||
/// let app = route("/", get(|| async { "Hi!" }));
|
||||
|
@ -244,11 +272,11 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
|||
/// ```
|
||||
///
|
||||
/// [`MakeService`]: tower::make::MakeService
|
||||
fn into_make_service(self) -> tower::make::Shared<Self>
|
||||
pub fn into_make_service(self) -> tower::make::Shared<S>
|
||||
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
|
||||
|
@ -264,7 +292,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
|||
/// extract::ConnectInfo,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use std::net::SocketAddr;
|
||||
///
|
||||
|
@ -291,7 +318,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
|||
/// extract::connect_info::{ConnectInfo, Connected},
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use hyper::server::conn::AddrStream;
|
||||
///
|
||||
|
@ -335,14 +361,14 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
|||
/// [`Connected`]: crate::extract::connect_info::Connected
|
||||
/// [`ConnectInfo`]: crate::extract::connect_info::ConnectInfo
|
||||
/// [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,
|
||||
) -> IntoMakeServiceWithConnectInfo<Self, C>
|
||||
) -> IntoMakeServiceWithConnectInfo<S, C>
|
||||
where
|
||||
Self: Clone,
|
||||
S: Clone,
|
||||
C: Connected<Target>,
|
||||
{
|
||||
IntoMakeServiceWithConnectInfo::new(self)
|
||||
IntoMakeServiceWithConnectInfo::new(self.svc)
|
||||
}
|
||||
|
||||
/// Merge two routers into one.
|
||||
|
@ -354,7 +380,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
|||
/// use axum::{
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// #
|
||||
/// # 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();
|
||||
/// # };
|
||||
/// ```
|
||||
fn or<S>(self, other: S) -> or::Or<Self, S>
|
||||
where
|
||||
S: RoutingDsl,
|
||||
{
|
||||
or::Or {
|
||||
first: self,
|
||||
pub fn or<S2>(self, other: S2) -> Router<or::Or<S, S2>> {
|
||||
self.map(|first| or::Or {
|
||||
first,
|
||||
second: other,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// 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,
|
||||
/// http::StatusCode,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use tower::{BoxError, timeout::TimeoutLayer};
|
||||
/// use std::{time::Duration, convert::Infallible};
|
||||
|
@ -435,7 +456,6 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
|||
/// handler::get,
|
||||
/// http::StatusCode,
|
||||
/// route,
|
||||
/// routing::RoutingDsl
|
||||
/// };
|
||||
/// use tower::{BoxError, timeout::TimeoutLayer};
|
||||
/// 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();
|
||||
/// # };
|
||||
/// ```
|
||||
fn handle_error<ReqBody, F>(
|
||||
self,
|
||||
f: F,
|
||||
) -> HandleError<Self, F, ReqBody, HandleErrorFromRouter> {
|
||||
HandleError::new(self, f)
|
||||
pub fn handle_error<ReqBody, F>(self, f: F) -> Router<HandleError<S, F, ReqBody>> {
|
||||
self.map(|svc| HandleError::new(svc, f))
|
||||
}
|
||||
|
||||
/// Check that your service cannot fail.
|
||||
///
|
||||
/// That is, its error type is [`Infallible`].
|
||||
fn check_infallible(self) -> CheckInfallible<Self> {
|
||||
CheckInfallible(self)
|
||||
pub fn check_infallible(self) -> Router<CheckInfallible<S>> {
|
||||
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> {}
|
||||
|
||||
impl<S, F> crate::sealed::Sealed for Route<S, F> {}
|
||||
/// A route that sends requests to one of two [`Service`]s depending on the
|
||||
/// path.
|
||||
///
|
||||
/// 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>
|
||||
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>
|
||||
where
|
||||
B: Send + Sync + 'static,
|
||||
|
@ -728,8 +755,8 @@ type Captures = Vec<(String, String)>;
|
|||
|
||||
/// A boxed route trait object.
|
||||
///
|
||||
/// See [`RoutingDsl::boxed`] for more details.
|
||||
pub struct BoxRoute<B, E = Infallible>(
|
||||
/// See [`Router::boxed`] for more details.
|
||||
pub struct BoxRoute<B = crate::body::Body, E = Infallible>(
|
||||
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>
|
||||
where
|
||||
E: Into<BoxError>,
|
||||
|
@ -772,7 +795,7 @@ where
|
|||
|
||||
/// 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> {
|
||||
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>
|
||||
where
|
||||
S: Service<R>,
|
||||
|
@ -835,7 +854,7 @@ where
|
|||
/// use axum::{
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::{nest, RoutingDsl},
|
||||
/// routing::nest,
|
||||
/// };
|
||||
/// use http::Uri;
|
||||
///
|
||||
|
@ -864,7 +883,7 @@ where
|
|||
/// extract::Path,
|
||||
/// handler::get,
|
||||
/// route,
|
||||
/// routing::{nest, RoutingDsl},
|
||||
/// routing::nest,
|
||||
/// };
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
|
@ -888,7 +907,7 @@ where
|
|||
///
|
||||
/// ```
|
||||
/// use axum::{
|
||||
/// routing::{nest, RoutingDsl},
|
||||
/// routing::nest,
|
||||
/// service::get,
|
||||
/// };
|
||||
/// 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
|
||||
/// `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
|
||||
S: Service<Request<B>> + Clone,
|
||||
{
|
||||
Nested {
|
||||
pattern: PathPattern::new(description),
|
||||
svc,
|
||||
fallback: EmptyRouter::not_found(),
|
||||
}
|
||||
Router::new().nest(description, svc)
|
||||
}
|
||||
|
||||
/// 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)]
|
||||
pub struct Nested<S, F> {
|
||||
pattern: PathPattern,
|
||||
|
@ -926,10 +941,6 @@ pub struct Nested<S, 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>
|
||||
where
|
||||
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.
|
||||
///
|
||||
/// Created with [`check_infallible`](RoutingDsl::check_infallible).
|
||||
/// Created with [`check_infallible`](Router::check_infallible).
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
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)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! [`Or`] used to combine two services into one.
|
||||
|
||||
use super::{FromEmptyRouter, OrDepth, RoutingDsl};
|
||||
use super::{FromEmptyRouter, OrDepth};
|
||||
use crate::body::BoxBody;
|
||||
use futures_util::ready;
|
||||
use http::{Request, Response};
|
||||
|
@ -14,19 +14,15 @@ use tower::{util::Oneshot, Service, ServiceExt};
|
|||
|
||||
/// [`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)]
|
||||
pub struct Or<A, B> {
|
||||
pub(super) first: A,
|
||||
pub(super) second: B,
|
||||
}
|
||||
|
||||
impl<A, B> RoutingDsl for Or<A, B> {}
|
||||
|
||||
impl<A, B> crate::sealed::Sealed for Or<A, B> {}
|
||||
|
||||
#[allow(warnings)]
|
||||
impl<A, B, ReqBody> Service<Request<ReqBody>> for Or<A, B>
|
||||
where
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
//! handler::get,
|
||||
//! http::Request,
|
||||
//! route,
|
||||
//! routing::RoutingDsl,
|
||||
//! service,
|
||||
//! };
|
||||
//!
|
||||
|
@ -68,7 +67,6 @@
|
|||
//! use axum::{
|
||||
//! handler::get,
|
||||
//! route,
|
||||
//! routing::RoutingDsl
|
||||
//! };
|
||||
//! use tower::ServiceBuilder;
|
||||
//! # let some_backpressure_sensitive_middleware =
|
||||
|
@ -151,7 +149,6 @@ where
|
|||
/// use axum::{
|
||||
/// http::Request,
|
||||
/// route,
|
||||
/// routing::RoutingDsl,
|
||||
/// service,
|
||||
/// };
|
||||
/// use http::Response;
|
||||
|
@ -249,7 +246,7 @@ where
|
|||
/// handler::on,
|
||||
/// service,
|
||||
/// route,
|
||||
/// routing::{MethodFilter, RoutingDsl},
|
||||
/// routing::MethodFilter,
|
||||
/// };
|
||||
/// use http::Response;
|
||||
/// use std::convert::Infallible;
|
||||
|
@ -344,7 +341,7 @@ impl<S, F, B> OnMethod<S, F, B> {
|
|||
/// handler::on,
|
||||
/// service,
|
||||
/// route,
|
||||
/// routing::{MethodFilter, RoutingDsl},
|
||||
/// routing::MethodFilter,
|
||||
/// };
|
||||
/// use http::Response;
|
||||
/// use std::convert::Infallible;
|
||||
|
@ -447,7 +444,7 @@ impl<S, F, B> OnMethod<S, F, B> {
|
|||
/// handler::on,
|
||||
/// service,
|
||||
/// route,
|
||||
/// routing::{MethodFilter, RoutingDsl},
|
||||
/// routing::MethodFilter,
|
||||
/// };
|
||||
/// use http::Response;
|
||||
/// 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.
|
||||
///
|
||||
/// Works similarly to [`RoutingDsl::handle_error`]. See that for more
|
||||
/// Works similarly to [`Router::handle_error`]. See that for more
|
||||
/// details.
|
||||
///
|
||||
/// [`RoutingDsl::handle_error`]: crate::routing::RoutingDsl::handle_error
|
||||
pub fn handle_error<ReqBody, H>(
|
||||
self,
|
||||
f: H,
|
||||
) -> HandleError<Self, H, ReqBody, HandleErrorFromService> {
|
||||
/// [`Router::handle_error`]: crate::routing::Router::handle_error
|
||||
pub fn handle_error<ReqBody, H>(self, f: H) -> HandleError<Self, H, ReqBody> {
|
||||
HandleError::new(self, f)
|
||||
}
|
||||
}
|
||||
|
@ -536,15 +530,15 @@ where
|
|||
///
|
||||
/// Created with
|
||||
/// [`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.
|
||||
pub struct HandleError<S, F, B, T> {
|
||||
pub struct HandleError<S, F, B> {
|
||||
inner: S,
|
||||
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
|
||||
S: Clone,
|
||||
F: Clone,
|
||||
|
@ -554,23 +548,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Marker type used for [`HandleError`] to indicate that it should implement
|
||||
/// [`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> {
|
||||
impl<S, F, B> HandleError<S, F, B> {
|
||||
pub(crate) fn new(inner: S, f: F) -> Self {
|
||||
Self {
|
||||
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
|
||||
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
|
||||
S: Service<Request<ReqBody>, Response = Response<ResBody>> + 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() {}
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
response::IntoResponse,
|
||||
route,
|
||||
routing::nest,
|
||||
routing::{MethodFilter, RoutingDsl},
|
||||
routing::MethodFilter,
|
||||
service,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
|
|
Loading…
Add table
Reference in a new issue