Skip to content

Release the connection for each redirect hop in parse(URL) - #113

Merged
pjfanning merged 1 commit into
apache:trunkfrom
pjfanning:leak-url-redirect-connections
Sep 7, 2026
Merged

Release the connection for each redirect hop in parse(URL)#113
pjfanning merged 1 commit into
apache:trunkfrom
pjfanning:leak-url-redirect-connections

Conversation

@pjfanning

Copy link
Copy Markdown
Member

SchemaTypeLoaderBase.parse(URL) follows up to five redirects. Each pass through the loop opens a connection and calls getResponseCode() — which sends the request and reads the response — then reassigns url and loops, never touching that connection again. Only the final connection is closed, by the try-with-resources around conn.getInputStream().

The redirect bodies are never read, so those sockets sit in the keep-alive cache holding a file descriptor until a finalizer or the cache timeout reclaims them. Fetching a redirected schema can therefore hold five idle sockets per call.

This calls disconnect() on the hop being abandoned.

Added ParseUrlRedirectTest: a loopback HttpServer serving a three-hop redirect chain to a small document. It passes both with and without the fix — its job is to pin the redirect-following behaviour and prove disconnect() does not break the chain, since the descriptor release itself is not directly observable from a test.

🤖 Generated with Claude Code

SchemaTypeLoaderBase.parse(URL) follows up to five redirects. Each pass opens a
connection and calls getResponseCode(), which reads the response, then moves on
to the next URL without touching that connection again. Only the final one is
closed, by the try-with-resources around getInputStream().

The redirect bodies are never read, so the sockets sit in the keep-alive cache
holding a descriptor until a finalizer or the cache timeout reclaims them. Call
disconnect() on the hop being abandoned instead.

Added ParseUrlRedirectTest, a loopback HttpServer serving a three-hop redirect
chain, to pin the follow behaviour - it passes either way and guards against
disconnect() breaking the chain.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@pjfanning
pjfanning merged commit c0c0c65 into apache:trunk Sep 7, 2026
3 checks passed
@pjfanning
pjfanning deleted the leak-url-redirect-connections branch September 7, 2026 12:00
pjfanning added a commit that referenced this pull request Sep 7, 2026
)

ParseUrlRedirectTest (added in #113) starts a com.sun.net.httpserver server on
loopback to pin redirect following. That package is not in the Android API
signature animalsniffer checks against, so animalsnifferTest reports 19
undefined references and ./gradlew check fails.

The signature describes what the published artifact may use. Test code never
ships and never runs on Android, so exclude just this file rather than weaken
the signature for main. Excluding the whole test source set would also work -
the animalsniffer block already carries a commented-out
"sourceSets = [sourceSets.main]" for that - but this keeps the rest of the
tests covered.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant