Axum's into_make_service_with_connect_info
provides the following way to access the IP address if the remote address:
https://docs.rs/axum/latest/axum/struct.Router.html#method.into_make_service_with_connect_info
Note how it says:
You can implement custom a Connected like so:
async fn handler(
ConnectInfo(my_connect_info): ConnectInfo<MyConnectInfo>,
) -> String {
format!("Hello {my_connect_info:?}")
}
#[derive(Clone, Debug)]
struct MyConnectInfo {
// ...
}
impl Connected<IncomingStream<'_, TcpListener>> for MyConnectInfo {
fn connect_info(target: IncomingStream<'_, TcpListener>) -> Self {
MyConnectInfo {
// ...
}
}
}
I am able to use this to have my custom MyConnectionInfo
which can be accessed by all my routes:
#[derive(Clone, Debug)]
struct MyConnectionInfo {
ip: String,
user_agent: String,
}
impl Connected<IncomingStream<'_, TcpListener>> for MyConnectionInfo {
fn connect_info(target: IncomingStream<'_, TcpListener>) -> Self {
MyConnectionInfo {
ip: target.remote_addr().to_string(), user_agent: "Firefox".to_string()
}
}
}
I am able to successfully get the target.remote_addr()
. However, for the user agent, I am not sure how to access it within this custom impl
. (note the currently hardcoded "Firefox" string).
Axum provides a way to get the user agent from the TypedHeader
as below:
https://docs.rs/axum/latest/axum/extract/index.html
Is it possible to access this user agent and other headers within my custom impl
?
Or is my approach wrong?
You cannot access the user agent from a Connected
implementation.
It is for retrieving metadata from the underlying connection - a TcpStream
under typical conditions. The user agent on the other hand is only accessible from the HTTP headers which haven't even been parsed yet.
If you do not need anything from the TCP layer beyond what ConnectInfo
already can get, you likely just want a custom extractor (via a FromRequestParts
implementation) from which you can get the existing ConnectInfo
and any TypedHeader
s as you require for your handlers or middleware.