@@ -35,7 +35,10 @@ import mockwebserver3.SocketEffect.CloseSocket
3535import mockwebserver3.SocketEffect.ShutdownConnection
3636import mockwebserver3.junit5.StartStop
3737import okhttp3.Headers.Companion.headersOf
38+ import okhttp3.HttpUrl.Companion.toHttpUrl
39+ import okhttp3.ResponseBody.Companion.toResponseBody
3840import okhttp3.testing.PlatformRule
41+ import okio.BufferedSource
3942import okio.IOException
4043import okio.Path.Companion.toPath
4144import okio.fakefilesystem.FakeFileSystem
@@ -419,6 +422,70 @@ open class TrailersTest {
419422 }
420423 }
421424
425+ @Test
426+ fun bufferResponseBodyAndReadTrailersHttp1 () {
427+ bufferResponseBodyAndReadTrailers(Protocol .HTTP_1_1 )
428+ }
429+
430+ @Test
431+ fun bufferResponseBodyAndReadTrailersHttp2 () {
432+ bufferResponseBodyAndReadTrailers(Protocol .HTTP_2 )
433+ }
434+
435+ private fun bufferResponseBodyAndReadTrailers (protocol : Protocol ) {
436+ enableProtocol(protocol)
437+
438+ server.enqueue(
439+ MockResponse
440+ .Builder ()
441+ .trailers(headersOf(" t1" , " v1" ))
442+ .body(protocol, " Hello" )
443+ .build(),
444+ )
445+
446+ val call = client.newCall(Request (server.url(" /" )))
447+ call.execute().use { originalResponse ->
448+ val responseBodyData = originalResponse.body.byteString()
449+ val responseTrailers = originalResponse.trailers()
450+ assertThat(responseTrailers).isEqualTo(headersOf(" t1" , " v1" ))
451+
452+ val rewrittenResponse =
453+ originalResponse
454+ .newBuilder()
455+ .body(responseBodyData.toResponseBody())
456+ .build()
457+ assertThat(rewrittenResponse.body.string()).isEqualTo(" Hello" )
458+ assertThat(rewrittenResponse.trailers()).isEqualTo(headersOf(" t1" , " v1" ))
459+ }
460+ }
461+
462+ /* *
463+ * We had a bug where a custom `ResponseBody` interacted poorly with `Response.trailers()`.
464+ * Confirm custom trailers can be read without even accessing the response body.
465+ */
466+ @Test
467+ fun customTrailersDoNotUseResponseBody () {
468+ val response =
469+ Response
470+ .Builder ()
471+ .request(Request (url = " https://example.com" .toHttpUrl()))
472+ .protocol(Protocol .HTTP_1_1 )
473+ .code(200 )
474+ .message(" OK" )
475+ .body(
476+ object : ResponseBody () {
477+ override fun contentType (): MediaType ? = null
478+
479+ override fun contentLength (): Long = - 1L
480+
481+ override fun source (): BufferedSource = error(" unexpected call" )
482+ },
483+ ).trailers { headersOf(" t1" , " v1" ) }
484+ .build()
485+
486+ assertThat(response.trailers()).isEqualTo(headersOf(" t1" , " v1" ))
487+ }
488+
422489 private fun MockResponse.Builder.body (
423490 protocol : Protocol ,
424491 body : String ,
0 commit comments