Pierre N. created HTTPCLIENT-2301:
-------------------------------------

             Summary: BasicHttpClientConnectionManager returns response of 
previous requests
                 Key: HTTPCLIENT-2301
                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-2301
             Project: HttpComponents HttpClient
          Issue Type: Improvement
          Components: HttpClient (classic)
    Affects Versions: 5.3-alpha1, 5.2.1
         Environment: JAVA 18
kotlin 1.7.22
Ubuntu 22.04 x64
            Reporter: Pierre N.


BasicHttpClientConnectionManager doesn't handle request timeout correctly and 
return the response of a previous request.

In the unit test below should output:

{quote}
http://localhost:41751/1 -> 1
http://localhost:41751/2 -> java.net.SocketTimeoutException: Read timed out
http://localhost:41751/2 -> java.net.SocketTimeoutException: Read timed out
http://localhost:41751/3 -> 3
http://localhost:41751/3 -> 3
http://localhost:41751/3 -> 3
{quote}

But instead it returns:

{quote}
http://localhost:33875/1 -> 1
http://localhost:33875/2 -> java.net.SocketTimeoutException: Read timed out
http://localhost:33875/2 -> java.net.SocketTimeoutException: Read timed out
http://localhost:33875/3 -> java.net.SocketTimeoutException: Read timed out
http://localhost:33875/3 -> 2
http://localhost:33875/3 -> 3
{quote}


As you can see it returns 2 when requesting the uri /3 which returned 3.
Also it timeout on the first request to /3 while it shouldn't.

Replace with PoolingHttpClientConnectionManager() and it works as expected.

Kotlin unit test to reproduce :

{quote}
import com.github.tomakehurst.wiremock.client.WireMock.*
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo
import com.github.tomakehurst.wiremock.junit5.WireMockTest
import org.apache.hc.client5.http.classic.methods.HttpGet
import org.apache.hc.client5.http.config.RequestConfig
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient
import org.apache.hc.client5.http.impl.classic.HttpClients
import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager
import org.apache.hc.core5.http.io.entity.EntityUtils
import org.apache.hc.core5.util.Timeout
import org.junit.jupiter.api.Test

//@Disabled
@WireMockTest
internal class HttpClientRaceConditionDebug {

    @Test
    fun `debugging z`(wm: WireMockRuntimeInfo) {
        stubFor(get(urlEqualTo("/1")).willReturn(aResponse().withBody("1")))
        
stubFor(get(urlEqualTo("/2")).willReturn(aResponse().withFixedDelay(2000).withBody("2")))
        stubFor(get(urlEqualTo("/3")).willReturn(aResponse().withBody("3")))

        val client = HttpClients.custom()
            .setConnectionManager(BasicHttpClientConnectionManager())
//            .setConnectionManager(PoolingHttpClientConnectionManager())
            .setDefaultRequestConfig(
                RequestConfig.custom()
                    .setResponseTimeout(Timeout.ofSeconds(1))
                    .build()
            )
            .build()

        client.executeAndLog("${wm.httpBaseUrl}/1")
        client.executeAndLog("${wm.httpBaseUrl}/2")
        client.executeAndLog("${wm.httpBaseUrl}/2")
        client.executeAndLog("${wm.httpBaseUrl}/3")
        client.executeAndLog("${wm.httpBaseUrl}/3")
        client.executeAndLog("${wm.httpBaseUrl}/3")
    }

    private fun CloseableHttpClient.executeAndLog(uri: String) {
        try {
            execute(HttpGet(uri)) { println("$uri -> 
${EntityUtils.toString(it.entity)}") }
        } catch (ex: Exception) {
            println("$uri -> $ex")
        }
    }
}
{quote}




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@hc.apache.org
For additional commands, e-mail: dev-h...@hc.apache.org

Reply via email to