Java HTTP 客户端是否处理压缩
Does Java HTTP Client handle compression
我试图在新的 Java HTTP 客户端中找到关于压缩处理的任何提及,但失败了。是否有内置配置来处理例如gzip
或 deflate
压缩?
我希望有一个 BodyHandler
例如像这样:
HttpResponse.BodyHandlers.ofGzipped(HttpResponse.BodyHandlers.ofString())
但我没看到。我也没有在 HttpClient
中看到任何配置。我是不是找错地方了,或者这是故意没有实现并推迟到支持库?
否,gzip/deflate 默认情况下不处理压缩。如果需要,您必须在应用程序代码中实现它——例如通过提供自定义的 BodySubscriber
来处理它。或者 - 您可能想看看那里的一些反应流库是否提供这样的功能,在这种情况下,您可以使用 BodyHandlers.fromSubscriber(Flow.Subscriber<? super List<ByteBuffer>> subscriber)
或 BodyHandlers.ofPublisher()
方法。
我也很惊讶新的 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("");
}
请注意,我没有添加对 "deflate" 类型的支持(因为我目前不需要它,而且我对 "deflate" 的了解越多,听起来越乱) .但我相信您可以通过向上面的开关块添加检查并将 httpResponse.body()
包装在 InflaterInputStream
.
中来轻松支持 "deflate"
您可以对 brotli 使用 Methanol. It has decompressing BodyHandler
implementations, with out-of-the-box support for gzip
& deflate
. There's also a module。
var response = client.send(request, MoreBodyHandlers.decoding(BodyHandlers.ofString()));
请注意,您可以使用任何 BodyHandler
。 MoreBodyHandlers::decoding
让您的处理程序看起来好像响应从未被压缩过!它负责 Content-Encoding
header 和所有
更好的是,您可以使用 Methanol 自己的 HttpClient
,它会在您的请求中添加适当的 Accept-Encoding
后进行透明解压。
var client = Methanol.create();
var request = MutableRequest.GET("https://example.com");
var response = client.send(request, BodyHandlers.ofString()); // The response is transparently decompressed
我试图在新的 Java HTTP 客户端中找到关于压缩处理的任何提及,但失败了。是否有内置配置来处理例如gzip
或 deflate
压缩?
我希望有一个 BodyHandler
例如像这样:
HttpResponse.BodyHandlers.ofGzipped(HttpResponse.BodyHandlers.ofString())
但我没看到。我也没有在 HttpClient
中看到任何配置。我是不是找错地方了,或者这是故意没有实现并推迟到支持库?
否,gzip/deflate 默认情况下不处理压缩。如果需要,您必须在应用程序代码中实现它——例如通过提供自定义的 BodySubscriber
来处理它。或者 - 您可能想看看那里的一些反应流库是否提供这样的功能,在这种情况下,您可以使用 BodyHandlers.fromSubscriber(Flow.Subscriber<? super List<ByteBuffer>> subscriber)
或 BodyHandlers.ofPublisher()
方法。
我也很惊讶新的 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("");
}
请注意,我没有添加对 "deflate" 类型的支持(因为我目前不需要它,而且我对 "deflate" 的了解越多,听起来越乱) .但我相信您可以通过向上面的开关块添加检查并将 httpResponse.body()
包装在 InflaterInputStream
.
您可以对 brotli 使用 Methanol. It has decompressing BodyHandler
implementations, with out-of-the-box support for gzip
& deflate
. There's also a module。
var response = client.send(request, MoreBodyHandlers.decoding(BodyHandlers.ofString()));
请注意,您可以使用任何 BodyHandler
。 MoreBodyHandlers::decoding
让您的处理程序看起来好像响应从未被压缩过!它负责 Content-Encoding
header 和所有
更好的是,您可以使用 Methanol 自己的 HttpClient
,它会在您的请求中添加适当的 Accept-Encoding
后进行透明解压。
var client = Methanol.create();
var request = MutableRequest.GET("https://example.com");
var response = client.send(request, BodyHandlers.ofString()); // The response is transparently decompressed