Uploaded image for project: 'HttpComponents HttpClient'
  1. HttpComponents HttpClient
  2. HTTPCLIENT-2301

BasicHttpClientConnectionManager returns response of previous requests

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Minor
    • Resolution: Fixed
    • 5.2.1, 5.3-alpha1
    • 5.4-alpha1
    • HttpClient (classic)
    • JAVA 18
      kotlin 1.7.22
      Ubuntu 22.04 x64

    Description

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

      The unit test below should output:

      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

      But instead it returns:

      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

      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 :

      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

      @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)

      Unknown macro: { println("$uri -> $ex") }

      }
      }

      Attachments

        1. test.kt
          2 kB
          Pierre N.

        Activity

          People

            abernal Arturo Bernal
            pierz Pierre N.
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Time Tracking

                Estimated:
                Original Estimate - Not Specified
                Not Specified
                Remaining:
                Remaining Estimate - 0h
                0h
                Logged:
                Time Spent - 1.5h
                1.5h