SMOODEV-948: Async auth-token provider across TS, Python, Rust, Go#72
Merged
Conversation
Only .NET shipped a first-class `AuthTokenProvider` delegate. The other four ports forced callers to wire auth either statically (`with_auth(string)`) or manually via a pre-request hook. Add a real async provider hook to each. TypeScript ---------- - `FetchBuilder.withAuthTokenProvider(provider, scheme = 'Bearer')`. - `PreRequestHook` return type widened to allow `Promise<...>` so the pipeline can `await` async hooks. The new builder method composes with any existing pre-request hook (hook runs first, Authorization injected after). - Export new `AuthTokenProvider` type. Python ------ - `FetchBuilder.with_auth_provider(provider, scheme='Bearer')`. - New `auth_token_provider` + `auth_scheme` fields on `FetchOptions`. - Provider may return `str` or an awaitable; the client awaits inline. Rust ---- - New `AuthTokenProvider` type alias (`Arc<dyn Fn() -> Pin<Box<dyn Future<Output=String>>>>`). - `FetchBuilder::with_auth_provider(provider, scheme)`. - `FetchClient` calls the provider before each `fetch()` / `fetch_with_options()` and injects the Authorization header into the merged init. Go -- - `AuthTokenProvider` type: `func(ctx context.Context) (string, error)`. - `ClientBuilder.WithAuthTokenProvider(provider, scheme)`. - Provider is invoked inside `executeHTTPRequest` after pre-request hook so cancellation/timeouts flow through; provider errors propagate via the PostResponseError hook chain. Tests ----- - TS: 4 new cases in `fetch.spec.ts` (sync, async, custom scheme, hook composition). - Python: new `test_auth_provider.py` with 5 cases. - Rust: new `auth_provider_tests.rs` with 3 cases. - Go: new `auth_provider_test.go` with 4 cases.
🦋 Changeset detectedLatest commit: 498c982 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
2 tasks
brentrager
added a commit
that referenced
this pull request
May 12, 2026
…ejection, FastFirst (#75) Brings the .NET port closer to feature parity with the TS / Python / Rust / Go ports. Existing `SmooFetchOptions` + `SmooFetch.Create` factory remain for backwards compatibility — everything new is additive. New surface ----------- - `SmooFetchBuilder` (`SmooFetchBuilder.Create().With...().Build()`). - `LifecycleHooks` with `PreRequest`, `PostRequestOk`, `PostRequestErr`. - `CircuitBreakerOptions` + Polly v8 circuit breaker composed inside the resilience pipeline. Trips on the same predicates as the retry policy. - `OnRejectionCallback` / `OnRejectionDecision` (`Retry` / `RetryWithDelay` / `Abort` / `Skip` / `Default`) honored by the Polly `DelayGenerator`. - `RetryPolicy.FastFirst` — first retry fires with zero delay. - `RetryPolicy` converted to `record` so builder methods can use `with` to compose policies on the fly. Tests ----- New `SmooFetchBuilderTests` (7 cases) cover the builder happy path, PreRequest / PostRequestOk hook firing, the PostRequestErr documented behavior (only fires on transport-level throws, not HttpResponseError from the JSON reader), FastFirst skipping the initial backoff, OnRejection RetryWithDelay overriding the default delay, and the circuit breaker tripping after the failure threshold. Also included ------------- - `#[allow(dead_code)]` on `TestReply` in the Rust `auth_provider_tests.rs` added in PR #72 — the struct is only used as a `serde` deserialization target so cargo errors under `-D warnings` without the annotation. Out of scope (parked as follow-up) ---------------------------------- - Sliding-window rate limiter for .NET (callout from SMOODEV-946: "Rate limiter and FastFirst can ship as a follow-up if context is tight" — FastFirst is included; rate limiter is the only remaining gap). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a first-class async auth-token provider to TS, Python, Rust, and Go (.NET already has one). The provider is invoked before every request to mint/refresh a token, with the result injected as the
Authorizationheader using a configurable scheme (defaultBearer).FetchBuilder.withAuthTokenProvider(provider, scheme?).PreRequestHookwidened to allow async returns so the pipeline can await hooks.FetchBuilder.with_auth_provider(provider, scheme='Bearer'). Provider may be sync or async.FetchBuilder::with_auth_provider(provider, scheme)withArc<dyn Fn() -> Pin<Box<dyn Future<Output=String>>>>.ClientBuilder.WithAuthTokenProvider(provider, scheme)withfunc(ctx context.Context) (string, error)— propagates context + errors.Test plan
pnpm exec vitest run(48 passed; 4 new)uv run pytest(118 passed; 5 new)cargo test(107 passed; 3 new)go test ./...(94 passed; 4 new)