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:
David Pedersen
2021-07-31 21:36:30 +02:00
committed by GitHub
parent 407aa533d7
commit f67abd1ee2
6 changed files with 333 additions and 5 deletions
+34 -4
View File
@@ -1,4 +1,7 @@
use axum::prelude::*;
use axum::{
extract::connect_info::{self, ConnectInfo},
prelude::*,
};
use futures::ready;
use http::{Method, StatusCode, Uri};
use hyper::{
@@ -9,9 +12,10 @@ use std::{
io,
path::PathBuf,
pin::Pin,
sync::Arc,
task::{Context, Poll},
};
use tokio::net::UnixListener;
use tokio::net::{unix::UCred, UnixListener};
use tokio::{
io::{AsyncRead, AsyncWrite},
net::UnixStream,
@@ -35,10 +39,10 @@ async fn main() {
let uds = UnixListener::bind(path.clone()).unwrap();
tokio::spawn(async {
let app = route("/", get(|| async { "Hello, World!" }));
let app = route("/", get(handler));
hyper::Server::builder(ServerAccept { uds })
.serve(app.into_make_service())
.serve(app.into_make_service_with_connect_info::<UdsConnectInfo, _>())
.await
.unwrap();
});
@@ -67,6 +71,12 @@ async fn main() {
assert_eq!(body, "Hello, World!");
}
async fn handler(ConnectInfo(info): ConnectInfo<UdsConnectInfo>) -> &'static str {
println!("new connection from `{:?}`", info);
"Hello, World!"
}
struct ServerAccept {
uds: UnixListener,
}
@@ -124,3 +134,23 @@ impl Connection for ClientConnection {
Connected::new()
}
}
#[derive(Clone, Debug)]
struct UdsConnectInfo {
peer_addr: Arc<tokio::net::unix::SocketAddr>,
peer_cred: UCred,
}
impl connect_info::Connected<&UnixStream> for UdsConnectInfo {
type ConnectInfo = Self;
fn connect_info(target: &UnixStream) -> Self::ConnectInfo {
let peer_addr = target.peer_addr().unwrap();
let peer_cred = target.peer_cred().unwrap();
Self {
peer_addr: Arc::new(peer_addr),
peer_cred,
}
}
}