Skip to content

Commit b8f8f74

Browse files
authored
impl(gax-internal): always sanitize the URLs (#5154)
1 parent 6c28e7c commit b8f8f74

4 files changed

Lines changed: 28 additions & 11 deletions

File tree

src/gax-internal/src/observability.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub mod attributes;
3030
mod errors;
3131

3232
#[cfg(all(google_cloud_unstable_tracing, feature = "_internal-http-client"))]
33-
mod http_tracing;
33+
pub(crate) mod http_tracing;
3434

3535
#[cfg(all(google_cloud_unstable_tracing, feature = "_internal-http-client"))]
3636
pub(crate) use http_tracing::{ResultExt as HttpResultExt, create_http_attempt_span};

src/gax-internal/src/observability/client_signals/recorder.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
// limitations under the License.
1414

1515
use crate::observability::attributes::{GCP_CLIENT_REPO_GOOGLEAPIS, RPC_SYSTEM_HTTP};
16+
#[cfg(feature = "_internal-http-client")]
17+
use crate::observability::http_tracing::sanitize_url;
1618
use crate::options::InstrumentationClientInfo;
1719
#[cfg(feature = "_internal-http-client")]
1820
use google_cloud_gax::error::Error;
@@ -161,7 +163,7 @@ impl RequestRecorder {
161163
rpc_system: Some(RPC_SYSTEM_HTTP),
162164
http_method: Some(request.method().clone()),
163165
http_status_code: None,
164-
url: Some(request.url().to_string()),
166+
url: Some(sanitize_url(request.url()).to_string()),
165167
};
166168
guard.transport_snapshot = Some(snapshot);
167169
}
@@ -365,12 +367,12 @@ impl ClientSnapshot {
365367
Some(self.attempt_count - 1)
366368
}
367369

368-
/// Returns the full URL used in the last request.
370+
/// Returns the sanitized (but otherwise full) URL used in the last request.
369371
///
370372
/// Note that this may not be populated for gRPC requests.
371373
///
372-
/// Use with the "rpc.method" attribute.
373-
pub fn url(&self) -> Option<&str> {
374+
/// Use with the "url.full" attribute.
375+
pub fn sanitized_url(&self) -> Option<&str> {
374376
self.transport_snapshot
375377
.as_ref()
376378
.and_then(|s| s.url.as_deref())
@@ -457,7 +459,7 @@ mod tests {
457459
assert_eq!(snap.rpc_method(), Some(TEST_METHOD_NAME), "{snap:?}");
458460
assert_eq!(snap.url_template(), Some(TEST_PATH_TEMPLATE), "{snap:?}");
459461
assert_eq!(snap.rpc_system(), Some("http"), "{snap:?}");
460-
assert_eq!(snap.url(), Some(url.as_str()), "{snap:?}");
462+
assert_eq!(snap.sanitized_url(), Some(url.as_str()), "{snap:?}");
461463

462464
assert_eq!(snap.attempt_count, 1, "{snap:?}");
463465
assert_eq!(snap.http_status_code(), Some(404), "{snap:?}");
@@ -484,7 +486,7 @@ mod tests {
484486
assert_eq!(snap.rpc_method(), Some(TEST_METHOD_NAME), "{snap:?}");
485487
assert_eq!(snap.url_template(), Some(TEST_PATH_TEMPLATE), "{snap:?}");
486488
assert_eq!(snap.rpc_system(), Some("http"), "{snap:?}");
487-
assert_eq!(snap.url(), Some(BAD_URL), "{snap:?}");
489+
assert_eq!(snap.sanitized_url(), Some(BAD_URL), "{snap:?}");
488490

489491
assert_eq!(snap.attempt_count, 1, "{snap:?}");
490492
assert!(snap.http_status_code().is_none(), "{snap:?}");
@@ -537,11 +539,26 @@ mod tests {
537539
assert!(snap.rpc_method().is_none(), "{snap:?}");
538540
assert_eq!(snap.url_template(), Some(STORAGE_PATH_TEMPLATE), "{snap:?}");
539541
assert_eq!(snap.rpc_system(), Some("http"), "{snap:?}");
540-
assert_eq!(snap.url(), Some(url.as_str()), "{snap:?}");
542+
assert_eq!(snap.sanitized_url(), Some(url.as_str()), "{snap:?}");
541543
assert_eq!(snap.attempt_count, 1, "{snap:?}");
542544
assert_eq!(snap.http_status_code(), Some(404), "{snap:?}");
543545
let addr = server.addr();
544546
assert_eq!(snap.server_address(), addr.ip().to_string(), "{snap:?}");
545547
assert_eq!(snap.server_port(), addr.port(), "{snap:?}");
546548
}
549+
550+
#[test]
551+
fn url_is_sanitized() -> anyhow::Result<()> {
552+
const RAW_URL: &str = "https://127.0.0.1:1/v42/unused?Signature=ABC&upload_id=123";
553+
const WANT_URL: &str =
554+
"https://127.0.0.1:1/v42/unused?Signature=REDACTED&upload_id=REDACTED";
555+
556+
let url = reqwest::Url::parse(RAW_URL)?;
557+
let request = reqwest::Request::new(reqwest::Method::GET, url);
558+
let recorder = RequestRecorder::new(TEST_INFO);
559+
recorder.on_http_request(&request);
560+
let snap = recorder.client_snapshot();
561+
assert_eq!(snap.sanitized_url(), Some(WANT_URL), "{snap:?}");
562+
Ok(())
563+
}
547564
}

src/gax-internal/src/observability/client_signals/with_client_logging.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ where
103103
{ GCP_CLIENT_ARTIFACT } = snapshot.client_artifact(),
104104
{ URL_DOMAIN } = snapshot.default_host(),
105105
// TODO(#5152) - sanitize the URL.
106-
{ URL_FULL } = snapshot.url(),
106+
{ URL_FULL } = snapshot.sanitized_url(),
107107
{ URL_TEMPLATE } = snapshot.url_template(),
108108
{ RPC_RESPONSE_STATUS_CODE } = rpc_status_code,
109109
{ ERROR_TYPE } = error_type.as_str(),

src/gax-internal/src/observability/http_tracing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub(crate) fn create_http_attempt_span(
4949
instrumentation: Option<&'static InstrumentationClientInfo>,
5050
prior_attempt_count: u32,
5151
) -> Span {
52-
let url = cleanup_url(request.url());
52+
let url = sanitize_url(request.url());
5353
let method = request.method();
5454

5555
let resource_name = options
@@ -223,7 +223,7 @@ pub fn record_intermediate_client_request(
223223
}
224224
}
225225

226-
fn cleanup_url(url: &::reqwest::Url) -> ::reqwest::Url {
226+
pub fn sanitize_url(url: &::reqwest::Url) -> ::reqwest::Url {
227227
if url.query().is_none() {
228228
return url.clone();
229229
}

0 commit comments

Comments
 (0)