Обертывание BodySubscriber<InputStream> в GZIPInputStream приводит к зависанию
Я использую новый java.net.http
классы для обработки асинхронного обмена HTTP-запросами + ответами, и я пытаюсь найти способ, чтобы BodySubscriber обрабатывал различные типы кодирования, такие как gzip.
Тем не менее, картирование BodySubsriber<InputStream>
так что основной поток обернут GZIPInputStream
(когда в заголовке ответа найдено "Content-Encoding: gzip"), это приводит к зависанию. Без исключений, просто полное прекращение деятельности.
Код, который отображает 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);
}
}
Получение HTTP-ответа с кодировкой "gzip" приводит к выводу на консоль только этого:
Введен метод EncodedBodyHandler.apply.
Введен метод decodeGzipStream.
Больше ничего не видно, поэтому линия после звонка на GZIPInputStream
Конструктор никогда не выполняется.
Кто-нибудь знает, почему эта попытка обернуть InputStream
из BodySubscriber<InputStream>
в GZIPInputStream
висит?
Примечание. Эквивалентный метод для тел без ответа (необработанного текста) HTTP-ответа содержит просто вызов BodySubscribers.ofInputStream()
без сопоставления, и это позволяет ответу быть принятым и отображенным без проблем.
0 ответов
Это действительно ошибка. Я вошел в систему 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;
}
}
Столкнулся с точно такой же проблемой. Я попробовал пример в Javadoc BodySubscribers.mapping
метод. Такое же поведение, приложение зависает без ошибок.
Может быть ошибка, потому что это официальный пример из Javadoc.
public static <W> BodySubscriber<W> asJSON(Class<W> targetType) {
BodySubscriber<InputStream> upstream = BodySubscribers.ofInputStream();
BodySubscriber<W> downstream = BodySubscribers.mapping(
upstream,
(InputStream is) -> {
try (InputStream stream = is) {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(stream, targetType);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
return downstream;
} }