【发布时间】:2021-04-12 02:19:57
【问题描述】:
环境
- MacOS
- JDK 11
- okhttp-4.9.0
我工作的环境对网络带宽非常敏感。
有时,我不需要阅读所有响应正文。响应主体的一部分可能足以决定结果。
我想关闭响应(=响应正文)不阅读正文。
我想做的如下所示
try (Response response = client.newCall(request).execute()) {
assertThat(response.code(), is(200))
// do nothing with the response body
}
但是,当与HTTP1建立连接时,ResponseBody::close最终会调用Http1ExchangeCodec.FixedLengthSource::close。
Http1ExchangeCodec.FixedLengthSource::close
override fun close() {
if (closed) return
if (bytesRemaining != 0L &&
!discard(ExchangeCodec.DISCARD_STREAM_TIMEOUT_MILLIS, MILLISECONDS)) {
connection.noNewExchanges() // Unread bytes remain on the stream.
responseBodyComplete()
}
closed = true
}
然后,discard 方法读取所有响应正文源,如下所示。
Util.kt
fun Source.discard(timeout: Int, timeUnit: TimeUnit): Boolean = try {
this.skipAll(timeout, timeUnit)
} catch (_: IOException) {
false
}
@Throws(IOException::class)
fun Source.skipAll(duration: Int, timeUnit: TimeUnit): Boolean {
val nowNs = System.nanoTime()
val originalDurationNs = if (timeout().hasDeadline()) {
timeout().deadlineNanoTime() - nowNs
} else {
Long.MAX_VALUE
}
timeout().deadlineNanoTime(nowNs + minOf(originalDurationNs, timeUnit.toNanos(duration.toLong())))
return try {
val skipBuffer = Buffer()
while (read(skipBuffer, 8192) != -1L) {
skipBuffer.clear()
}
true // Success! The source has been exhausted.
} catch (_: InterruptedIOException) {
false // We ran out of time before exhausting the source.
} finally {
if (originalDurationNs == Long.MAX_VALUE) {
timeout().clearDeadline()
} else {
timeout().deadlineNanoTime(nowNs + originalDurationNs)
}
}
}
它读取所有正文并清除缓冲区。就我而言,这是对 CPU 时间和网络带宽的浪费。
有什么方法可以直接关闭它吗?
【问题讨论】:
标签: okhttp