包装BodySubscriber< InputStream>在GZIPInputStream中导致挂起 [英] Wrapping BodySubscriber<InputStream> in GZIPInputStream leads to hang

查看:103
本文介绍了包装BodySubscriber< InputStream>在GZIPInputStream中导致挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用新的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.

有人知道为什么这种将InputStreamBodySubscriber<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&lt; InputStream&gt;在GZIPInputStream中导致挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆