mirror of
https://github.com/actix/actix-web.git
synced 2024-05-19 16:58:14 +00:00
Compare commits
2 commits
cf2d3f3e9b
...
a735c3e4fc
Author | SHA1 | Date | |
---|---|---|---|
a735c3e4fc | |||
4d3d6f8d3a |
|
@ -9,6 +9,7 @@
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.72.
|
- Minimum supported Rust version (MSRV) is now 1.72.
|
||||||
|
- `ConnectionInfo.realip_remote_addr()` now returns just IP addresses from `Forwarded` header.
|
||||||
|
|
||||||
## 4.5.1
|
## 4.5.1
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,19 @@ fn unquote(val: &str) -> &str {
|
||||||
val.trim().trim_start_matches('"').trim_end_matches('"')
|
val.trim().trim_start_matches('"').trim_end_matches('"')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove port and IPv6 square brackets from a peer specification.
|
||||||
|
fn bare_address(val: &str) -> &str {
|
||||||
|
if val.starts_with('[') {
|
||||||
|
val.split("]:")
|
||||||
|
.next()
|
||||||
|
.map(|s| s.trim_start_matches('[').trim_end_matches(']'))
|
||||||
|
// This shouldn't *actually* ever happen
|
||||||
|
.unwrap_or(val)
|
||||||
|
} else {
|
||||||
|
val.split(':').next().unwrap_or(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Extracts and trims first value for given header name.
|
/// Extracts and trims first value for given header name.
|
||||||
fn first_header_value<'a>(req: &'a RequestHead, name: &'_ HeaderName) -> Option<&'a str> {
|
fn first_header_value<'a>(req: &'a RequestHead, name: &'_ HeaderName) -> Option<&'a str> {
|
||||||
let hdr = req.headers.get(name)?.to_str().ok()?;
|
let hdr = req.headers.get(name)?.to_str().ok()?;
|
||||||
|
@ -100,7 +113,7 @@ impl ConnectionInfo {
|
||||||
// --- https://datatracker.ietf.org/doc/html/rfc7239#section-5.2
|
// --- https://datatracker.ietf.org/doc/html/rfc7239#section-5.2
|
||||||
|
|
||||||
match name.trim().to_lowercase().as_str() {
|
match name.trim().to_lowercase().as_str() {
|
||||||
"for" => realip_remote_addr.get_or_insert_with(|| unquote(val)),
|
"for" => realip_remote_addr.get_or_insert_with(|| bare_address(unquote(val))),
|
||||||
"proto" => scheme.get_or_insert_with(|| unquote(val)),
|
"proto" => scheme.get_or_insert_with(|| unquote(val)),
|
||||||
"host" => host.get_or_insert_with(|| unquote(val)),
|
"host" => host.get_or_insert_with(|| unquote(val)),
|
||||||
"by" => {
|
"by" => {
|
||||||
|
@ -368,16 +381,25 @@ mod tests {
|
||||||
.insert_header((header::FORWARDED, r#"for="192.0.2.60:8080""#))
|
.insert_header((header::FORWARDED, r#"for="192.0.2.60:8080""#))
|
||||||
.to_http_request();
|
.to_http_request();
|
||||||
let info = req.connection_info();
|
let info = req.connection_info();
|
||||||
assert_eq!(info.realip_remote_addr(), Some("192.0.2.60:8080"));
|
assert_eq!(info.realip_remote_addr(), Some("192.0.2.60"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn forwarded_for_ipv6() {
|
fn forwarded_for_ipv6() {
|
||||||
|
let req = TestRequest::default()
|
||||||
|
.insert_header((header::FORWARDED, r#"for="[2001:db8:cafe::17]""#))
|
||||||
|
.to_http_request();
|
||||||
|
let info = req.connection_info();
|
||||||
|
assert_eq!(info.realip_remote_addr(), Some("2001:db8:cafe::17"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn forwarded_for_ipv6_with_port() {
|
||||||
let req = TestRequest::default()
|
let req = TestRequest::default()
|
||||||
.insert_header((header::FORWARDED, r#"for="[2001:db8:cafe::17]:4711""#))
|
.insert_header((header::FORWARDED, r#"for="[2001:db8:cafe::17]:4711""#))
|
||||||
.to_http_request();
|
.to_http_request();
|
||||||
let info = req.connection_info();
|
let info = req.connection_info();
|
||||||
assert_eq!(info.realip_remote_addr(), Some("[2001:db8:cafe::17]:4711"));
|
assert_eq!(info.realip_remote_addr(), Some("2001:db8:cafe::17"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue