Complete the backend-neutral HTTP protocol and migrate intgs onto it#24516
Open
mwdd146980 wants to merge 36 commits into
Open
Complete the backend-neutral HTTP protocol and migrate intgs onto it#24516mwdd146980 wants to merge 36 commits into
mwdd146980 wants to merge 36 commits into
Conversation
Contributor
🎉 All green!🧪 All tests passed 🔄 Datadog auto-retried 1 job - 1 passed on retry 🎯 Code Coverage (details) 🔗 Commit SHA: 5d79646 | Docs | Datadog PR Page | Give us feedback! |
3 tasks
Base automatically changed from
mwdd146980/floor-exception-translation
to
mwdd146980/httpx-migration-base
July 13, 2026 14:02
3 tasks
mwdd146980
marked this pull request as ready for review
July 13, 2026 21:04
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f1cfae991e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…seam Freeze the backend-neutral HTTP surface in http_protocol.py and implement it on RequestsWrapper so consumers depend on the protocol, not requests: - Add connection close(), get_cookie(), and a trust_env property to HTTPClientProtocol/RequestsWrapper (capabilities expose behavior, never a backend object). - Add an agnostic auth hook (HTTPRequestAuth + OutgoingRequest) with a requests.auth.AuthBase adapter, so checks contribute headers/params without a requests-family auth type. - Add an overridable AgentCheck.create_http_wrapper() factory seam behind self.http, so the backend is swappable without touching consumers. Backend stays requests; changes are additive. Foundation for the httpx2 backend.
Address code-review findings on the agnostic HTTP surface: - get_cookie: return default without eagerly building a session when none exists yet, and catch requests CookieConflictError so the documented value-or-default contract holds even with duplicate cookie names; fix the docstring. - Annotate the new _OutgoingRequest and _RequestsAuthHookAdapter helpers, matching the typed capabilities and protocols added in the same change. - Add regression tests: idempotent close after open, no-eager-session on cookie lookup, and conflict-returns-default.
- Trim the _RequestsAuthHookAdapter docstring to describe actual behavior: header edits apply via the shared dict, params are merged into the URL query, and the URL is read-only (finding 1). - Document that only per-call auth= is adapted for HTTPRequestAuth hooks; a hook set persistently via options['auth'] is unsupported (finding 4). - Revert the get_cookie hardening back to the minimal RequestsCookieJar.get delegation; that robustness was out of scope for a behavior-preserving foundation PR (finding 3). Keeps the new-code type annotations (finding 5) and the idempotent-close test (finding 7).
…otocol Round-2 review follow-ups on the agnostic HTTP surface: - get_cookie: catch requests CookieConflictError and return default so the method honors its own documented value-or-default contract. The method is new and the frozen protocol declares that contract, and the exception is requests-specific with no httpx2 equivalent, so leaving it unhandled would diverge per backend. Adds a cross-domain collision regression test. - OutgoingRequest protocol: document that url is inspection-only and writes are not guaranteed to be honored, in the frozen contract file where a second backend author will read it.
When a session is injected via session=, initialize the tracked _trust_env from that session's trust_env instead of hard-coding True, so the reported trust_env matches the session it wraps. getattr guards sessions that do not expose the attribute (e.g. autospec mocks). Adds a regression test for the injected-session case. Addresses round-2 review finding 2.
…_wrapper to create_http_client Rename the agnostic auth-hook request view OutgoingRequest (and its concrete _OutgoingRequest) to HTTPRequest/_HTTPRequest, and the factory seam AgentCheck.create_http_wrapper to create_http_client, aligning with the HTTPClientProtocol return type. Behavior unchanged.
ruff isort reordered the renamed http_protocol imports (HTTPRequest before HTTPRequestAuth) in http.py and test_auth_hook.py, and the double-close test's bare 'http.session' expression is now an assertion to satisfy B018.
The HTTPClientProtocol.get_cookie contract said only value or default; the concrete RequestsWrapper returns default on an ambiguous same-name cookie (CookieConflictError) but the frozen backend-neutral protocol gave no signal that a second backend must do the same. Align the contract so a future backend implements the edge case identically.
Remove HTTPRequest/HTTPRequestAuth from the protocol surface and the _HTTPRequest/_RequestsAuthHookAdapter plumbing plus its per-call dispatch, and delete the seam-only test. The seam had a single intended consumer (voltdb), which now sends credentials as query params without it, so the frozen surface should not carry the hook. Net diff of this PR no longer introduces it.
mwdd146980
force-pushed
the
mwdd146980/http-agnostic-protocol-surface
branch
from
July 13, 2026 22:02
f1cfae9 to
cbb7c39
Compare
… into mwdd146980/http-agnostic-protocol-surface
This was referenced Jul 14, 2026
MockHTTPResponse's __getattr__/__setattr__ rejected any name not on the HTTPResponse protocol, including leading-underscore names. When wrapped by wrapt's ResponseWrapper, wrapt forwards private attribute sets (e.g. _ResponseWrapper__default_chunk_size) to the wrapped object, and the guard raised AttributeError on those, breaking the request path. A protocol is a public contract, so only public names should be checked against it; underscore-prefixed names pass through.
Swaps the .raw.connection.sock.getpeercert access for the HTTPResponse.get_peer_cert protocol member, so the check no longer depends on the requests-specific raw urllib3 response.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Declare ignore_tls_warning and persist_connections as writable client attributes, add a should_bypass_proxy capability, and document the per-request persist option on the verb methods. These cover the client touchpoints (items 2-5 of the surface audit) integrations reach for today, so they can move onto the agnostic protocol without reaching into RequestsWrapper internals. RequestsWrapper already carried the two attributes as slots and consumed persist in _request; only should_bypass_proxy is new, delegating to the existing module-level helper. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Shorten multi-line comments to single lines and drop backticks.
Shorten the comment to one line and drop the semicolon.
Shorten multi-line comments to single lines and drop backticks.
Run ddev test --fmt across the PR's changed files.
Entries land on master through feature branch #22676, so the changelog filenames must reference that PR number. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
triviajon
approved these changes
Jul 16, 2026
apiazza-dd
approved these changes
Jul 16, 2026
* Agnosticize integrations batch A1 (catch-narrowing + tests) Narrow self.http catch sites to backend-agnostic http_exceptions and swap interception-path tests to the agnostic surface for: activemq_xml, ambari, arangodb, citrix_hypervisor, cloud_foundry_api, consul. * Agnosticize integrations batch A2 (catch-narrowing + tests) Same agnosticization for: control_m, couch, couchbase, druid, ecs_fargate, elastic, envoy. * Preserve error handling after agnostic exception narrowing (batch A review) Address review findings on #24546 where narrowed catch sites changed behavior versus master: - couchbase: the agnostic ResponseWrapper.json() raises a stdlib json.JSONDecodeError (ValueError), not an HTTPError, so a 200 with a non-JSON body escaped `except HTTPError` and aborted the run. Master caught it via the broad RequestException. Also catch json.JSONDecodeError at the three sync-gateway/query-monitoring/index-stats sites. - activemq_xml: ConnectTimeout translates to HTTPTimeoutError (a sibling of HTTPConnectionError), so connect timeouts escaped `except HTTPConnectionError` and defeated suppress_errors. Catch HTTPTimeoutError as well. - druid: add explicit parametrize ids to the can-connect failure test. * chore: drop changelog entries for feature-branch merge This PR merges into a feature branch, not master, so changelog entries aren't needed until the feature branch itself ships. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* Agnosticize integrations batch B (catch-narrowing + tests) Narrow self.http catch sites to backend-agnostic http_exceptions and swap interception-path tests to the agnostic surface for: fly_io, gitlab, harbor, hdfs_datanode, hdfs_namenode, ibm_db2, kubelet, kyototycoon, mapreduce, marathon, marklogic, mesos_master. * Catch connect timeouts in marklogic after agnostic narrowing (batch B review) ConnectTimeout translates to HTTPTimeoutError, a sibling of HTTPConnectionError, so it escaped `except (HTTPStatusError, HTTPConnectionError)` and skipped the CRITICAL connect service check that master emitted (master caught it via requests ConnectionError). Add HTTPTimeoutError to the catch. * Rename kubelet node-metrics test to match agnostic exception (batch 2 review) The test body raises HTTPStatusError, not a requests HTTPError, so rename test_report_node_metrics_kubernetes1_18_requests_httperror to ..._httpstatuserror. Test-only, no behavior change. * chore: drop changelog entries for feature-branch merge This PR merges into a feature branch, not master, so changelog entries aren't needed until the feature branch itself ships. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* Agnosticize integrations batch C1 (catch-narrowing + tests) Narrow self.http catch sites to backend-agnostic http_exceptions and swap interception-path tests to the agnostic surface for: mesos_slave, n8n, nifi, nutanix, octopus_deploy. Keeps the existing n8n/nutanix changelog entries already present on the base. * Agnosticize integrations batch C2 (catch-narrowing + tests) Narrow self.http catch sites to backend-agnostic http_exceptions and swap interception-path tests to the agnostic surface for: proxmox, rabbitmq, sonarqube, sonatype_nexus, spark, squid, teamcity, traefik_mesh, yarn, and complete prefect. * Preserve malformed-JSON handling in sonarqube after narrowing (batch C review) The agnostic ResponseWrapper.json() raises a stdlib json.JSONDecodeError (ValueError), not an HTTPError, so a 200 with a non-JSON body escaped `except HTTPError` in check() and skipped the connect service check that master emitted (master caught it via the broad RequestException). Also catch json.JSONDecodeError. * Tidy nifi test helpers after agnostic migration (batch 3 review) Address non-blocking review nits on the new nifi test helpers: - Drop the leading underscore from the module-level helpers introduced in this PR (_dispatch, _mock_http_responses -> dispatch, mock_http_responses) per the repo naming convention for test-file helpers. Pre-existing underscore helpers are left untouched (out of scope). - Route test_overlapping_process_groups_no_duplicates through mock_http_responses instead of a hand-rolled side_effect, matching its siblings. Behavior is identical (same URL-substring dispatch). * chore: drop changelog entries for feature-branch merge This PR merges into a feature branch, not master, so changelog entries aren't needed until the feature branch itself ships. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
3 tasks
…4594) * fix(openstack_controller): use backend-neutral HTTP protocol for keystone session Build the keystoneauth Session from the backend-neutral HTTPClient protocol surface (verify, cert, headers) instead of handing keystoneauth the underlying requests.Session. This removes the last openstack_controller coupling to the requests backend while preserving TLS config and the Nova and Ironic microversion headers on the SDK data-plane connection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(openstack_controller): add changelog entry for 24594 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Delete openstack_controller/changelog.d/24594.fixed --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Two stragglers from this branch's own HTTP refactors were left with stale references and broke CI: - MockHTTPResponse moved from datadog_checks.base.utils.http_testing to datadog_checks.dev.http; update the four test files still importing the old path (sonatype_nexus, nifi, traefik_mesh, nutanix). - HTTPResponseProtocol was renamed to HTTPResponse in http_protocol; update the two production files still referencing the old name (nutanix at runtime, control_m under TYPE_CHECKING). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Close protocol-compliance and hardening gaps surfaced by the automated self review, and finish decoupling http_check from requests internals. - Wrap ResponseWrapper.history so redirect items satisfy HTTPResponse and translate exceptions, instead of leaking raw requests objects. - Guard get_peer_cert against bare non-TLS sockets that lack getpeercert, so plain http:// requests return None rather than raise. - Route http_check through trust_env and close() instead of reaching into the raw session, removing its last requests-specific internals. - Drop the leading underscore from CaseInsensitiveDict and prune the redundant dunders from protocol_members(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This PR merges into the httpx-migration-base feature branch, not master, so per-integration changelog entries are premature. Remove the entries added here and restore the base-branch entries this branch had deleted, leaving the PR changelog-neutral.
3 tasks
…24597) * fix(http): migrate remaining consumers to backend-neutral HTTP protocol Replace the last direct reaches into the requests Session across four integrations with the backend-neutral HTTPClient protocol: - avi_vantage: http.close() and http.get_cookie() - cisco_aci: http.close() - hpe_aruba_edgeconnect: http.get_cookie() and http.set_header() - http_check: http.trust_env setter and http.close() Behavior is preserved; only the access path changes. Updates the hpe_aruba_edgeconnect unit tests to drive the protocol methods. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
Validation ReportAll 21 validations passed. Show details
|
This was referenced Jul 18, 2026
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?
RequestsWrapper.Protocolsuffix from the two classes (HTTPClientProtocol->HTTPClient,HTTPResponseProtocol->HTTPResponse).AgentCheck.create_http_client()factory behindself.http, so the HTTP backend can be swapped without touching consumers. The default still returns aRequestsWrapper.MockHTTPResponseout of the shipped base wheel intodatadog_checks_dev, enforces theHTTPResponsesurface on it, and updates its import sites.response.json().http_checkreads the TLS peer certificate throughget_peer_cert().openstack_controller's SDK path drops its direct requests coupling.The requests backend is unchanged. Every protocol addition is additive, and the exception migration preserves the same catch behavior through the neutral aliases.
Motivation
Groundwork for the httpx backend. Checks must depend on a backend-neutral HTTP surface rather than on requests objects, so the backend can be swapped later without editing each integration. An audit of what integrations use today surfaced gaps in the client and response contracts and a long tail of checks catching
requests.exceptions.*directly. This fills the contract gaps and moves those consumers onto the neutral surface.Relocating
MockHTTPResponsetodatadog_checks_devalso stops shipping test-only code inside the Agent bundle.Verification
RequestsWrapper, the enforcedMockHTTPResponsesurface, the kubeletresponse.json()path, and thehttp_checkpeer-cert read.Review checklist (to be filled by reviewers)
qa/requiredif this PR needs QA validation, orqa/skip-qaif it does not. Exactly one of the two is required.