我试图在新的Java HTTP Client中找到有关压缩处理的任何内容,但均失败了。是否有内置配置可以处理例如gzip
或deflate
压缩?
我希望例如使用BodyHandler
像这样的东西:
HttpResponse.BodyHandlers.ofGzipped(HttpResponse.BodyHandlers.ofString())
但是我没看到。我也没有在HttpClient
中看到任何配置。我在找错地方了吗?还是故意将其实施并推迟以支持图书馆?
答案 0 :(得分:2)
令我感到惊讶的是,新的java.net.http
框架无法自动处理此问题,但是以下内容对我而言可以处理以InputStream
接收且未压缩或压缩的HTTP响应gzip:
public static InputStream getDecodedInputStream(
HttpResponse<InputStream> httpResponse) {
String encoding = determineContentEncoding(httpResponse);
try {
switch (encoding) {
case "":
return httpResponse.body();
case "gzip":
return new GZIPInputStream(httpResponse.body());
default:
throw new UnsupportedOperationException(
"Unexpected Content-Encoding: " + encoding);
}
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
public static String determineContentEncoding(
HttpResponse<?> httpResponse) {
return httpResponse.headers().firstValue("Content-Encoding").orElse("");
}
请注意,我还没有添加对“放气”类型的支持(因为我目前不需要它,而且我对“放气”的了解越多,听起来就越混乱了)。但我相信您可以通过在上述开关块上添加检查并将httpResponse.body()
包裹在InflaterInputStream
中来轻松支持“放气”。
答案 1 :(得分:1)
否,默认情况下不处理gzip / deflate压缩。如果需要,您必须在应用程序代码中实现它-例如通过提供自定义的BodySubscriber
来处理它。或者,您可能想看看那里的某些反应式流库是否提供了这样的功能,在这种情况下,您可能可以使用BodyHandlers.fromSubscriber(Flow.Subscriber<? super List<ByteBuffer>> subscriber)
或{{1}中的一个将其插入}方法。
答案 2 :(得分:1)
这个问题有点老了,但是我最近发布了一个可解决此问题的库。该库称为Methanol,可在Maven上使用。
您可以使用它来解码响应,如下所示:
HttpResponse<String> response = client.send(request, MoreBodyHandlers.decoding(BodyHandlers.ofString()));
您还可以使用所需的任何BodyHandler
。 MoreBodyHandlers::decoding
使您的处理程序看起来好像从未压缩过响应!它负责Content-Encoding
标头和所有标头。默认情况下支持Gzip和deflate,而brotli也有module。
更好的是,您可以使用自定义HttpClient
进行透明压缩(无需添加Accept-Encoding
):
Methanol client = Methanol.newBuilder()
.autoAcceptEncoding(true) // note that true is the default
.build();
HttpRequest request = ...
HttpResponse<String> response = client.send(request, BodyHandlers.ofString()); // response is compressed transparently