Repository navigation
Name bridge transport failures without the bridge URL and close its other exits (B04) - #19
Closed
AsyncAssassin wants to merge 2 commits into
Closed
AsyncAssassin wants to merge 2 commits into
AsyncAssassin wants to merge 2 commits into
Conversation
The HTTP bridge has no credential setting of its own, so its credentials can only live in base-url, in the userinfo or the path. Every transport failure passed Spring's I/O error text on, and that text quotes the request URL: the userinfo and the path reached the health details, the WARN log, and the lastError of sync runs that the READ role sees. A transport failure now names its kind, taken from the first known exception in the cause chain (connection refused, timeout, unknown host, TLS, I/O), with that exception's class, and carries no cause. The cause chain goes to the DEBUG log with every URL cut out.
This was referenced Sep 23, 2026
…s other exits Review of the transport message fix found that it labelled a connect timeout "connection refused" whenever a ConnectException sat anywhere in the cause chain, and that it moved the only diagnosis to a DEBUG line. The kind now comes from the I/O error RestClient wraps, with a neutral "cannot connect" for a ConnectException, and the WARN line carries the cause chain with every URL cut out, the closing quote kept. The review also found where the URL still got out. HttpURLConnection never sends the userinfo of base-url, so a user name or password there only looked configured; it now stops startup with a message that leaves the URL out, and the docs say a token goes in the path or the query. At DEBUG and TRACE the JDK's HttpURLConnection and Spring's URI parser printed the URL with its token; both loggers are pinned to INFO, which the e2e test checks at a TRACE root level. Two failures on the same catch path are fixed on the way: a null element in events was an outage and is now a data error for the address, and a Retry-After beyond Instant's range turned a 429 into a failed request without its backoff.
Owner
Author
|
Combined into #23 together with the other batch-1 fixes, so they merge without a rebase per PR. This description keeps the detailed evidence for its fix. |
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
B04 from the merged review of v0.4.0; 0.4.1 is released once all fixes are merged. The HTTP bridge has no credential setting of its own, so a bridge token can only live in the path or the query of
base-url. Every transport failure, such as a refused connection or a timeout, passed Spring'sResourceAccessExceptiontext on, and that text quotes the request URL. The path reached the health details, the WARN log, and thelastErrorof sync runs that theREADrole sees.Provider transport failure: cannot connect (ConnectException).Any other failure of the request saysProvider request failed (<class>).The exception carries no cause, because the cause quotes the URL.http_provider_page_fetch_failedadds the cause chain with every URL cut out, such asResourceAccessException: I/O error on GET request for "<url>": Connection refused.HttpURLConnectionnever sends a user name or password from the URL, so one inbase-urlonly looked configured, and a bridge that needs it could only answer401. It now stops startup with a message that leaves the URL out. This is marked Breaking inCHANGELOG.md; a header credential for the bridge belongs to the bridge contract in batch 2.HttpURLConnectionand Spring's URI parser printed the URL with its token. Both are pinned to INFO next to the existingorg.springframework.web.clientpin.nullelement ineventsis a data error for its address, not a provider outage;Retry-AfterbeyondInstant's range is ignored instead of turning the429into a failed request without its backoff.docs/api.md,docs/architecture.md,docs/failure-modes.md, the README, anddocs/testing.mddescribe it.CHANGELOG.mdlists the changes under[Unreleased]→ Security, Changed, and Fixed.Verification
./gradlew clean check: 279 tests, 0 failures, 2 skipped (the env-gated Alchemy live smoke).HttpChainProviderTransportFailureTestsbuilds the bridge client withProviderConfiguration, as in production, with a token in the path and the query ofbase-url:cannot connectand no cause. The healtherrorcarries no token, and the WARN line has the cause chain with"<url>"in place of the URL;timeout;ConnectExceptionaround aClosedChannelException, gets the same label;base-urlwith a user name or password is refused without quoting it.HttpChainProviderHealthIndicatorTests: a page with"events":[null]fails as a data error with healthUP, and a429withRetry-After: 99999999999999999stays a rate limit.BridgeCredentialsE2ETestsbootse2ewith such abase-urlon a real Tomcat. It registers and syncs an address with the root log level at TRACE, then reads the run asREAD:lastErroris the fixed message, and neither the health details nor the captured log contain the token.lastError=I/O error on GET request for "http://…/PATH_SECRET/v1/chains/…".Retry-Afterguard, thenullevent check, and a URL pattern that swallows the closing quote.A regression review of the first commit (
/code-review) found the label order, the DEBUG-only diagnosis, the userinfo that is never sent, the logger leaks, and the two catch-path failures; all are fixed in the second commit. Moved to the bridge contract in batch 2:This PR and #15 to #18 and #20 each add a section under
[Unreleased]inCHANGELOG.md, so each later merge needs a one-file rebase. The other files merge cleanly with all of them.