Estoy usando las nuevas java.net.http
clases para manejar los intercambios petición + respuesta HTTP asíncronas, y estoy tratando de encontrar una manera de tener el mango BodySubscriber diferentes tipos de codificación tales como gzip.
Sin embargo, la asignación de un BodySubsriber<InputStream>
modo que la corriente subyacente es envuelto por un GZIPInputStream
(cuando "-Content Encoding: gzip" se encuentra en la cabecera de respuesta) conduce a un bloqueo. No hay excepciones, sólo un cese total de la actividad.
El código que mapea los BodySubscriber
ve así:
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);
}
}
Recibir una respuesta HTTP que tiene "gzip" que codifican conduce a la consola que muestra esto:
Método EncodedBodyHandler.apply introducido.
Método decodeGzipStream introducido.
Nada más se ve, por lo que la línea después de la llamada al GZIPInputStream
constructor nunca se ejecuta.
¿Alguien sabe por qué este intento de envolver el InputStream
de una BodySubscriber<InputStream>
en una GZIPInputStream
está colgando?
Nota: El método equivalente para codificar (texto sin formato) HTTP cuerpos de respuesta contiene una simple llamada a BodySubscribers.ofInputStream()
con ninguna asignación, y esto permite que la respuesta a recibir y visualizar sin problemas.
Este es de hecho un error. He conectado JDK-8217264 . Puedo sugerir dos soluciones temporales:
Solución alternativa uno
No utilice BodySubscribers.mapping
- pero transformar la InputStream
en una GZIPInputStream
después de conseguir el cuerpo de HttpResponse:
GZIPInputStream gzin = new GZIPInputStream(resp.getBody());
Solución alternativa de dos
Tener la correlación de funciones de retorno una Supplier<InputStream>
vez, teniendo cuidado de no crear el GZIPInputStream
hasta que Supplier::get
se llama
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;
}
}