mirror of
https://github.com/tokio-rs/axum.git
synced 2026-08-26 00:00:23 +02:00
Add extractor for remote connection info (#55)
Fixes https://github.com/tokio-rs/axum/issues/43 With this you can get the remote address like so: ```rust use axum::{prelude::*, extract::ConnectInfo}; use std::net::SocketAddr; let app = route("/", get(handler)); async fn handler(ConnectInfo(addr): ConnectInfo<SocketAddr>) -> String { format!("Hello {}", addr) } // Starting the app with `into_make_service_with_connect_info` is required // for `ConnectInfo` to work. let make_svc = app.into_make_service_with_connect_info::<SocketAddr, _>(); hyper::Server::bind(&"0.0.0.0:3000".parse().unwrap()) .serve(make_svc) .await .expect("server failed"); ``` This API is fully generic and supports whatever transport layer you're using with Hyper. I've updated the unix domain socket example to extract `peer_creds` and `peer_addr`.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
use crate::{
|
||||
body::{box_body, BoxBody},
|
||||
buffer::MpscBuffer,
|
||||
extract::connect_info::{Connected, IntoMakeServiceWithConnectInfo},
|
||||
response::IntoResponse,
|
||||
util::ByteStr,
|
||||
};
|
||||
@@ -266,6 +267,93 @@ pub trait RoutingDsl: crate::sealed::Sealed + Sized {
|
||||
{
|
||||
tower::make::Shared::new(self)
|
||||
}
|
||||
|
||||
/// Convert this router into a [`MakeService`], that will store `C`'s
|
||||
/// associated `ConnectInfo` in a request extension such that [`ConnectInfo`]
|
||||
/// can extract it.
|
||||
///
|
||||
/// This enables extracting things like the client's remote address.
|
||||
///
|
||||
/// Extracting [`std::net::SocketAddr`] is supported out of the box:
|
||||
///
|
||||
/// ```
|
||||
/// use axum::{prelude::*, extract::ConnectInfo};
|
||||
/// use std::net::SocketAddr;
|
||||
///
|
||||
/// let app = route("/", get(handler));
|
||||
///
|
||||
/// async fn handler(ConnectInfo(addr): ConnectInfo<SocketAddr>) -> String {
|
||||
/// format!("Hello {}", addr)
|
||||
/// }
|
||||
///
|
||||
/// # async {
|
||||
/// hyper::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
||||
/// .serve(
|
||||
/// app.into_make_service_with_connect_info::<SocketAddr, _>()
|
||||
/// )
|
||||
/// .await
|
||||
/// .expect("server failed");
|
||||
/// # };
|
||||
/// ```
|
||||
///
|
||||
/// You can implement custom a [`Connected`] like so:
|
||||
///
|
||||
/// ```
|
||||
/// use axum::{
|
||||
/// prelude::*,
|
||||
/// extract::connect_info::{ConnectInfo, Connected},
|
||||
/// };
|
||||
/// use hyper::server::conn::AddrStream;
|
||||
///
|
||||
/// let app = route("/", get(handler));
|
||||
///
|
||||
/// async fn handler(
|
||||
/// ConnectInfo(my_connect_info): ConnectInfo<MyConnectInfo>,
|
||||
/// ) -> String {
|
||||
/// format!("Hello {:?}", my_connect_info)
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Clone, Debug)]
|
||||
/// struct MyConnectInfo {
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// impl Connected<&AddrStream> for MyConnectInfo {
|
||||
/// type ConnectInfo = MyConnectInfo;
|
||||
///
|
||||
/// fn connect_info(target: &AddrStream) -> Self::ConnectInfo {
|
||||
/// MyConnectInfo {
|
||||
/// // ...
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// # async {
|
||||
/// hyper::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
||||
/// .serve(
|
||||
/// app.into_make_service_with_connect_info::<MyConnectInfo, _>()
|
||||
/// )
|
||||
/// .await
|
||||
/// .expect("server failed");
|
||||
/// # };
|
||||
/// ```
|
||||
///
|
||||
/// See the [unix domain socket example][uds] for an example of how to use
|
||||
/// this to collect UDS connection info.
|
||||
///
|
||||
/// [`MakeService`]: tower::make::MakeService
|
||||
/// [`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>(
|
||||
self,
|
||||
) -> IntoMakeServiceWithConnectInfo<Self, C>
|
||||
where
|
||||
Self: Clone,
|
||||
C: Connected<Target>,
|
||||
{
|
||||
IntoMakeServiceWithConnectInfo::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, F> RoutingDsl for Route<S, F> {}
|
||||
|
||||
Reference in New Issue
Block a user