Move middleware::from_fn into axum (#719)

* Move `middleware::from_fn` into axum

* changelog

* fix feature

* Rephrase changelog a bit
This commit is contained in:
David Pedersen
2022-02-22 13:33:10 +01:00
parent 340948c337
commit 6d821d2a23
11 changed files with 48 additions and 36 deletions
+7
View File
@@ -8,8 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# Unreleased # Unreleased
- **fix:** Depend on tower with `default_features = false` ([#666]) - **fix:** Depend on tower with `default_features = false` ([#666])
- **change:** `middleware::from_fn` has been deprecated and moved into the main
axum crate ([#719])
[#666]: https://github.com/tokio-rs/axum/pull/666 [#666]: https://github.com/tokio-rs/axum/pull/666
[#719]: https://github.com/tokio-rs/axum/pull/719
# 0.1.2 (13. January, 2021)
- **fix:** Depend on tower with `default_features = false` ([#666])
# 0.1.1 (27. December, 2021) # 0.1.1 (27. December, 2021)
+1 -1
View File
@@ -20,7 +20,7 @@ http = "0.2"
mime = "0.3" mime = "0.3"
pin-project-lite = "0.2" pin-project-lite = "0.2"
tower = { version = "0.4", default_features = false, features = ["util"] } tower = { version = "0.4", default_features = false, features = ["util"] }
tower-http = { version = "0.2", features = ["util", "map-response-body"] } tower-http = { version = "0.2", features = ["map-response-body"] }
tower-layer = "0.3" tower-layer = "0.3"
tower-service = "0.3" tower-service = "0.3"
-1
View File
@@ -44,6 +44,5 @@
#![cfg_attr(test, allow(clippy::float_cmp))] #![cfg_attr(test, allow(clippy::float_cmp))]
pub mod extract; pub mod extract;
pub mod middleware;
pub mod response; pub mod response;
pub mod routing; pub mod routing;
-5
View File
@@ -1,5 +0,0 @@
//! Additional types for creating middleware.
pub mod middleware_fn;
pub use self::middleware_fn::{from_fn, Next};
+4 -1
View File
@@ -7,7 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# Unreleased # Unreleased
- None. - **added:** `middleware::from_fn` for creating middleware from async functions.
This previously lived in axum-extra but has been moved to axum ([#719])
[#719]: https://github.com/tokio-rs/axum/pull/719
# 0.4.5 (31. January, 2022) # 0.4.5 (31. January, 2022)
+1 -1
View File
@@ -39,7 +39,7 @@ sync_wrapper = "0.1.1"
tokio = { version = "1", features = ["time"] } tokio = { version = "1", features = ["time"] }
tokio-util = "0.6" tokio-util = "0.6"
tower = { version = "0.4.11", default-features = false, features = ["util", "buffer", "make"] } tower = { version = "0.4.11", default-features = false, features = ["util", "buffer", "make"] }
tower-http = { version = "0.2.0", features = ["map-response-body"] } tower-http = { version = "0.2.0", features = ["util", "map-response-body"] }
tower-layer = "0.3" tower-layer = "0.3"
tower-service = "0.3" tower-service = "0.3"
+1
View File
@@ -463,6 +463,7 @@ pub mod body;
pub mod error_handling; pub mod error_handling;
pub mod extract; pub mod extract;
pub mod handler; pub mod handler;
pub mod middleware;
pub mod response; pub mod response;
pub mod routing; pub mod routing;
@@ -1,8 +1,4 @@
//! Create middleware from async functions. use crate::{
//!
//! See [`from_fn`] for more details.
use axum::{
body::{self, Bytes, HttpBody}, body::{self, Bytes, HttpBody},
response::{IntoResponse, Response}, response::{IntoResponse, Response},
BoxError, BoxError,
@@ -39,8 +35,8 @@ use tower_service::Service;
/// http::{Request, StatusCode}, /// http::{Request, StatusCode},
/// routing::get, /// routing::get,
/// response::IntoResponse, /// response::IntoResponse,
/// middleware::{self, Next},
/// }; /// };
/// use axum_extra::middleware::{self, Next};
/// ///
/// async fn auth<B>(req: Request<B>, next: Next<B>) -> impl IntoResponse { /// async fn auth<B>(req: Request<B>, next: Next<B>) -> impl IntoResponse {
/// let auth_header = req.headers() /// let auth_header = req.headers()
@@ -76,8 +72,8 @@ use tower_service::Service;
/// http::{Request, StatusCode}, /// http::{Request, StatusCode},
/// routing::get, /// routing::get,
/// response::IntoResponse, /// response::IntoResponse,
/// middleware::{self, Next}
/// }; /// };
/// use axum_extra::middleware::{self, Next};
/// ///
/// #[derive(Clone)] /// #[derive(Clone)]
/// struct State { /* ... */ } /// struct State { /* ... */ }
@@ -109,9 +105,9 @@ use tower_service::Service;
/// http::{Request, StatusCode}, /// http::{Request, StatusCode},
/// routing::get, /// routing::get,
/// response::IntoResponse, /// response::IntoResponse,
/// middleware::{self, Next},
/// AddExtensionLayer, /// AddExtensionLayer,
/// }; /// };
/// use axum_extra::middleware::{self, Next};
/// use tower::ServiceBuilder; /// use tower::ServiceBuilder;
/// ///
/// #[derive(Clone)] /// #[derive(Clone)]
@@ -138,37 +134,37 @@ use tower_service::Service;
/// ); /// );
/// # let app: Router = app; /// # let app: Router = app;
/// ``` /// ```
pub fn from_fn<F>(f: F) -> MiddlewareFnLayer<F> { pub fn from_fn<F>(f: F) -> FromFnLayer<F> {
MiddlewareFnLayer { f } FromFnLayer { f }
} }
/// A [`tower::Layer`] from an async function. /// A [`tower::Layer`] from an async function.
/// ///
/// [`tower::Layer`] is used to apply middleware to [`axum::Router`]s. /// [`tower::Layer`] is used to apply middleware to [`Router`](crate::Router)'s.
/// ///
/// Created with [`from_fn`]. See that function for more details. /// Created with [`from_fn`]. See that function for more details.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct MiddlewareFnLayer<F> { pub struct FromFnLayer<F> {
f: F, f: F,
} }
impl<S, F> Layer<S> for MiddlewareFnLayer<F> impl<S, F> Layer<S> for FromFnLayer<F>
where where
F: Clone, F: Clone,
{ {
type Service = MiddlewareFn<F, S>; type Service = FromFn<F, S>;
fn layer(&self, inner: S) -> Self::Service { fn layer(&self, inner: S) -> Self::Service {
MiddlewareFn { FromFn {
f: self.f.clone(), f: self.f.clone(),
inner, inner,
} }
} }
} }
impl<F> fmt::Debug for MiddlewareFnLayer<F> { impl<F> fmt::Debug for FromFnLayer<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MiddlewareFnLayer") f.debug_struct("FromFnLayer")
// Write out the type name, without quoting it as `&type_name::<F>()` would // Write out the type name, without quoting it as `&type_name::<F>()` would
.field("f", &format_args!("{}", type_name::<F>())) .field("f", &format_args!("{}", type_name::<F>()))
.finish() .finish()
@@ -179,12 +175,12 @@ impl<F> fmt::Debug for MiddlewareFnLayer<F> {
/// ///
/// Created with [`from_fn`]. See that function for more details. /// Created with [`from_fn`]. See that function for more details.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct MiddlewareFn<F, S> { pub struct FromFn<F, S> {
f: F, f: F,
inner: S, inner: S,
} }
impl<F, Fut, Out, S, ReqBody, ResBody> Service<Request<ReqBody>> for MiddlewareFn<F, S> impl<F, Fut, Out, S, ReqBody, ResBody> Service<Request<ReqBody>> for FromFn<F, S>
where where
F: FnMut(Request<ReqBody>, Next<ReqBody>) -> Fut, F: FnMut(Request<ReqBody>, Next<ReqBody>) -> Fut,
Fut: Future<Output = Out>, Fut: Future<Output = Out>,
@@ -221,12 +217,12 @@ where
} }
} }
impl<F, S> fmt::Debug for MiddlewareFn<F, S> impl<F, S> fmt::Debug for FromFn<F, S>
where where
S: fmt::Debug, S: fmt::Debug,
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MiddlewareFnLayer") f.debug_struct("FromFnLayer")
.field("f", &format_args!("{}", type_name::<F>())) .field("f", &format_args!("{}", type_name::<F>()))
.field("inner", &self.inner) .field("inner", &self.inner)
.finish() .finish()
@@ -250,14 +246,14 @@ impl<ReqBody> Next<ReqBody> {
impl<ReqBody> fmt::Debug for Next<ReqBody> { impl<ReqBody> fmt::Debug for Next<ReqBody> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MiddlewareFnLayer") f.debug_struct("FromFnLayer")
.field("inner", &self.inner) .field("inner", &self.inner)
.finish() .finish()
} }
} }
pin_project! { pin_project! {
/// Response future for [`MiddlewareFn`]. /// Response future for [`FromFn`].
pub struct ResponseFuture<F> { pub struct ResponseFuture<F> {
#[pin] #[pin]
inner: F, inner: F,
@@ -283,7 +279,7 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use axum::{body::Empty, routing::get, Router}; use crate::{body::Empty, routing::get, Router};
use http::{HeaderMap, StatusCode}; use http::{HeaderMap, StatusCode};
use tower::ServiceExt; use tower::ServiceExt;
+5
View File
@@ -0,0 +1,5 @@
//! Utilities for writing middleware
mod from_fn;
pub use self::from_fn::{from_fn, FromFn, FromFnLayer, Next};
+1 -1
View File
@@ -7,11 +7,11 @@
use axum::{ use axum::{
body::{Body, Bytes}, body::{Body, Bytes},
http::{Request, StatusCode}, http::{Request, StatusCode},
middleware::{self, Next},
response::{IntoResponse, Response}, response::{IntoResponse, Response},
routing::post, routing::post,
Router, Router,
}; };
use axum_extra::middleware::{self, Next};
use std::net::SocketAddr; use std::net::SocketAddr;
#[tokio::main] #[tokio::main]
+8 -2
View File
@@ -7,8 +7,14 @@
//! cargo run -p example-prometheus-metrics //! cargo run -p example-prometheus-metrics
//! ``` //! ```
use axum::{extract::MatchedPath, http::Request, response::IntoResponse, routing::get, Router}; use axum::{
use axum_extra::middleware::{self, Next}; extract::MatchedPath,
http::Request,
middleware::{self, Next},
response::IntoResponse,
routing::get,
Router,
};
use metrics_exporter_prometheus::{Matcher, PrometheusBuilder, PrometheusHandle}; use metrics_exporter_prometheus::{Matcher, PrometheusBuilder, PrometheusHandle};
use std::{ use std::{
future::ready, future::ready,