Repository navigation
feat(client): construct clients from FMP_API_KEY and FMP_BASE_URL for proxy routing - #418
Merged
Merged
Conversation
This change lets callers build a client from the process environment, which simplifies routing through a proxy that issues its own keys and forwards to FMP without any code change. **Environment-driven client construction:** * Added `ClientBuilder::from_env` and `Client::from_env`, which read `FMP_API_KEY` and `FMP_BASE_URL` to select the `apikey` header authentication and an optional base URL override while keeping the default path prefix. * The key becomes `Authentication::FmpHeader`; a set base URL replaces the default origin and keeps its path, so `https://valet.bitbrew.app/fmp` sends the quote endpoint to `https://valet.bitbrew.app/fmp/stable/quote`. * A missing or blank `FMP_API_KEY` yields `MissingCredential`; an invalid, unsafe, or insecure base URL reports its typed configuration error at build time, and selecting a second authentication fails with `ConflictingAuthentication`. `Client::builder` never reads the environment. **Base URL environment reader:** * Added `FMP_BASE_URL_ENV` and `fmp_base_url_from_env` in config, which trim surrounding whitespace and treat an empty or whitespace-only value as unset, factored through a shared `trimmed_non_empty` helper. **Tests and documentation:** * Added tests covering the proxy base URL, the default FMP origin fallback, the typed error cases, loopback and dangerous-http rules, conflicting authentication, and base URL trimming. * Documented the proxy workflow in the README and switched the custom-router example to the `FMP_BASE_URL` variable.
This commit introduces an environment-based constructor so callers can route through a proxy that issues its own keys, such as valet, without wiring the options by hand. **New environment-based client:** * Added `NewClientFromEnv`, which reads `FMP_API_KEY` and sends it as the `apikey` header via `FMPHeader`, and `FMP_BASE_URL`, which replaces `DefaultBaseURL` while keeping its path so the quote endpoint resolves to the proxy origin (for example `https://valet.bitbrew.app/fmp/stable/quote`). * Added `BaseURLFromEnv`, which reads and trims `FMP_BASE_URL` and reports false when unset, empty, or whitespace-only, leaving validation to `NewClient`. * Exported the `EnvBaseURL` constant for the `FMP_BASE_URL` variable. * Applied options after the environment so `WithBaseURL` wins, while `WithAuthentication` conflicts with the environment key; a missing or blank key returns `ConfigurationKindMissingCredential`, and every `NewClient` rule still applies, including the refusal of plaintext HTTP to a non-loopback host without the danger opt-in. **Testing:** * Added tests covering base URL normalization, proxy targeting with the header auth, the fallback to the FMP origin, option precedence and the authentication conflict, typed configuration errors with no key leakage, and the loopback and dangerous-HTTP rules. **Documentation:** * Documented the new constructor and `FMP_BASE_URL` in the README and package docs, noting the environment names match the Rust crate.
This commit lets `FmpClient` resolve its base URL from the `FMP_BASE_URL` environment variable when no explicit `base_url` is passed, so a proxy such as valet works with only `FMP_API_KEY` and `FMP_BASE_URL` set and no code change. **Functional change:** * Added `resolve_base_url` in client.rs, which prefers an explicit `base_url` and otherwise falls back to `fmp_base_url_from_env`; a blank variable keeps the default `https://financialmodelingprep.com` origin. * The variable only replaces the base URL and never selects or relaxes authentication, so the `token` and `FMP_API_KEY` precedence rules are unchanged. **Tests:** * Added tests/test_base_url_env.py to cover the new pickup and precedence. * The autouse `isolated_api_key_env` fixture now also unsets `FMP_BASE_URL` so the developer's shell cannot leak into the suite. **Docs:** * Documented the behaviour in README.md with a "Using a proxy" section and a precedence table, and in the `__init__.pyi` and client.rs docstrings. close #415
benbenbang
enabled auto-merge (rebase)
October 6, 2026 09:58
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.
Routing requests through a proxy that issues its own keys and forwards to FMP previously required wiring client options by hand in each language binding. This adds environment-driven client construction across the Rust crate, the Go SDK, and the Python package so callers can target a proxy such as valet with only
FMP_API_KEYandFMP_BASE_URLset and no code change.What changed:
FMP_API_KEYas anapikeyheader and an optionalFMP_BASE_URLoverride:ClientBuilder::from_env/Client::from_envin libfmp,NewClientFromEnvin the Go SDK, andFMP_BASE_URLfallback inFmpClientwhenbase_urlis omitted.fmp_base_url_from_env,BaseURLFromEnv/EnvBaseURL,resolve_base_url), replacing the default origin while preserving its path so the quote endpoint resolves under the proxy.FMP_BASE_URLto avoid shell leakage.FMP_BASE_URLvariable in each README, package docs, and docstrings.close #415