Я хочу реализовать небольшой веб-сервис на основе библиотеки Apache httpcomponents.Требование заключается в том, что служба поддерживает ответы на длинные запросы.Поэтому я начинаю отвечать с помощью InputStreamEntity вместо строки и возвращаю данные после того, как происходит событие.Приведенный ниже отрывок имитирует это с помощью простого «Thread.sleep (..)».
Как указано в документации к библиотеке apache, я предоставляю Content-Length со значением -1 из-за неизвестной длины при возврате заголовков HTTP(содержимое зависит от информации о состоянии, проверенной при возникновении события, и не является статической строкой, как в примере ниже).
Я не уверен, как прекратить потоковую передачу после завершения вывода.На мой взгляд, я должен как-то закрыть потоки.Документация библиотеки apache гласит, что «receiveContent» устарел, и после HttpEntity.getContent () поток должен быть закрыт с помощью InputStream.close ().(https://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/entity/InputStreamEntity.html)
Но когда я закрываю основной входной поток возвращенного InputStreamEntity, клиент утверждает, что поток был закрыт до того, как клиент смог получить данные потока.
В моемслучай, это
java.io.IOException: Pipe closed
at java.io.PipedInputStream.read(PipedInputStream.java:307)
at java.io.PipedInputStream.read(PipedInputStream.java:377)
at java.io.InputStream.read(InputStream.java:101)
at org.apache.http.entity.InputStreamEntity.writeTo(InputStreamEntity.java:133)
at org.apache.http.impl.DefaultBHttpServerConnection.sendResponseEntity(DefaultBHttpServerConnection.java:166)
at org.apache.http.protocol.HttpService.handleRequest(HttpService.java:363)
at org.apache.http.impl.bootstrap.Worker.run(Worker.java:66)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Как реализовать правильный сервер, который закрывает свой поток?
Моя реализация сервера:
public HttpResultMetaData handleRequest(IncomingHttpRequest request, URI requestURI, HttpResponse response,
HttpServer httpTransmitter) throws IOException {
if (request.getURI().getPath().startsWith("/longpolling")) {
String query = request.getURI().getQuery();
java.util.Map<String, String> args = new HashMap<>();
try {
String[] kvpairs = query.split("&");
for (String kvpair:kvpairs) {
String[] kvPairSplitted = kvpair.split("=");
String key = kvPairSplitted[0];
String value = kvPairSplitted[1];
args.put(key, value);
}
String responseTime = args.get("respondAfter");
PipedOutputStream pos = new PipedOutputStream();
PipedInputStream is = new PipedInputStream(pos);
InputStreamEntity ise = new InputStreamEntity(is);
response.setEntity(ise);
//typically when an event occured, the event handler writes to an OutputStream - this is why we are using PipedOutputStream... Instead of the event, we simplified here with THread.sleep(..) for a unit test.
Thread.sleep(Long.parseLong(responseTime));
pos.write("<html><body><p>Hello World!</p></body></html>".getBytes());
response.setStatusCode(200);
ise.getContent().close();
}
catch (Exception e) {
response.setStatusCode(500);
}
} else {
response.setStatusCode(404);
}