使用空负载解析 HTTP 202 - java.io.EOFException - Android、Retrofit、Gson
Parsing HTTP 202 with an empty payload - java.io.EOFException - Android, Retrofit, Gson
想法:我正尝试在 Android 上使用一个端点。调用它后,端点将 return HTTP 202(空主体,根本没有有效负载)几次,当数据准备好时,它将 return HTTP 200 与数据。
我想要做的是能够解析 202 响应,但由于它没有有效负载,我将检查状态并在需要时再次轮询,一旦我得到 200 OK,我将解析和使用数据。
我解析和使用 200 OK 响应的部分工作正常,但解析 202 响应不起作用,我收到异常(见下文)。
我知道有几种方法可以解决这个问题:
- 使用 Void 作为 return 类型,
- 使用 ResponseBody 作为 return 类型,
- 使用 Converter.Factory.
我为此创建了一个转换器 class:
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.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$responseBodyConverter.convert(NullOnEmptyConverterFactory.kt:22)
at data.network.util.NullOnEmptyConverterFactoryKt$nullOnEmptyConverterFactory$responseBodyConverter.convert(NullOnEmptyConverterFactory.kt:17)
at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225)
at retrofit2.OkHttpCall.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)
找出导致此问题的原因:none 上述库、Retrofit、GSon 有问题。如果您跟踪堆栈跟踪,您会发现它指向一个问题,即响应不符合 gzip 文件格式。
如果您使用的是 gzip 文件格式,OkHttp 库期望响应有 10 个字节 header。如果响应没有它,库会抛出异常。
在这种情况下 API 有问题。
The ticket 帮助我弄清楚了问题。
想法:我正尝试在 Android 上使用一个端点。调用它后,端点将 return HTTP 202(空主体,根本没有有效负载)几次,当数据准备好时,它将 return HTTP 200 与数据。
我想要做的是能够解析 202 响应,但由于它没有有效负载,我将检查状态并在需要时再次轮询,一旦我得到 200 OK,我将解析和使用数据。
我解析和使用 200 OK 响应的部分工作正常,但解析 202 响应不起作用,我收到异常(见下文)。
我知道有几种方法可以解决这个问题:
- 使用 Void 作为 return 类型,
- 使用 ResponseBody 作为 return 类型,
- 使用 Converter.Factory.
我为此创建了一个转换器 class:
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.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$responseBodyConverter.convert(NullOnEmptyConverterFactory.kt:22)
at data.network.util.NullOnEmptyConverterFactoryKt$nullOnEmptyConverterFactory$responseBodyConverter.convert(NullOnEmptyConverterFactory.kt:17)
at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225)
at retrofit2.OkHttpCall.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)
找出导致此问题的原因:none 上述库、Retrofit、GSon 有问题。如果您跟踪堆栈跟踪,您会发现它指向一个问题,即响应不符合 gzip 文件格式。
如果您使用的是 gzip 文件格式,OkHttp 库期望响应有 10 个字节 header。如果响应没有它,库会抛出异常。
在这种情况下 API 有问题。
The ticket 帮助我弄清楚了问题。