Repository: seanmonstar/reqwest (language: rust)

Issue:
Remove debug log of status and URL
Hi,

I have a situation where the API takes the UID/PW as URL parameters (yes, I know, it's not ideal, but it is a constraint)...
```
20220430 22:52:29.027859000 UTC|DEBUG|P: 25072|T: 22936|hyper::proto::h1::conn| incoming body completed
20220430 22:52:29.027955900 UTC|DEBUG|P: 25072|T: 32456|reqwest::async_impl::client| response '200 OK' for http://127.0.0.1/api/table.json?columns=objid,name,status,active&username=MyUser&password=mypassword
20220430 22:52:29.028124600 UTC|DEBUG|P: 25072|T: 32456|moah_client::client| handle_recoverable_failures(): headers[("connection", "\"close\""), ("content-type", "\"application/json; charset=UTF-8\""), ("content-length", "\"2096\""), ("date", "\"Sat, 30 Apr 2022 22:52:28 GMT\""), ("expires", "\"0\""), ("cache-control", "\"cache, must-revalidate\""), ("x-content-type-options", "\"nosniff\""), ("x-xss-protection", "\"1; mode=block\""), ("pragma", "\"public\""), ("server", "\"HUMBUG\"")]
```
Is there a way to sanitize the URL parameters the same way it is done for headers...
I have a routine that does it for my debug, but it still shows in the reqwest debug
```
20220430 22:52:28.893586000 UTC|DEBUG|P: 25072|T: 32456|moah_client::client| RQ: GET URL[(Url { scheme: "http", cannot_be_a_base: false, username: "", password: None, host: Some(Ipv4(127.0.0.1)), port: None, path: "/api/table.json", query: Some("... Active&filter_parentid=0&username=MyUser&password=**REDACTED**"), fragment: None }, true)]
	headers[("user-agent", "\"test.API\""), ("accept", "\"application/json\"")]
	body[None]
```
Is there a hook where do the sanitation ?
  Thanks
    JR


Discussion / hints:
There's no hook. But I think we can safely just remove that log. I don't think it provides much value, a user can see the same information by inspecting the response status and URL.
@seanmonstar ,
Thanks for getting back to me...

Seems a bit drastic, but I see your point..
I could provide my routine, but it's a bit "heavy handed""..

```rust

use lazy_static::lazy_static;

lazy_static!{
    pub static ref REDACTRED_SET       : HashSet<&'static str> = vec![
        "PASSWORD", "SECRET", "TOKEN", "PASSWD", "PASSHASH", "DIGEST",
        "AUTHORIZATION","X-AUTH-TOKEN","SSN","BEARER", "COOKIE"
    ].iter().cloned().collect();
// 
    pub static ref REDACTRED_PARTIALS   : Vec<&'static str>     = vec![
        "PASSWO", "SECRET", "AUTH", "TOKEN", "PASSWD", "KEY", "PASSHA", "SSN","BEARER", "DIGEST","COOKIE"
    ];
}

#[cfg(target_os = "windows")]
lazy_static!{
    pub static ref PATH_VARIABLENAMES_PARTIALS   : Vec<&'static str>     = vec![
    "COMMONFI", "COMMONPR", "PATH", "PROGRAMFILES", "PROGRAMDATA","HOME","WINDIR",
    "COMSPEC","APPDATA"
];
}
#[cfg(not(target_os = "windows"))]
lazy_static!{
    pub static ref PATH_VARIABLENAMES_PARTIALS   : Vec<&'static str>     = vec![
    "COMMONF", "PATH", "PROGRAMF","HOME"
];
}

pub static REDACTED_SUBST_VAR: &'static str = r#"[*REDACTED*]"#;
pub static REDACTED_SUBST_URLVAR: &'static str = r#"**REDACTED**"#;

// Return if a variable should be redaced
pub fn is_redactable_variable(var: &str, additional: Option<&Vec<&str>>) -> bool {
    let tmpvar = var.to_uppercase();
    if REDACTRED_SET.contains(tmpvar.as_str()) ||
       REDACTRED_PARTIALS.iter().any(|&curr| tmpvar.contains(curr))
    {
        true
    } else {
        if let Some(extra) = additional {
            extra.iter().any(|&curr| tmpvar.contains(curr))     
        } else {
            false
        }
    }
}

pub fn sanitize_variable_json(var: &str, value: String) -> SerdeJValue {
    if is_redactable_variable(var, None) {
        json!(REDACTED_SUBST_VAR)
    } else {
        json!(value)
    }
}

/// Sanitize a url(query params) redacting secure items.. (Password/passhash, etc)
/// Returns (sanitized URL, Modified(bool))
pub fn sanitize_url_query(url: StdUrl, extra_redactables: Option<&Vec<&str>>) -> (StdUrl, bool) {
    // standard
    let mut url = url;
    let mut have_redacted = false;
    let mut sanitized: Vec<(String, String)> = Vec::new();
    {
        let query_pairs = url.query_pairs();
        for (cur_key, cur_val) in query_pairs {
            if super::sanitize::is_redactable_variable(cur_key.as_ref(), extra_redactables) {
                have_redacted = true;
                sanitized.push((cur_key.to_string(), super::sanitize::REDACTED_SUBST_URLVAR.to_owned()));
            } else {
                sanitized.push((cur_key.to_string(), cur_val.to_string()));
            }
        }
        if have_redacted {
            url.set_query(None);
        }    
    }
    if have_redacted {
        url.query_pairs_mut()
            .extend_pairs(sanitized.into_iter());
        (url, have_redacted)
    } else {
        (url, have_redacted)
    }
}

pub fn sanitize_headermap(hewader_map: &HttpHeaderMap, extra_redactables: Option<&Vec<&str>>) -> Vec<(String, String)> {
    // standard
    let mut retval: Vec<(String, String)> = Vec::new();
    {
        for (cur_key, cur_val) in hewader_map {
            if super::sanitize::is_redactable_variable(cur_key.as_ref(), extra_redactables) {
                retval.push((cur_key.to_string(), super::sanitize::REDACTED_SUBST_VAR.to_owned()));
            } else {
                let val = format!("{:?}", cur_val);
                retval.push((cur_key.to_string(), val));
            }
        }
    }
    retval
}

...
debug!("RQ: {} URL[{:?}]\n\theaders{:?}\n\tbody[{:?}]", 
            request.method().to_string(), 
            url_utils::sanitize_url_query(request.url().clone(), None), 
            url_utils::sanitize_headermap(request.headers(), None),
            request.body());
    }
```
Thanks
  JR

Fix patch:
diff --git a/src/async_impl/client.rs b/src/async_impl/client.rs
index b6e693738..4517328c9 100644
--- a/src/async_impl/client.rs
+++ b/src/async_impl/client.rs
@@ -2014,7 +2014,6 @@ impl Future for PendingRequest {
                 }
             }
 
-            debug!("response '{}' for {}", res.status(), self.url);
             let res = Response::new(
                 res,
                 self.url.clone(),


Test patch: