Skip to content

Assigning client.proxy resets verify, CA bundle, mTLS identity, redirects, https_only and timeout #84

Description

@thomasht86

Summary

Assigning client.proxy = "..." after construction throws away the entire client configuration and rebuilds a default reqwest client. TLS verification settings, custom CA bundles, the mTLS identity, redirect policy, https_only and timeout are all silently reset.

Cause

src/lib.rs:343set_proxy builds a brand-new client from a bare builder:

let new_client = reqwest::Client::builder()
    .proxy(rproxy)
    .build()
    .map_err(map_reqwest_error)?;

None of the settings applied in new() are carried over, because RClient never retains them.

Reproduction

Verified against a local forward proxy plus a trustme-issued HTTPS server:

setting at construction behaviour after client.proxy = <working proxy>
verify=False lostConnectError on the self-signed cert (worked before)
ca_cert_file=<trusted CA> lostConnectError, custom root gone
follow_redirects=False lost302 became 200
https_only=True lost — plain-HTTP request now returns 200 instead of erroring
timeout=1 lost — returned 200 against a 3s sleep instead of timing out
client_pem / client_pem_data (mTLS) lost by the same code path
client headers, referer preserved (re-applied per request from self.headers)

Impact

This is a silent change in security posture: a client configured with a custom CA bundle or an mTLS identity quietly stops presenting/validating them. mTLS is one of the project's headline features. https_only=True being dropped is the most dangerous of the set, since traffic that was restricted to HTTPS can then go out in plaintext — over a proxy.

Proposed fix

Retain the configuration so it can be reapplied:

  1. Extract the body of new() (src/lib.rs:120-247) into a fn build_client(cfg: &ClientConfig) -> PyResult<reqwest::Client>, where ClientConfig holds the constructor arguments.
  2. Store the ClientConfig on RClient.
  3. Have set_proxy update cfg.proxy and rebuild via build_client(&cfg).

This also removes the current duplication between new() and set_proxy.

Worth noting in the docs that reassigning .proxy rebuilds the client and drops the existing connection pool — it's an expensive operation either way.

Suggested tests

One test per row of the table above: assert the behaviour is unchanged across a .proxy assignment. The verify=False and https_only=True cases are the important ones.

Size

~2 hours — mostly the mechanical ClientConfig extraction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrustPull requests that update rust code

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions