Как остановить потоковую передачу с помощью org.apache.http.entity.InputStreamEntity - PullRequest
0 голосов
/ 14 февраля 2019

Я хочу реализовать небольшой веб-сервис на основе библиотеки 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);
            }
...