1313// limitations under the License.
1414
1515use crate :: observability:: attributes:: { GCP_CLIENT_REPO_GOOGLEAPIS , RPC_SYSTEM_HTTP } ;
16+ #[ cfg( feature = "_internal-http-client" ) ]
17+ use crate :: observability:: http_tracing:: sanitize_url;
1618use crate :: options:: InstrumentationClientInfo ;
1719#[ cfg( feature = "_internal-http-client" ) ]
1820use 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}
0 commit comments