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)

Reply via email to