Seshu Thota created CAMEL-26110:
-----------------------------------
Summary: camel-as2 - client keeps a connection the partner closed
in the pool, so the next send fails
Key: CAMEL-26110
URL: https://issues.apache.org/jira/browse/CAMEL-26110
Project: Camel
Issue Type: Bug
Components: camel-as2
Affects Versions: 4.23.0
Reporter: Seshu Thota
h3. Problem
When the AS2 partner answers with {{Connection: close}},
{{AS2ClientConnection.send()}} still returns the connection to the pool as
reusable, with no expiry. A send that leases it within 2 seconds writes on a
socket the partner has closed and fails with {{NoHttpResponseException: The
target server failed to respond}}. After 2 seconds of idle time the pool's
stale check ({{validateAfterInactivity}}, 2s by default) discards it, so the
failure only shows when sends follow each other quickly.
h3. Cause
In {{AS2ClientConnection}} (main):
* The keep-alive strategy returns {{TimeValue.NEG_ONE_MILLISECOND}} for a
{{Connection: close}} response (line 161).
* When there is no response, the {{finally}} block of {{send()}} releases with
{{TimeValue.ZERO_MILLISECONDS}} (line 228). Its comment says "do NOT keep this
connection around".
In HttpClient 5.6.4 and 5.6.5 (the version on main),
{{PoolingHttpClientConnectionManager.release()}} closes the connection only
when the keep-alive is {{null}}. With any other value, an open connection goes
back to the pool, and {{PoolEntry.updateExpiry()}} gives a non-positive value
no expiry ({{Deadline.calculate()}} returns {{MAX_VALUE}}). So {{NEG_ONE}} and
{{ZERO}} both keep the connection, which is the opposite of what is intended.
The {{ZERO}} case does not cause a failure on its own today:
{{HttpRequestExecutor.execute()}} closes the connection itself on an exception,
so it is not reusable when it is released. The {{Connection: close}} case does.
h3. Reproduction
A plain server that answers each request with {{HTTP/1.1 200 OK}},
{{Connection: close}}, {{Content-Length: 2}}, then closes the socket. Three
sends in a row through one {{AS2ClientConnection}} (no proxy):
{noformat}
send 0 -> 200
send 1 FAILED org.apache.hc.core5.http.NoHttpResponseException: The target
server failed to respond
send 2 -> 200
connections with a request: 2
{noformat}
Send 1 reused the closed connection; send 2 worked because the failed
connection was closed by then.
h3. Proposed change
In the {{finally}} block of {{send()}}, release with a {{null}} keep-alive,
which closes the connection, when there is no response or when HttpCore's
{{DefaultConnectionReuseStrategy}} says the connection cannot be kept
({{Connection: close}}, HTTP/1.0 without keep-alive, a response without a
length). Otherwise release with the keep-alive from the strategy, as today. Add
a test with a partner that answers {{Connection: close}} and several sends in a
row.
Found while addressing the review of https://github.com/apache/camel/pull/28265
(CAMEL-25941), where the same release behaviour kept a connection whose proxy
tunnel had failed. That PR closes the connection explicitly in its own failure
cases and leaves this block as it is.
_Filed with the help of Claude Code on behalf of seshuthota._
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)