|
| 1 | +#![expect( |
| 2 | + clippy::let_underscore_must_use, |
| 3 | + reason = "derivative's Debug derive with format_with expands to a must_use let binding" |
| 4 | +)] |
| 5 | + |
1 | 6 | use std::{fmt, str::FromStr}; |
2 | 7 |
|
| 8 | +use derivative::Derivative; |
3 | 9 | use http::uri::{Authority, PathAndQuery, Scheme, Uri}; |
4 | 10 | use percent_encoding::percent_decode_str; |
5 | 11 | use snafu::{ResultExt, Snafu}; |
@@ -239,9 +245,29 @@ pub enum HttpEndpointError { |
239 | 245 | /// still an absolute `http(s)` URL. |
240 | 246 | #[configurable_component] |
241 | 247 | #[configurable(title = "An absolute HTTP(S) URL.", description = "")] |
242 | | -#[derive(Debug, Clone, PartialEq, Eq)] |
| 248 | +#[derive(Derivative, Clone, PartialEq, Eq)] |
| 249 | +#[derivative(Debug)] |
243 | 250 | #[serde(try_from = "String", into = "String")] |
244 | | -pub struct HttpEndpoint(Uri); |
| 251 | +pub struct HttpEndpoint(#[derivative(Debug(format_with = "fmt_http_endpoint_uri"))] Uri); |
| 252 | + |
| 253 | +fn fmt_http_endpoint_uri(uri: &Uri, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 254 | + if let Some(scheme) = uri.scheme_str() { |
| 255 | + write!(f, "{scheme}://")?; |
| 256 | + } |
| 257 | + if let Some(authority) = uri.authority() { |
| 258 | + if authority.as_str().contains('@') { |
| 259 | + f.write_str("<redacted>@")?; |
| 260 | + } |
| 261 | + f.write_str(authority.host())?; |
| 262 | + if let Some(port) = authority.port() { |
| 263 | + write!(f, ":{}", port.as_str())?; |
| 264 | + } |
| 265 | + } |
| 266 | + if let Some(path_and_query) = uri.path_and_query() { |
| 267 | + f.write_str(path_and_query.as_str())?; |
| 268 | + } |
| 269 | + Ok(()) |
| 270 | +} |
245 | 271 |
|
246 | 272 | impl TryFrom<String> for HttpEndpoint { |
247 | 273 | type Error = HttpEndpointError; |
@@ -539,6 +565,16 @@ mod tests { |
539 | 565 | } |
540 | 566 | } |
541 | 567 |
|
| 568 | + #[test] |
| 569 | + fn http_endpoint_debug_redacts_userinfo() { |
| 570 | + let endpoint = |
| 571 | + HttpEndpoint::parse("http://user:secret@example.com:8080/path?query=1").unwrap(); |
| 572 | + assert_eq!( |
| 573 | + format!("{endpoint:?}"), |
| 574 | + "HttpEndpoint(http://<redacted>@example.com:8080/path?query=1)" |
| 575 | + ); |
| 576 | + } |
| 577 | + |
542 | 578 | #[test] |
543 | 579 | fn http_endpoint_defaults_missing_scheme_to_https() { |
544 | 580 | for endpoint in [ |
|
0 commit comments