diff --git a/Cargo.lock b/Cargo.lock index 0d9bbfb..f8da595 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,7 +99,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -128,15 +128,15 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "boring-sys2" -version = "4.13.6" +version = "4.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab6af1d75bd1d48b07da142dd1fc90ac24925af8258fcd13636882e6f3d013c" +checksum = "098769dec83815b4c12f4847da584198c7a94207780fd02870441c837d312a4b" dependencies = [ "autocfg", "bindgen", @@ -147,9 +147,9 @@ dependencies = [ [[package]] name = "boring2" -version = "4.13.6" +version = "4.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0630177503a89deb297b07d993b3edbeafb7569f8edf8108dffe77d39c466d01" +checksum = "d94931c04c0540757a9a5f516081154935c1dff6d91355129b9b5308f7e4bb8a" dependencies = [ "bitflags", "boring-sys2", @@ -194,9 +194,9 @@ checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.2.7" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "jobserver", "libc", @@ -510,7 +510,7 @@ dependencies = [ "markup5ever", "nom", "tendril", - "thiserror 2.0.9", + "thiserror 2.0.11", "unicode-width", ] @@ -787,7 +787,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -829,9 +829,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "lru" @@ -898,9 +898,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", ] @@ -984,7 +984,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1105,7 +1105,6 @@ dependencies = [ "foldhash", "html2text", "indexmap", - "log", "pyo3", "pyo3-log", "pythonize", @@ -1113,14 +1112,15 @@ dependencies = [ "serde_json", "tokio", "tokio-util", + "tracing", "webpki-root-certs", ] [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -1143,9 +1143,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.23.3" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e484fd2c8b4cb67ab05a318f1fd6fa8f199fcc30819f08f07d200809dba26c15" +checksum = "57fe09249128b3173d092de9523eaa75136bf7ba85e0d69eca241c7939c933cc" dependencies = [ "anyhow", "cfg-if", @@ -1163,9 +1163,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.23.3" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e0469a84f208e20044b98965e1561028180219e35352a2afaf2b942beff3b" +checksum = "1cd3927b5a78757a0d71aa9dff669f903b1eb64b54142a9bd9f757f8fde65fd7" dependencies = [ "once_cell", "target-lexicon", @@ -1173,9 +1173,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.23.3" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1547a7f9966f6f1a0f0227564a9945fe36b90da5a93b3933fc3dc03fae372d" +checksum = "dab6bb2102bd8f991e7749f130a70d05dd557613e39ed2deeee8e9ca0c4d548d" dependencies = [ "libc", "pyo3-build-config", @@ -1194,9 +1194,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.23.3" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb6da8ec6fa5cedd1626c886fc8749bdcbb09424a86461eb8cdf096b7c33257" +checksum = "91871864b353fd5ffcb3f91f2f703a22a9797c91b9ab497b1acac7b07ae509c7" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -1206,9 +1206,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.23.3" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38a385202ff5a92791168b1136afae5059d3ac118457bb7bc304c197c2d33e7d" +checksum = "43abc3b80bc20f3facd86cd3c60beed58c3e2aa26213f3cda368de39c60a27e4" dependencies = [ "heck", "proc-macro2", @@ -1325,9 +1325,9 @@ dependencies = [ [[package]] name = "rquest" -version = "1.3.5" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4851800c1f7cccbaa7e8386e85f2a9514c2998f1b1298671a8dba247380998ee" +checksum = "551d4dfc07ad61d2e67ef9e2ca9b215e8a7ac583b58dfe9f533c28f1b0181ad4" dependencies = [ "antidote", "async-compression", @@ -1347,6 +1347,7 @@ dependencies = [ "http-body-util", "hyper2", "ipnet", + "libc", "linked_hash_set", "log", "lru", @@ -1365,7 +1366,6 @@ dependencies = [ "tokio-socks", "tokio-util", "tower", - "tower-layer", "tower-service", "typed-builder", "url", @@ -1534,9 +1534,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.95" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -1612,11 +1612,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.9" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ - "thiserror-impl 2.0.9", + "thiserror-impl 2.0.11", ] [[package]] @@ -1632,9 +1632,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.9" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", @@ -1684,9 +1684,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.42.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -1702,9 +1702,9 @@ dependencies = [ [[package]] name = "tokio-boring2" -version = "4.13.6" +version = "4.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b719539ae2fd57495b38d0ae4e3b32fb03f5d853a47574d4579e537d66ab2a97" +checksum = "8e0216304b351c0d3eab0f42f296e2327209cea57930c8957f50d2bafd826077" dependencies = [ "boring-sys2", "boring2", @@ -1714,9 +1714,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", @@ -1781,10 +1781,23 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.33" @@ -1927,31 +1940,31 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-registry" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bafa604f2104cf5ae2cc2db1dee84b7e6a5d11b05f737b60def0ffdc398cbc0a" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" dependencies = [ "windows-result", "windows-strings", - "windows-targets", + "windows-targets 0.53.0", ] [[package]] name = "windows-result" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +checksum = "d08106ce80268c4067c0571ca55a9b4e9516518eaa1a1fe9b37ca403ae1d1a34" dependencies = [ - "windows-targets", + "windows-targets 0.53.0", ] [[package]] name = "windows-strings" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978d65aedf914c664c510d9de43c8fd85ca745eaff1ed53edf409b479e441663" +checksum = "b888f919960b42ea4e11c2f408fadb55f78a9f236d5eef084103c8ce52893491" dependencies = [ - "windows-targets", + "windows-targets 0.53.0", ] [[package]] @@ -1960,7 +1973,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1969,14 +1982,30 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -1985,48 +2014,96 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "write16" version = "1.0.0" diff --git a/Cargo.toml b/Cargo.toml index e2c524b..d4134f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,11 +12,11 @@ name = "primp" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.23.3", features = ["extension-module", "abi3-py38", "indexmap", "anyhow"] } +pyo3 = { version = "0.23.4", features = ["extension-module", "abi3-py38", "indexmap", "anyhow"] } anyhow = "1.0.95" -log = "0.4.22" +tracing = { version = "0.1.41", features = ["log-always"] } pyo3-log = "0.12.1" -rquest = { version = "1.3.5", features = [ +rquest = { version = "1.5.5", features = [ "json", "cookies", "socks", @@ -27,12 +27,11 @@ rquest = { version = "1.3.5", features = [ "multipart", "stream", "impersonate_str", - "impersonate_settings", ] } encoding_rs = { version = "0.8.35" } foldhash = "0.1.4" indexmap = { version = "2.7.0", features = ["serde"] } -tokio = { version = "1.42.0", features = ["full"] } +tokio = { version = "1.43.0", features = ["full"] } tokio-util = { version = "0.7.13", features = ["codec"] } # for multipart html2text = "0.13.6" bytes = "1.9.0" diff --git a/src/lib.rs b/src/lib.rs index 65add9a..55a3eed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,7 @@ use tokio::{ runtime::{self, Runtime}, }; use tokio_util::codec::{BytesCodec, FramedRead}; +use tracing; mod response; use response::Response; @@ -178,6 +179,9 @@ impl Client { // Redirects if follow_redirects.unwrap_or(true) { client_builder = client_builder.redirect(Policy::limited(max_redirects.unwrap_or(20))); + if proxy.is_some() { + client_builder = client_builder.redirect_with_proxy_auth(true); + } } else { client_builder = client_builder.redirect(Policy::none()); } @@ -402,7 +406,7 @@ impl Client { let url = resp.url().to_string(); let buf = resp.bytes().await?; - log::info!("response: {} {} {}", url, status_code, buf.len()); + tracing::info!("response: {} {} {}", url, status_code, buf.len()); Ok((buf, cookies, headers, status_code, url)) }; diff --git a/src/traits.rs b/src/traits.rs index aeaf48f..c14002f 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -17,17 +17,18 @@ impl HeadersTraits for IndexMapSSR { self.clone() } fn to_headermap(&self) -> HeaderMap { - self.iter() - .map(|(k, v)| { - ( - HeaderName::from_bytes(k.as_bytes()) - .unwrap_or_else(|k| panic!("Invalid header name: {k:?}")), - HeaderValue::from_bytes(v.as_bytes()) - .unwrap_or_else(|v| panic!("Invalid header value: {v:?}")), - ) - }) - .collect() + let mut header_map = HeaderMap::with_capacity(self.len()); + for (k, v) in self { + header_map.insert( + HeaderName::from_bytes(k.as_bytes()) + .unwrap_or_else(|k| panic!("Invalid header name: {k:?}")), + HeaderValue::from_bytes(v.as_bytes()) + .unwrap_or_else(|v| panic!("Invalid header value: {v:?}")), + ); + } + header_map } + fn insert_key_value(&mut self, key: String, value: String) -> Result<(), Error> { self.insert(key.to_string(), value.to_string()); Ok(()) @@ -36,16 +37,18 @@ impl HeadersTraits for IndexMapSSR { impl HeadersTraits for HeaderMap { fn to_indexmap(&self) -> IndexMapSSR { - self.iter() - .map(|(k, v)| { - ( - k.to_string(), - v.to_str() - .unwrap_or_else(|v| panic!("Invalid header value: {v:?}")) - .to_string(), - ) - }) - .collect() + let mut index_map = + IndexMapSSR::with_capacity_and_hasher(self.len(), RandomState::default()); + for (key, value) in self { + index_map.insert( + key.as_str().to_string(), + value + .to_str() + .unwrap_or_else(|v| panic!("Invalid header value: {v:?}")) + .to_string(), + ); + } + index_map } fn to_headermap(&self) -> HeaderMap { @@ -68,9 +71,15 @@ pub trait CookiesTraits { impl CookiesTraits for IndexMapSSR { fn to_string(&self) -> String { - self.iter() - .map(|(k, v)| format!("{}={}", k, v)) - .collect::>() - .join("; ") + let mut result = String::with_capacity(self.len() * 40); + for (k, v) in self { + if !result.is_empty() { + result.push_str("; "); + } + result.push_str(k); + result.push('='); + result.push_str(v); + } + result } } diff --git a/src/utils.rs b/src/utils.rs index 91a4f85..20ac56d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,6 +10,7 @@ use rquest::boring::{ X509, }, }; +use tracing; /// Loads the CA certificates from venv var PRIMP_CA_BUNDLE or the WebPKI certificate store pub fn load_ca_certs() -> Option<&'static X509Store> { @@ -36,11 +37,11 @@ pub fn load_ca_certs() -> Option<&'static X509Store> { match CERT_STORE.as_ref() { Ok(cert_store) => { - log::debug!("Loaded CA certs"); + tracing::debug!("Loaded CA certs"); Some(cert_store) } Err(err) => { - log::error!("Failed to load CA certs: {:?}", err); + tracing::error!("Failed to load CA certs: {:?}", err); None } }