Skip to content

feat: Support custom reqwest clients - #263

Merged
marandaneto merged 4 commits into
mainfrom
feat/custom-http-clients
Sep 24, 2026
Merged

marandaneto merged 4 commits into
mainfrom
feat/custom-http-clients

Conversation

@marandaneto

@marandaneto marandaneto commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

💡 Motivation and Context

Closes #262. Related to #256 and #257.

Public API change: add ClientOptionsBuilder::http_client(reqwest::Client) and blocking_http_client(reqwest::blocking::Client). The API shape was approved on #262.

Applications can now share their HTTP connection pools, proxies, TLS settings, and timeouts with the SDK. The async client handles immediate capture, remote flags, and local-evaluation polling. The blocking client handles blocking requests and background capture in both SDK modes. Omitting either option preserves SDK-created clients for that path.

SDK timeout options also apply to supplied clients. request_timeout_seconds bounds immediate capture, background capture, and initial and periodic local-evaluation requests. feature_flags_request_timeout_seconds bounds remote flags. These options replace the supplied request timeout even if it is shorter. Background shutdown draining additionally caps requests at the remaining shutdown deadline. shutdown_timeout_ms is not a hard limit on the total wait for work already underway; this limitation is documented above the custom-client setters. No shutdown lifecycle behavior is changed.

The SDK releases its blocking-client handles outside the async runtime, including disabled initialization and cancellation. Construction also works outside Tokio when local evaluation is disabled. Background initialization task failures are logged. Documentation warns against supplying clients with default headers or cookies containing credentials for unrelated services.

This is separate from the TLS-provider selection added to v1 in #245. This PR targets main and does not add that feature or disable background transport.

Includes a usage example, documentation, public API snapshot, and minor changeset.

💚 How did you test it?

  • cargo test --workspace
  • cargo test --no-default-features
  • cargo test --features capture-v1
  • cargo test --no-default-features --features capture-v1,error-tracking
  • Custom-client tests cover routing, partial injection, timeout precedence, retained application handles, shutdown, disabled initialization, cancellation, and construction outside Tokio. The non-Tokio panic and missing async/blocking deadlines for flags, capture, and local evaluation were reproduced with failing tests before the fixes. Retained regression tests cover each request surface, including periodic polling.
  • cargo fmt --all -- --check
  • cargo clippy -- -D warnings
  • cargo check --examples
  • cargo check --example custom_http_clients --no-default-features
  • scripts/check-public-api.sh
  • Autoreview of 0f81997 against origin/main reported no actionable findings.

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed.
  • No breaking change or entry added to the changelog.

If releasing new changes

  • Ran sampo add to generate a changeset file

@greptile-apps

greptile-apps Bot commented Sep 23, 2026

Copy link
Copy Markdown

Retrigger

The PR appears safe to merge with no actionable correctness, security, compatibility, or repository-rule issues identified.

Reviews (1) · Last reviewed commit: "feat: Support custom reqwest clients"

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

posthog-rs-v0 Compliance Report

Date: 2026-09-24 08:35:21 UTC
Duration: 15384ms

✅ All Tests Passed!

46/46 tests passed


Capture Tests

✅ 29/29 tests passed

View Details
Test Status Duration
Format Validation.Event Has Required Fields ✅ 102ms
Format Validation.Event Has Uuid ✅ 113ms
Format Validation.Event Has Lib Properties ✅ 112ms
Format Validation.Distinct Id Is String ✅ 115ms
Format Validation.Token Is Present ✅ 114ms
Format Validation.Custom Properties Preserved ✅ 104ms
Format Validation.Event Has Timestamp ✅ 112ms
Retry Behavior.Retries On 503 ✅ 5114ms
Retry Behavior.Does Not Retry On 400 ✅ 2112ms
Retry Behavior.Does Not Retry On 401 ✅ 2107ms
Retry Behavior.Respects Retry After Header ✅ 5067ms
Retry Behavior.Implements Backoff ✅ 15077ms
Retry Behavior.Retries On 500 ✅ 5069ms
Retry Behavior.Retries On 502 ✅ 5072ms
Retry Behavior.Retries On 504 ✅ 5067ms
Retry Behavior.Max Retries Respected ✅ 15067ms
Deduplication.Generates Unique Uuids ✅ 72ms
Deduplication.Preserves Uuid On Retry ✅ 5019ms
Deduplication.Preserves Uuid And Timestamp On Retry ✅ 10025ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 5028ms
Deduplication.No Duplicate Events In Batch ✅ 20ms
Deduplication.Different Events Have Different Uuids ✅ 18ms
Compression.Sends Gzip When Enabled ✅ 18ms
Batch Format.Uses Proper Batch Structure ✅ 25ms
Batch Format.Flush With No Events Sends Nothing ✅ 27ms
Batch Format.Multiple Events Batched Together ✅ 96ms
Error Handling.Does Not Retry On 403 ✅ 2069ms
Error Handling.Does Not Retry On 413 ✅ 2053ms
Error Handling.Retries On 408 ✅ 5064ms

Feature_Flags Tests

✅ 17/17 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 52ms
Request Payload.Flags Request Uses V2 Query Param ✅ 48ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 26ms
Request Payload.Flags Request Omits Authorization Header ✅ 24ms
Request Payload.Token In Flags Body Matches Init ✅ 34ms
Request Payload.Groups Round Trip ✅ 33ms
Request Payload.Groups Default To Empty Object ✅ 34ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 35ms
Request Payload.Disable Geoip Omitted Defaults To False ✅ 21ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 32ms
Request Lifecycle.No Flags Request On Init Alone ✅ 21ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 40ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 40ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 28ms
Retry Behavior.Retries Flags On 502 ✅ 233ms
Retry Behavior.Retries Flags On 504 ✅ 231ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 34ms

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

posthog-rs-v1 Compliance Report

Date: 2026-09-24 08:36:18 UTC
Duration: 23007ms

✅ All Tests Passed!

111/111 tests passed


Capture_V1 Tests

✅ 94/94 tests passed

View Details
Test Status Duration
Endpoint And Method.Targets V1 Endpoint ✅ 149ms
Endpoint And Method.Does Not Use Legacy Endpoints ✅ 150ms
Required Headers.Has Authorization Bearer Header ✅ 149ms
Required Headers.Has Content Type Json ✅ 148ms
Required Headers.Has Posthog Sdk Info Format ✅ 147ms
Required Headers.Has Posthog Attempt Header ✅ 148ms
Required Headers.Has Posthog Request Id ✅ 146ms
Required Headers.Has Posthog Request Timestamp ✅ 146ms
Required Headers.Has User Agent ✅ 147ms
Body Format.Body Has Created At And Batch ✅ 145ms
Body Format.No Api Key In Body ✅ 144ms
Body Format.No Sent At In Body ✅ 145ms
Event Format.Event Has Required Root Fields ✅ 146ms
Event Format.Event Uuid Is Valid ✅ 145ms
Event Format.Event Timestamp Is Rfc3339 ✅ 146ms
Event Format.Distinct Id Is String ✅ 145ms
Event Format.Distinct Id At Root Not Properties ✅ 146ms
Event Format.Custom Properties Preserved ✅ 150ms
Event Format.Set Properties Preserved ✅ 144ms
Event Format.Set Once Properties Preserved ✅ 143ms
Event Format.Groups Properties Preserved ✅ 138ms
Event Format.Sdk Generates Uuid If Not Provided ✅ 134ms
Event Format.Event Has Required Root Fields Batch ✅ 170ms
Event Format.Event Uuid Is Valid Batch ✅ 170ms
Event Format.Event Timestamp Is Rfc3339 Batch ✅ 181ms
Event Format.Distinct Id Is String Batch ✅ 170ms
Event Format.Distinct Id At Root Not Properties Batch ✅ 181ms
Event Format.Custom Properties Preserved Batch ✅ 182ms
Event Format.Set Properties Preserved Batch ✅ 181ms
Event Format.Set Once Properties Preserved Batch ✅ 177ms
Event Format.Groups Properties Preserved Batch ✅ 137ms
Event Format.Sdk Generates Uuid If Not Provided Batch ✅ 134ms
Batch Behavior.Multiple Events In Single Batch ✅ 187ms
Batch Behavior.Batch Envelope Smoke ✅ 167ms
Batch Behavior.Flush With No Events Sends Nothing ✅ 50ms
Batch Behavior.Flush At Triggers Batch ✅ 1119ms
Batch Behavior.Created At Reflects Batch Creation Time ✅ 111ms
Deduplication.Generates Unique Uuids ✅ 200ms
Deduplication.Different Events Same Content Different Uuids ✅ 151ms
Deduplication.Preserves Uuid On Retry ✅ 5117ms
Deduplication.Preserves Timestamp On Retry ✅ 5115ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 5090ms
Deduplication.No Duplicate Events In Batch ✅ 156ms
Header Behavior On Retry.Attempt Header Starts At One ✅ 85ms
Header Behavior On Retry.Attempt Header Increments On Retry ✅ 10068ms
Header Behavior On Retry.Request Id Preserved On Retry ✅ 5065ms
Header Behavior On Retry.Different Requests Have Different Request Ids ✅ 2079ms
Header Behavior On Retry.Request Timestamp Changes On Retry ✅ 5054ms
Response Format Validation.Success Response Has Uuid Keyed Results ✅ 59ms
Response Format Validation.Success Response Has Ok For Each Event ✅ 40ms
Response Format Validation.Success No Retry After When All Ok ✅ 32ms
Response Format Validation.Success Retry After Present When Retry Events ✅ 32ms
Response Format Validation.Success No Retry After When Drop Only ✅ 34ms
Response Format Validation.Response Echoes Request Id ✅ 26ms
Retry Behavior.Retries On 408 ✅ 5028ms
Retry Behavior.Retries On 500 ✅ 5028ms
Retry Behavior.Retries On 503 ✅ 5025ms
Retry Behavior.Retries On 504 ✅ 5023ms
Retry Behavior.Retryable Errors Have Retry After ✅ 2026ms
Retry Behavior.Respects Retry After On Retryable Error ✅ 8025ms
Retry Behavior.Does Not Retry On 400 ✅ 2027ms
Retry Behavior.Does Not Retry On 401 ✅ 2027ms
Retry Behavior.Does Not Retry On 402 ✅ 2026ms
Retry Behavior.Does Not Retry On 413 ✅ 2028ms
Retry Behavior.Does Not Retry On 415 ✅ 2026ms
Retry Behavior.Non Retryable Errors Have No Retry After ✅ 2026ms
Retry Behavior.Implements Backoff ✅ 15032ms
Retry Behavior.Max Retries Respected ✅ 15024ms
Partial Batch Handling.Handles 200 Full Success ✅ 2024ms
Partial Batch Handling.Handles 200 With All Ok ✅ 3037ms
Partial Batch Handling.Does Not Retry Dropped Events ✅ 3038ms
Partial Batch Handling.Does Not Retry Limited Events ✅ 3029ms
Partial Batch Handling.Prunes Ok Events On Partial Retry ✅ 5029ms
Partial Batch Handling.Prunes Dropped Events On Partial Retry ✅ 5026ms
Partial Batch Handling.Retries Only Retry Events From Partial ✅ 5027ms
Partial Batch Handling.Partial Retry Preserves Uuids ✅ 5026ms
Partial Batch Handling.Partial Retry Attempt Header Increments ✅ 5031ms
Partial Batch Handling.Partial Retry Request Id Preserved ✅ 5036ms
Partial Batch Handling.Respects Retry After On Partial ✅ 5026ms
Partial Batch Handling.Unknown Result Treated As Terminal ✅ 3024ms
Partial Batch Handling.Mixed Ok Drop Limited No Retry ✅ 3028ms
Compression.Sends Gzip Content Encoding ✅ 24ms
Compression.No Content Encoding When Disabled ✅ 23ms
Compression.Compressed Body Is Decompressible ✅ 24ms
Error Handling.Does Not Retry On Unknown 4Xx ✅ 2024ms
Event Options.Cookieless Mode Override ✅ 24ms
Event Options.Disable Skew Correction Override ✅ 23ms
Event Options.Process Person Profile Override ✅ 23ms
Event Options.Product Tour Id Override ✅ 23ms
Event Options.Unset Options Omitted ✅ 24ms
Event Options.Options Override In Batch ✅ 24ms
Geoip And Historical Migration.Geoip Disable Injected Into Properties ✅ 24ms
Geoip And Historical Migration.Historical Migration Set In Body ✅ 25ms
Geoip And Historical Migration.Historical Migration Absent By Default ✅ 25ms

Feature_Flags Tests

✅ 17/17 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 16ms
Request Payload.Flags Request Uses V2 Query Param ✅ 16ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 18ms
Request Payload.Flags Request Omits Authorization Header ✅ 19ms
Request Payload.Token In Flags Body Matches Init ✅ 17ms
Request Payload.Groups Round Trip ✅ 17ms
Request Payload.Groups Default To Empty Object ✅ 16ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 16ms
Request Payload.Disable Geoip Omitted Defaults To False ✅ 15ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 15ms
Request Lifecycle.No Flags Request On Init Alone ✅ 12ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 25ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 17ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 14ms
Retry Behavior.Retries Flags On 502 ✅ 219ms
Retry Behavior.Retries Flags On 504 ✅ 221ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 24ms

@marandaneto
marandaneto marked this pull request as ready for review September 23, 2026 11:25
@marandaneto
marandaneto requested a review from a team as a code owner September 23, 2026 11:25
Comment thread src/client/async_client.rs Outdated
Comment thread src/client/async_client.rs
@veria-ai

veria-ai Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 3 · PR risk: 0/10

Comment thread src/client/async_client.rs
Comment thread src/client/async_client.rs Outdated
Comment thread src/client/async_client.rs Outdated
Comment thread src/client/transport.rs Outdated
@marandaneto
marandaneto merged commit fedcb87 into main Sep 24, 2026
26 checks passed
@marandaneto
marandaneto deleted the feat/custom-http-clients branch September 24, 2026 08:39
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.

API proposal: support application-provided HTTP clients

2 participants