首页 > 解决方案 > 使用空负载解析 HTTP 202 - java.io.EOFException - Android、Retrofit、Gson

问题描述

想法:我正在尝试在 Android 上使用一个端点。调用它后,端点将返回 HTTP 202(空正文,根本没有有效负载)几次,当数据准备好时,它将返回 HTTP 200 和数据。

我想要做的是能够解析 202 响应,但由于它没有有效负载,我将检查状态并在需要时再次轮询,一旦我得到 200 OK,我将解析并使用数据.

我解析和使用 200 OK 响应的部分正在工作,但解析 202 响应不起作用,我得到了异常(见下文)。

我知道有几种方法可以解决这个问题:

我为此创建了一个转换器类:

internal val nullOnEmptyConverterFactory = object : Converter.Factory() {
    fun converterFactory() = this
    override fun responseBodyConverter(
        type: Type,
        annotations: Array<out Annotation>,
        retrofit: Retrofit
    ) = object : Converter<ResponseBody, Any?> {
        val nextResponseBodyConverter =
            retrofit.nextResponseBodyConverter<Any?>(converterFactory(), type, annotations)

        override fun convert(value: ResponseBody) =
            if (value.contentLength() != 0L) nextResponseBodyConverter.convert(value) else null
    }
}

这就是我使用它的方式:

return Retrofit.Builder()
            .client(client)
            .addConverterFactory(nullOnEmptyConverterFactory)
            .addConverterFactory(ScalarsConverterFactory.create()) // used for jsonp
            .addConverterFactory(GsonConverterFactory.create(factory))
            .addCallAdapterFactory(CoroutineCallAdapterFactory())
            .baseUrl(ApiService.getBaseUrl())
            .build()

这是我得到的错误:

error: java.io.EOFException
        at okio.RealBufferedSource.require(RealBufferedSource.kt:55)
        at okio.GzipSource.consumeHeader(GzipSource.kt:104)
        at okio.GzipSource.read(GzipSource.kt:62)
        at okio.RealBufferedSource.read(RealBufferedSource.kt:41)
        at okio.ForwardingSource.read(ForwardingSource.kt:29)
        at retrofit2.OkHttpCall$ExceptionCatchingResponseBody$1.read(OkHttpCall.java:288)
        at okio.RealBufferedSource.select(RealBufferedSource.kt:93)
        at okhttp3.internal.Util.readBomAsCharset(Util.kt:256)
        at okhttp3.ResponseBody$BomAwareReader.read(ResponseBody.kt:208)
        at com.google.gson.stream.JsonReader.fillBuffer(JsonReader.java:1295)
        at com.google.gson.stream.JsonReader.nextNonWhitespace(JsonReader.java:1333)
        at com.google.gson.stream.JsonReader.consumeNonExecutePrefix(JsonReader.java:1576)
        at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:534)
        at com.google.gson.stream.JsonReader.peek(JsonReader.java:425)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:207)
        at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:39)
        at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27)
        at data.network.util.NullOnEmptyConverterFactoryKt$nullOnEmptyConverterFactory$1$responseBodyConverter$1.convert(NullOnEmptyConverterFactory.kt:22)
        at data.network.util.NullOnEmptyConverterFactoryKt$nullOnEmptyConverterFactory$1$responseBodyConverter$1.convert(NullOnEmptyConverterFactory.kt:17)
        at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225)
        at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:121)
        at okhttp3.RealCall$AsyncCall.run(RealCall.kt:138)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
        at java.lang.Thread.run(Thread.java:764)

标签: androidretrofitretrofit2

解决方案


找出造成这种情况的原因:上面提到的库、Retrofit、GSon 都没有问题。如果您跟踪堆栈跟踪,您会发现它指向一个问题,即响应不符合 gzip 文件格式。

如果您使用 gzip 文件格式,OkHttp 库期望响应具有 10 字节的标头。如果响应没有它,则库会引发异常。

在这种情况下,API 有问题。

帮助我弄清楚问题的票。


推荐阅读