java - 在 GZIPInputStream 中包装 BodySubscriber<InputStream> 导致挂起

标签 java gzipinputstream java-http-client

我正在使用新的 java.net.http处理异步 HTTP 请求+响应交换的类,我正在尝试找到一种方法让 BodySubscriber 处理不同的编码类型,例如 gzip。

然而,映射一个BodySubsriber<InputStream>以便底层流被 GZIPInputStream 包裹(当在响应 header 中找到“Content-Encoding: gzip”时)导致挂起。没有异常(exception),只是完全停止 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 响应会导致控制台显示如下:

Entered EncodedBodyHandler.apply method.
Entered decodeGzipStream method.

没有看到更多内容,所以调用 GZIPInputStream 之后的行永远不会执行构造函数。

有谁知道为什么要尝试包装 InputStream来自BodySubscriber<InputStream>GZIPInputStream挂了吗?

注意:未编码(原始文本)HTTP 响应主体的等效方法仅包含对 BodySubscribers.ofInputStream() 的调用没有映射,这允许毫无问题地接收和显示响应。

最佳答案

编辑:JDK-8217264自 JDK13 以来已修复


这确实是一个错误。我已经登录JDK-8217264 .我可以建议两种解决方法:

解决方法一

不要使用 BodySubscribers.mapping - 但转换 InputStream进入GZIPInputStream获取 HttpResponse 的主体后:

GZIPInputStream gzin = new GZIPInputStream(resp.getBody());

解决方法二

让映射函数返回 Supplier<InputStream>相反,注意不要创建 GZIPInputStream直到 Supplier::get被称为

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;
    }
}

关于java - 在 GZIPInputStream 中包装 BodySubscriber<InputStream> 导致挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53379087/

相关文章:

java - 如何读取内容编码为 : gzip 的压缩 HTML 页面

java - logback:AsyncAppender 比同步 FileAppender 花费更多时间

java - 是否使 Reentrant Lock 静态并使其成为互斥体?

java - 这个通用 Guice 绑定(bind)方法的 TypeLiteral 等价物有什么问题?

java - RPI 上的 JDK8 安装路径不起作用

java - 解压缩 HTTPInputStream 时 GZIPInputStream 过早关闭

java - 通过 GZIP 流读写对象?

java - 我正在尝试通过实现异步任务在 android (java) 中流式传输 chatgpt api 的响应(逐字),但我收到错误

java - 不能在 java.net.http.HttpClient 上发出多个请求,否则将收到 : javax.net.ssl.SSLHandshakeException

Java HttpRequest 超时意外抛出 HttpConnectTimeoutException