Мой HttpServer отвечает на запросы http get с некоторым содержимым. Этот контент относительно небольшой, но его получение может занять некоторое время. Как я понимаю реактивный стек, я должен передать Mono или Flux HttpServerResponse, и мой сервис должен выполнять фоновую блокировку ввода-вывода в некоторых потоках, отличных от рабочих потоков Netty. Например:
class SomeService {
private static final ExecutorService EXECUTOR = ...
public Mono<String> load() {
CompletableFuture<String> future = new CompletableFuture<>();
EXECUTOR.submit(() -> loadContent(future));
Mono<String> ret = Mono.fromFuture(future).onErrorResume(Mono::error);
return ret;
}
private void loadContent(CompletableFuture<String> cf) {
String s = doBlockingLoadFromSomewhere();
cf.complete(s);
}
}
class Server {
private SomeService loader;
void activate() {
InetSocketAddress address = getAddressSomehow();
server = HttpServer.create()
.host(address.getHostString())
.port(address.getPort())
.route(routes -> routes.get("/path", this::handlePath))
.bindNow();
}
private Publisher<Void> handlePath(HttpServerRequest request, HttpServerResponse response)
{
Mono<String> contentMono = loader.load();
return response.status(OK).sendString(contentMono);
}
}
Это прекрасно работает с одним исключением. Я должен отправить заголовок CONTENT_LENGTH, но реактор-нетто не устанавливает его автоматически, поэтому я должен сделать это сам.
У меня есть очевидный способ блокировать и подсчитывать длину контента, когда он доступен, но он блокирует поток Netty.
Я пытался составить весь NettyOutbound в Mono, но это полностью теряет контент, возможно, я сделал что-то не так.
private Publisher<Void> handlePath(HttpServerRequest request, HttpServerResponse response)
{
Mono<String> contentMono = loader.load();
Mono<NettyOutbound> handling = contentMono.flatMap(str -> {
NettyOutbound r = response.status(OK)
.header(CONTENT_LENGTH, Long.valueOf(str.length()).toString())
.sendString(Mono.just(str), UTF_8);
return Mono.just(r);
});
return handling.then();
}
Пожалуйста, скажите мне, есть ли канонический способ отправки CONTENT_LENGTH (и вообще составление заголовков ответа на контент, который Mono готов) без блокировки рабочего потока Netty?
Другими словами. Все образцы документации составляют заголовки ответа сразу и составляют контент в тот момент, когда он готов. Как я могу составить заголовки и контент ответа в тот момент, когда контент готов?
PS
Я использую io.projectreactor: реактор-ядро: 3.2.5.RELEASE и io.projectreactor.netty: реактор-нетто: 0.8.4.RELEASE