Pluggable HTTP client#149
Open
up2jj wants to merge 7 commits into
Open
Conversation
Introduce a `ConfigCat.HTTPClient` behaviour with a normalized request contract (plain maps for response/error, no HTTPoison structs at the boundary). `ConfigCat.API` becomes the default adapter wrapping HTTPoison and classifying transient vs. permanent errors. Callers can swap in Finch, Req, Mint, Tesla or a test stub via the new `:http_client` start option, which the supervisor plumbs through to the config fetcher.
HTTPoison and Finch are both declared as optional deps. ConfigCat.API guards itself with Code.ensure_loaded?/1 and raises a clear error if neither HTTPoison nor a custom :http_client is configured. ConfigCat.HTTPClient.Finch is a drop-in adapter that translates the SDK's HTTPoison-shaped timeout options to Finch's request options and reads the pool name from application config.
Pattern matching on %HTTPoison.Response{} / %HTTPoison.Error{} in
ConfigCat.API and %Finch.Response{} in ConfigCat.HTTPClient.Finch
forced the compiler to resolve those structs at compile time, so the
SDK could not compile when the optional dep was absent. Match on the
underlying map shape instead — same runtime semantics, no compile-time
coupling to the optional package.
Group the two built-in adapters under one namespace so they're discoverable side-by-side in HexDocs: ConfigCat.HTTPClient.HTTPoison (default) ConfigCat.HTTPClient.Finch
Member
|
Hey @up2jj, |
Finch 0.18+ requires Elixir ~> 1.15, causing compile failures on the 1.12 and 1.14 CI jobs. Since we are contributors rather than maintainers we cannot bump the project's minimum Elixir version, so remove the Finch adapter and its dependency entirely. Users who need Finch can implement the ConfigCat.HTTPClient behaviour themselves. Also fix a formatting issue in config_fetcher.ex (guard clause line wrapping) that caused the Elixir 1.16 format check to fail.
9a516d3 to
f10cadf
Compare
Author
Hey @kp-cat I had to drop the support for Finch as it is not supported on Elixir 1.12. As long as you want to support this version SDK, Finch adapter cannot be shipped together due to failing check. Users can still implement it on their own. |
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.
Describe the purpose of your pull request
Make the HTTP transport pluggable so the SDK no longer hard-codes HTTPoison. Apps can keep the current default or supply their own client (Req, Mint, Finch, Tesla, a test stub, ...) via a small behaviour.
ConfigCat.HTTPClientbehaviour with a normalized request/response contract (plain maps — no HTTP-client structs leak across the boundary). Adapters are responsible for classifying errors as transient vs. permanent.ConfigCat.HTTPClient.HTTPoison— the default adapter, wraps HTTPoison. Guards itself withCode.ensure_loaded?/1and raisesArgumentErrorif HTTPoison is missing and no custom client was provided. (Replaces the previous internalConfigCat.API.):httpoisonis now declaredoptional: trueinmix.exs. Consumer apps add it explicitly — or skip it entirely if they ship their own adapter.ConfigFetcherdrops all HTTPoison struct pattern matches and consumes the normalized map contract instead. The internal:apifield is renamed to:http_client; the supervisor plumbs a new:http_clientstart option through to the fetcher.ConfigCatmoduledoc documents the new option.Backwards compatible on the wire: the default adapter preserves today's headers, options pass-through, and transient/permanent error split.
Related issues (only if applicable)
N/A
How to test?
mix test— the full suite (436 tests) passes against the new default adapter; fetcher and data-governance tests were updated to use normalized response maps instead of%HTTPoison.Response{}and thehttp_client:option in place ofapi:.ConfigCat.HTTPClient, pass it viahttp_client:, and verifyConfigFetcherworks without HTTPoison being called. The Mox-backedConfigCat.MockAPI(now mockingConfigCat.HTTPClient) is a ready-made example.:httpoisonfrom a consumer app's deps without setting:http_client— startup raises a clearArgumentErrorinstructing the user to either add HTTPoison or provide their own client.{:error, %{reason: :timeout, transient?: true}}and{:error, %{reason: :unauthorized, transient?: false}}; verify the fetcher's retry/log behavior matches the previous HTTPoison-coupled implementation.Security
The SDK still only issues outbound HTTPS requests to the ConfigCat CDN. Custom adapters run in the user's own application process and inherit whatever TLS/proxy posture they configure for their HTTP client — that boundary is now explicit (a documented behaviour) rather than implicit (HTTPoison/hackney options leaked through the SDK).
Requirement checklist