From 9c402f7ae7b8776631605313400ea2579fa89896 Mon Sep 17 00:00:00 2001 From: Frantisek Nagy Date: Tue, 9 Jul 2024 12:17:20 +0200 Subject: [PATCH 1/2] Fix duplicate network call for chunked responses --- .../main/java/coil/fetch/HttpUriFetcher.kt | 2 +- .../java/coil/fetch/HttpUriFetcherTest.kt | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/coil-base/src/main/java/coil/fetch/HttpUriFetcher.kt b/coil-base/src/main/java/coil/fetch/HttpUriFetcher.kt index 2278ca42b6..4f75ed34cf 100644 --- a/coil-base/src/main/java/coil/fetch/HttpUriFetcher.kt +++ b/coil-base/src/main/java/coil/fetch/HttpUriFetcher.kt @@ -93,7 +93,7 @@ internal class HttpUriFetcher( } // If we failed to read a new snapshot then read the response body if it's not empty. - if (responseBody.contentLength() > 0) { + if (response.peekBody(1).bytes().isNotEmpty()) { return SourceResult( source = responseBody.toImageSource(), mimeType = getMimeType(url, responseBody.contentType()), diff --git a/coil-base/src/test/java/coil/fetch/HttpUriFetcherTest.kt b/coil-base/src/test/java/coil/fetch/HttpUriFetcherTest.kt index 260d56a84f..7f3f218765 100644 --- a/coil-base/src/test/java/coil/fetch/HttpUriFetcherTest.kt +++ b/coil-base/src/test/java/coil/fetch/HttpUriFetcherTest.kt @@ -35,6 +35,7 @@ import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockWebServer +import okio.Buffer import okio.FileSystem import okio.blackholeSink import okio.buffer @@ -147,6 +148,18 @@ class HttpUriFetcherTest { assertEquals(expectedSize, result.source.use { it.source().readAll(blackholeSink()) }) } + @Test + fun `no disk cache and chunked response - fetcher calls network just once`() = runTestAsync { + val url = server.url(IMAGE).toString() + + server.enqueueChunkedImage(IMAGE) + server.enqueueChunkedImage(IMAGE) + + newFetcher(url, diskCache = null).fetch() + + assertEquals(1, server.requestCount) + } + @Test fun `request on main thread with network cache policy disabled executes without throwing`() = runTestAsync { val expectedSize = server.enqueueImage(IMAGE) @@ -458,6 +471,14 @@ class HttpUriFetcherTest { assertEquals(expectedSize, result.source.use { it.source().readAll(blackholeSink()) }) } + fun MockWebServer.enqueueChunkedImage(image: String) { + val buffer = Buffer() + val context = ApplicationProvider.getApplicationContext() + context.assets.open(image).source().buffer().readAll(buffer) + val response = MockResponse().setChunkedBody(buffer, 100) + enqueue(response) + } + private fun newFetcher( url: String, options: Options = Options(context), From cb4822c29089725ff143be138e08b81281430222 Mon Sep 17 00:00:00 2001 From: ferinagy <2743419+ferinagy@users.noreply.github.com> Date: Wed, 10 Jul 2024 11:27:49 +0200 Subject: [PATCH 2/2] Avoid allocating a new peek source Co-authored-by: Colin White --- coil-base/src/main/java/coil/fetch/HttpUriFetcher.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coil-base/src/main/java/coil/fetch/HttpUriFetcher.kt b/coil-base/src/main/java/coil/fetch/HttpUriFetcher.kt index 4f75ed34cf..b1ddae1cc0 100644 --- a/coil-base/src/main/java/coil/fetch/HttpUriFetcher.kt +++ b/coil-base/src/main/java/coil/fetch/HttpUriFetcher.kt @@ -93,7 +93,7 @@ internal class HttpUriFetcher( } // If we failed to read a new snapshot then read the response body if it's not empty. - if (response.peekBody(1).bytes().isNotEmpty()) { + if (responseBody.source().request(1L)) { return SourceResult( source = responseBody.toImageSource(), mimeType = getMimeType(url, responseBody.contentType()),