[AI-6576]: requests to httpx migration#22586
Closed
mwdd146980 wants to merge 27 commits into
Closed
Conversation
Contributor
|
Contributor
|
|
Codecov Report❌ Patch coverage is Additional details and impacted files🚀 New features to boost your workflow:
|
8c1e8a5 to
31e733f
Compare
d90afe7 to
2afc793
Compare
- Add httpx dependency and HTTPXResponseAdapter wrapping httpx.Response with the same surface as the requests response (content, headers, encoding, iter_lines, iter_content, raise_for_status, close). - Introduce HTTPXWrapper with the same public API as RequestsWrapper (config, get/post/head/put/patch/delete/options_method, options dict). Supports basic auth, TLS via create_ssl_context, proxy/no_proxy, UDS, and auth_token handler. Other auth types (digest, Kerberos, NTLM, AWS) log a warning for now. - Make AgentCheck.http return HTTPXWrapper instead of RequestsWrapper. - Update test_activate to assert HTTPXWrapper; keep RequestsWrapper in tests that exercise it directly. Prometheus mixin, OpenMetrics mixin, v2 scraper, and direct RequestsWrapper usage are unchanged (Phases 2–4). Part of the migrate-requests-to-httpx proposal.
- HTTPXResponseAdapter: add json() for integrations that call response.json() - HTTPXResponseAdapter: map httpx.HTTPStatusError to requests.HTTPError with response=self - HTTPXWrapper: add session property (session.close()) for backward compatibility (e.g. cisco_aci) - _make_httpx_auth: return (user, password) tuple for basic auth so options match tests/expectations - Add test_httpx.py with unit tests for adapter, session, auth, and request/response paths
- Add datadog_checks.base.utils.httpx with HTTPXWrapper and HTTPXResponseAdapter (same public API as RequestsWrapper; http.py unchanged). - Add use_httpx option (default false) to base check; when true, self.http returns HTTPXWrapper instead of RequestsWrapper. - Add httpx dependency to datadog_checks_base. - Add unit tests in tests/base/utils/http/test_httpx.py. - Document use_httpx in docs/developer/base/http.md. - Add RFC proposal docs/proposals/migrate-requests-to-httpx.md.
2afc793 to
6a85eb3
Compare
- UDS path: run auth token retry (handle_auth_token + retry) so token refresh works for unix:// URLs like in RequestsWrapper. - Non-UDS and UDS: pass headers per request via _request_headers() instead of at client creation so AuthTokenHeaderWriter updates to self.options['headers'] are used on retry after token refresh. - Add tests for _make_httpx_auth, _parse_uds_url, adapter (iter_content, iter_lines delimiter, json, raise_for_status), wrapper (all HTTP methods, log_requests, no_proxy, persist=False, extra_headers, init options, UDS, session.close with client), and auth token retry (401 then success for both TCP and UDS). Coverage for httpx.py raised to ~89%.
…ncluding params in the set of options forwarded into request_kwargs
- Introduce HTTPResponseProtocol, HTTPSessionLike, and HTTPClientProtocol in datadog_checks.base.utils.http_protocol for type-safe use of RequestsWrapper/HTTPXWrapper. - Change AgentCheck.http return type from RequestsWrapper to HTTPClientProtocol (protocol only; behavior unchanged). - Add HTTPResponseMock and RequestWrapperMock in datadog_checks.base.utils .http_mock so tests can mock check.http without depending on requests or httpx. - Add tests for the protocol and mock helpers, and document usage in docs/developer/base/http.md.
…kwargs so that every client.request(..., **request_kwargs) receives the right timeout
Move HTTPResponseMock and RequestWrapperMock from datadog_checks.base.utils.http_mock to datadog_checks.dev.http so they are not shipped with the base check. Add http_response_mock and request_wrapper_mock pytest fixtures in the dev plugin. Update base tests and docs to use datadog_checks.dev.http.
…ttp_response - mock_response: yield HTTPResponseMock (single path) - mock_http_response: require check class as first arg, patch get_http_handler with RequestWrapperMock only; raise ValueError if no class given (no requests.Session.get) - mock_http_response_per_endpoint: use mock_response for 404, add optional handler_target to patch get_http_handler by URL - HTTPResponseMock: support content- and status_code-first calls, file_path/content/json_data, .text, .raw, context manager for v2 scraper
Introduce datadog_checks.base.utils.http_exceptions (HTTPError, SSLError) so HTTP client wrappers and tests can use a single exception contract instead of requests/httpx-specific types. - ResponseWrapper.raise_for_status(): catch requests.HTTPError, re-raise SharedHTTPError(response=self). - RequestsWrapper._request(): catch requests ConnectionError/SSLError, re-raise built-in ConnectionError and SharedSSLError. - HTTPXResponseAdapter.raise_for_status(): raise http_exceptions.HTTPError. - HTTPResponseMock.raise_for_status(): raise http_exceptions.HTTPError instead of requests.exceptions.HTTPError. Enables openmetrics/prometheus and other consumers to stop depending on requests exception types and supports eventually removing the requests dependency.
…pper Convert httpx.ConnectError and httpx.ConnectTimeout from _request to built-in ConnectionError and SharedSSLError so callers (e.g. OpenMetrics v2 base_scraper) that catch ConnectionError or SharedSSLError behave correctly when use_httpx=True. Matches exception handling in RequestsWrapper.
…k class - mock_http_response: when no check class is given, patch both base_scraper.RequestsWrapper and mixins.RequestsWrapper so v2 and legacy OpenMetrics tests work; set options['headers'] on the mock for scraper init - RequestWrapperMock: add .text for legacy tests that use mock_http_response(...).return_value.text
…r patching mock_http_response now only supports the get_http_handler path: the first argument must be a check class with get_http_handler (e.g. OpenMetricsBaseCheckV2, OpenMetricsBaseCheck). The fixture patches that class's get_http_handler and uses a per-test response queue so multiple calls enqueue responses in order. Remove the legacy branch that patched base_scraper.RequestsWrapper and mixins.RequestsWrapper when no class was passed.
- Add httpx-gssapi dependency (http extra and agent_requirements) and LICENSE-3rdparty entry. - Implement _create_kerberos_auth_httpx() in httpx.py, mapping the same config keys as RequestsWrapper (kerberos_auth, delegate, force_initiate, hostname, principal) to HTTPSPNEGOAuth. - Use it from _make_httpx_auth when auth_type is kerberos; on ImportError log a warning and send requests without auth. - Add unit tests for Kerberos auth (mocked httpx_gssapi) and for _make_httpx_auth delegating to the Kerberos helper.
- mock_http_response: support general mode when called without a check class; return (client, enqueue) so tests without a check can inject a RequestWrapperMock and feed responses via enqueue(). - Keep check mode unchanged: mock_http_response(CheckClass, ...) still patches get_http_handler with a queue-backed RequestWrapperMock. - Add tests for general mode in test_http_mock.py (client, enqueue, empty-queue default). - docs/developer/base/http.md: document check mode, general mode, and direct HTTPResponseMock/RequestWrapperMock usage. - docs/proposals/migrate-requests-to-httpx.md: note implementation branches (ai-6576, base-httpx-migration) and testing/mock design.
- mock_http_response: check-only; require check class as first arg, patch get_http_handler with queue-backed RequestWrapperMock. - mock_http_client: new fixture; returns (client, enqueue) for tests without a check; inject client where the HTTP wrapper is created. - Remove http_response_mock (redundant with mock_response); document in mock_response docstring. - request_wrapper_mock: clarify use for custom handler logic when mock_http_response/mock_http_client are not enough; example uses mock_response. - test_http_mock: add TestMockHttpClient for mock_http_client; use mock_http_client fixture in those tests. - docs/developer/base/http.md, docs/proposals/migrate-requests-to-httpx.md: describe mock_http_response and mock_http_client; note request_wrapper_mock for custom logic only.
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.
What does this PR do?
This PR adds an optional httpx-backed HTTP client alongside the existing requests-based one and introduces shared types so the codebase can support both backends without changing call sites.
New module
datadog_checks.base.utils.httpxRequestsWrapper(get/post/head/put/patch/delete/options_method,options,session, etc.).httpx.Responseto match the current response surface (content, headers, encoding, iter_lines, raise_for_status, etc.).Shared exception and protocol types
datadog_checks.base.utils.http_exceptions– HTTPError and SSLError used by both wrappers and by checks soexceptclauses don’t depend on requests/httpx.datadog_checks.base.utils.http_protocol– HTTPClientProtocol and HTTPResponseProtocol for type hints and future backends (e.g. async).HTTPClientProtocoldescribes the wrapper interface (get/post/…/options_method, options, session, handle_auth_token);HTTPResponseProtocoldescribes the response (content, headers, iter_lines, raise_for_status, etc.). Both wrappers implement these so type checkers and call sites see a single interface.requests.HTTPError. Session handling respects an injected session for tests (e.g.session=make_mock_session()).Base check opt-in
use_httpx(defaultfalse) in instance or init_config.true,AgentCheck.httpreturns HTTPXWrapper; otherwise RequestsWrapper.self.httpis typed as HTTPClientProtocol so both implementations are valid.Fixture and mock changes
mock_http_response– Check-only: first argument must be a check class withget_http_handler; it patches that class and serves responses from a queue.mock_http_client– New fixture; returns(client, enqueue)for tests without a check; injectclientwhere the HTTP wrapper is created.request_wrapper_mockdocstring clarified for custom handler logic when the above two aren’t enough.Dependencies
Integrations keep using
self.http.get(url)etc.; no call-site changes. OpenMetrics/Prometheus wiring (e.g.get_http_handleron the check, scraper using it) and test migrations to the new fixtures are in the base-httpx-migration branch.Motivation
RFC
Review checklist (to be filled by reviewers)
qa/skip-qalabel if the PR doesn't need to be tested during QA.backport/<branch-name>label to the PR and it will automatically open a backport PR once this one is merged