Skip to content

perf: allow sharing an SSL context across clients - #547

Open
lilyydu wants to merge 4 commits into
mainfrom
lilyydu/client-improvement
Open

perf: allow sharing an SSL context across clients#547
lilyydu wants to merge 4 commits into
mainfrom
lilyydu/client-improvement

Conversation

@lilyydu

@lilyydu lilyydu commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Issue

Every httpx.AsyncClient builds its own ssl.SSLContext, which parses the full CA bundle (~150 certs) from disk at roughly 2.4ms (on Mac). Client did this unconditionally and ClientOptions had no way to opt out, so callers that construct many clients paid it repeatedly.

Implementation

Added ClientOptions.ssl_context, an optional pre-built ssl.SSLContext that is passed through to httpx and propagated by clone(). Callers build one context per process and reuse it everywhere.

An SSLContext is passed rather than a transport deliberately: httpx reuses the context as-is while keeping per-client connection pools and env-based proxy detection, both of which a custom transport would silently disable.

Default behaviour is unchanged. ssl_context defaults to None, which maps to httpx's own True.

Note that a cached context is a snapshot of the CA bundle at the time it is built; long-lived processes should rebuild it periodically to pick up CA rotation. This is why it is opt-in rather than the default.

Every httpx.AsyncClient builds its own ssl.SSLContext, which parses the
full CA bundle (~150 certs) from disk at roughly 2.4ms. Client did this
unconditionally and ClientOptions had no way to opt out, so callers that
construct many clients paid it repeatedly.

Add ClientOptions.verify, an optional pre-built ssl.SSLContext that is
passed through to httpx and propagated by clone(). Callers build one
context per process and reuse it everywhere.

An SSLContext is passed rather than a transport deliberately: httpx
reuses the context as-is while keeping per-client connection pools and
env-based proxy detection, both of which a custom transport would
silently disable.

Default behaviour is unchanged. verify defaults to None, which maps to
httpx's own True. The field is typed Optional[ssl.SSLContext] and does
not accept bool, so TLS verification cannot be disabled through it.

Note that a cached context is a snapshot of the CA bundle at the time it
is built; long-lived processes should rebuild it periodically to pick up
CA rotation. This is why it is opt-in rather than the default.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@lilyydu
lilyydu marked this pull request as ready for review August 4, 2026 22:05
Copilot AI lite review requested due to automatic review settings August 4, 2026 22:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an opt-in way to reuse a single TLS ssl.SSLContext across many httpx.AsyncClient instances created by the SDK’s Client, reducing repeated CA-bundle parsing overhead for workloads that instantiate many clients.

Changes:

  • Added ClientOptions.verify: Optional[ssl.SSLContext] and threaded it through Client construction and clone().
  • Updated Client initialization to pass the provided SSL context through to httpx.
  • Added tests asserting the provided SSL context is used, shared across clients, and preserved/overridden across clones.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/common/src/microsoft_teams/common/http/client.py Adds ClientOptions.verify and wires it into httpx.AsyncClient construction and clone() option merging.
packages/common/tests/test_client.py Adds tests that introspect the underlying httpx transport to verify SSL context reuse and cloning behavior.

Comment thread packages/common/src/microsoft_teams/common/http/client.py
Comment thread packages/common/tests/test_client.py Outdated
lilyydu and others added 3 commits August 4, 2026 15:13
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Naming the field `verify` mirrored httpx, which also accepts bool and str
there. That made `verify=False` -- the most common Python TLS workaround --
look like valid input, and it would have silently disabled certificate
verification.

Renaming to `ssl_context` removes the ambiguity rather than guarding
against it: the field only ever meant "a pre-built ssl.SSLContext", and
`ssl_context=False` is now rejected by the dataclass itself with no
runtime type check required.

Drops test_verify_rejects_bool, which covered the guard this replaces.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants