Add a policy-aware HTTP client builder (#34630)

## What changed

- Add `HttpClientBuilder` for configuring default headers, redirects, the
  Cloudflare cookie store, and request diagnostics without exposing the
  underlying transport.
- Provide factory-backed construction for fixed destinations that respects
  outbound proxy policy, alongside explicit direct and legacy
  transport-default construction paths.
- Preserve the request-logging setting in `ReqwestTransport`, so disabling
  diagnostics also suppresses transport-level URL and request-body traces.
- Add `HEAD`, `DELETE`, and query-parameter helpers to the shared client
  wrappers.

## Testing

- Verify builder configuration survives policy-aware construction and custom
  CA fallback.
- Verify disabled request logging omits request URLs and bodies from transport
  traces.

GitOrigin-RevId: 529c33abefeb88f38ff9a0ead374d29fcc872e6a
This commit is contained in:
Michael Bolin authored and copyberry committed 2026-07-21 22:40:12 +00:00
1 parent a26f219f67
commit adb143a291
8 files changed
+496 -53

No files matched your search

+23 -18
View File
@@ -1,5 +1,5 @@
use crate::default_client::HttpClient;
use crate::default_client::RequestBuilder;
use crate::client::HttpClient;
use crate::client::RequestBuilder;
use crate::error::TransportError;
use crate::request::Request;
use crate::request::RequestBody;
@@ -45,6 +45,10 @@ impl ReqwestTransport {
}
}
pub fn from_http_client(client: HttpClient) -> Self {
Self { client }
}
fn build(&self, req: Request) -> Result<RequestBuilder, TransportError> {
let prepared = req.prepare_body_for_send().map_err(TransportError::Build)?;
@@ -80,6 +84,17 @@ impl ReqwestTransport {
TransportError::Network(err.to_string())
}
}
fn trace_request(&self, req: &Request) {
if self.client.request_logging_enabled() && enabled!(Level::TRACE) {
trace!(
"{} to {}: {}",
req.method,
req.url,
request_body_for_trace(req)
);
}
}
}
fn request_body_for_trace(req: &Request) -> String {
@@ -95,14 +110,7 @@ fn request_body_for_trace(req: &Request) -> String {
impl HttpTransport for ReqwestTransport {
async fn execute(&self, req: Request) -> Result<Response, TransportError> {
if enabled!(Level::TRACE) {
trace!(
"{} to {}: {}",
req.method,
req.url,
request_body_for_trace(&req)
);
}
self.trace_request(&req);
let url = req.url.clone();
let builder = self.build(req)?;
@@ -127,14 +135,7 @@ impl HttpTransport for ReqwestTransport {
}
async fn stream(&self, req: Request) -> Result<StreamResponse, TransportError> {
if enabled!(Level::TRACE) {
trace!(
"{} to {}: {}",
req.method,
req.url,
request_body_for_trace(&req)
);
}
self.trace_request(&req);
let url = req.url.clone();
let builder = self.build(req)?;
@@ -160,3 +161,7 @@ impl HttpTransport for ReqwestTransport {
})
}
}
#[cfg(test)]
#[path = "transport_tests.rs"]
mod tests;