包装BodySubscriber< InputStream>在GZIPInputStream中导致挂起 [英] Wrapping BodySubscriber<InputStream> in GZIPInputStream leads to hang
问题描述
我正在使用新的java.net.http
类来处理异步HTTP请求和响应交换,并且我试图找到一种方法使BodySubscriber处理不同的编码类型,例如gzip.
I'm using the new java.net.http
classes to handle asynchronous HTTP request+response exchanges, and I'm trying to find a way to have the BodySubscriber handle different encoding types such as gzip.
但是,映射BodySubsriber<InputStream>
以便基础流被GZIPInputStream
包装(当在响应标头中找到"Content-Encoding:gzip"时)会导致挂起.没有例外,只是完全停止了活动.
However, mapping a BodySubsriber<InputStream>
so that the underlying stream is wrapped by a GZIPInputStream
(when "Content-Encoding: gzip" is found in the response header) leads to a hang. No exceptions, just a total cessation of activity.
映射BodySubscriber
的代码如下:
private HttpResponse.BodySubscriber<InputStream> gzippedBodySubscriber(
HttpResponse.ResponseInfo responseInfo) {
return HttpResponse.BodySubscribers.mapping(
HttpResponse.BodySubscribers.ofInputStream(),
this::decodeGzipStream);
}
private InputStream decodeGzipStream(InputStream gzippedStream) {
System.out.println("Entered decodeGzipStream method.");
try {
InputStream decodedStream = new GZIPInputStream(gzippedStream);
System.out.println(
"Created GZIPInputStream to handle response body stream.");
return decodedStream;
} catch (IOException ex) {
System.out.println("IOException occurred while trying to create GZIPInputStream.");
throw new UncheckedIOException(ex);
}
}
接收到具有"gzip"编码的HTTP响应会导致控制台仅显示以下内容:
Receiving an HTTP response which has "gzip" encoding leads to the console showing just this:
输入了EncodedBodyHandler.apply方法.
输入了encodeGzipStream方法.
Entered EncodedBodyHandler.apply method.
Entered decodeGzipStream method.
什么也看不到,因此永远不会执行对GZIPInputStream
构造函数的调用之后的那一行.
Nothing more is seen, so the line after the call to the GZIPInputStream
constructor is never executed.
有人知道为什么这种将InputStream
从BodySubscriber<InputStream>
包裹在GZIPInputStream
中的尝试挂起的原因吗?
Does anyone know why this attempt to wrap the InputStream
from a BodySubscriber<InputStream>
in a GZIPInputStream
is hanging?
注意:未编码(原始文本)HTTP响应正文的等效方法仅包含对BodySubscribers.ofInputStream()
的调用,而没有映射,这使得可以毫无问题地接收和显示响应.
Note: the equivalent method for unencoded (raw text) HTTP response bodies contains simply a call to BodySubscribers.ofInputStream()
with no mapping, and this allows the response to be received and displayed without problem.
推荐答案
这确实是一个错误.我已经记录了 JDK-8217264 .我可以建议两个解决方法:
This is indeed a bug. I have logged JDK-8217264. I can suggest two work-arounds:
请勿使用BodySubscribers.mapping
-在获取HttpResponse的正文之后,将InputStream
转换为GZIPInputStream
:
Do not use BodySubscribers.mapping
- but transform the InputStream
into a GZIPInputStream
after getting the HttpResponse's body:
GZIPInputStream gzin = new GZIPInputStream(resp.getBody());
解决方法二
让映射函数返回Supplier<InputStream>
,注意不要在调用Supplier::get
之前创建GZIPInputStream
Workaround two
Have the mapping function return a Supplier<InputStream>
instead, taking care not to create the GZIPInputStream
until Supplier::get
is called
static final class ISS implements Supplier<InputStream> {
final InputStream in;
GZIPInputStream gz;
ISS(InputStream in) {
this.in = in;
}
public synchronized InputStream get() {
if (gz == null) {
try {
gz = new GZIPInputStream(in);
} catch (IOException t) {
throw new UncheckedIOException(t);
}
}
return gz;
}
}
这篇关于包装BodySubscriber< InputStream>在GZIPInputStream中导致挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!