Skip to content

Crash reading trailers in Retrofit Call #8902

@swankjesse

Description

@swankjesse

We’ve observed this crash with Retrofit 3 and OkHttp 5.0.0:

java.lang.IllegalStateException: Cannot read raw response body of a converted body.
	at retrofit2.OkHttpCall$NoContentResponseBody.source(OkHttpCall.java:300)
	at okhttp3.Response.trailers(Response.kt:195)
	at misk.client.ClientMetricsInterceptorNoSummaryTest.responseCodes(ClientMetricsInterceptorNoSummaryTest.kt:107)
	at java.lang.reflect.Method.invoke(Method.java:568)

I believe the core problem is this recently-changed function in OkHttp 5:

  @Throws(IOException::class)
  fun trailers(): Headers {
    val source = body.source()
    if (source.isOpen) {
      source.skipAll()
    }
    return trailersSource.get()
  }

I think it’s fine that we exhaust the response body before attempting to read the trailers. But I also believe that behavior should be within the implementation of trailersSource and not in the code that calls that function.

Ie. we should change all of our built-in TrailersSource.get implementations to do this:

  override fun get(): Headers {
    val source = bodySource // Somehow!
    if (source.isOpen) {
      source.skipAll()
    }
  }

That way a custom ResponseBody won’t interact awkwardly with Response.

An alternative solution would be a custom function on ResponseBody to do this work. That way the custom Retrofit ResponseBody could override that function.

Metadata

Metadata

Assignees

Labels

bugBug in existing code

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions