Как удалить заголовок Content-length из ответа HTTP, сгенерированного на простом сервере?

Ниже приведен пример моего HTTP-сервера. Мне нужно удалить заголовок «Content-length:», сгенерированный в ответе. Я пробовал много подходов и не преуспел. Есть ли способ удалить длину содержимого из ответа сервера?

public class SimpleHttpServer {

    public static void main(String[] args) throws Exception {
        HttpServer server = HttpServer.create(new InetSocketAddress(9000), 0);
        server.createContext("/test", new TestHandler());
        server.setExecutor(null); // creates a default executor
        server.start();
    }

    static class TestHandler implements HttpHandler {
        public void handle(HttpExchange t) throws IOException {
            byte[] response = "Welcome to Test Server..!!\n".getBytes();
            t.sendResponseHeaders(200, response.length);
            OutputStream os = t.getResponseBody();
            os.write(response);
            os.close();
        }
    }
}

person Methma    schedule 16.03.2018    source источник
comment
Какова цель удаления этого поля заголовка. Потому что, исходя из этого, только клиенты могут читать контент из вашего потока? это объем данных, отправленных вашим сервером.   -  person Hakuna Matata    schedule 16.03.2018
comment
Мне нужно сгенерировать ответ для целей тестирования   -  person Methma    schedule 16.03.2018
comment
Это должно быть так. Без длины содержимого в ответе. › POST / HTTP/1.1 › User-Agent: curl/7.29.0 › Accept: / › Content-Type: application/json › Content-Length: 115 › полностью отправлено: 115 из 115 байтов ‹ HTTP/1.1 200 ХОРОШО   -  person Methma    schedule 16.03.2018
comment
stackoverflow.com/questions/38176262/   -  person Hakuna Matata    schedule 16.03.2018
comment
@MariaSekar связанный ответ предназначен для программы Spring - в этом примере здесь используется основной класс JDK HttpExchange   -  person hovanessyan    schedule 16.03.2018


Ответы (3)


Обходной путь может быть:

t.sendResponseHeaders(200, 0);

Обратите внимание, что

Если параметр длины ответа равен 0, то используется кодирование передачи по частям, и может быть отправлено произвольное количество данных.

person Andrew Tobilko    schedule 16.03.2018
comment
Проблема в том, что мне нужен ответ, который содержит только код состояния. Transfer-encoding: chunked быть не должно. - person Methma; 16.03.2018
comment
@MPS, почему тебе не нужны заголовки в ответе? это сбивает меня с толку. чего вы пытаетесь достичь? - person Andrew Tobilko; 16.03.2018

Вы должны отправить 0 в длине ответа, как указано в javadoc для sendResponseHeaders:

responseLength — если > 0, указывает фиксированную длину тела ответа, и точное количество байтов должно быть записано в поток, полученный от getResponseBody(), иначе, если равно 0, то используется кодирование по частям, и произвольное количество байтов может быть написано. если ‹= -1, то длина тела ответа не указывается и тело ответа не может быть записано.

t.sendResponseHeaders(200, 0);

Это означает, что он не будет отправлять в браузер длину ответа, а также не будет отправлять заголовок Content-Length, вместо этого он отправляет ответ как фрагментированное кодирование, которое, как вы указываете, предназначено для теста, может быть в порядке.

Кодирование групповой передачи — это механизм потоковой передачи данных, доступный в версии 1.1 протокола передачи гипертекста (HTTP). При групповом кодировании передачи поток данных делится на серию неперекрывающихся «кусков». Фрагменты отправляются и принимаются независимо друг от друга. Ни отправителю, ни получателю в любой момент времени не требуется никаких сведений о потоке данных за пределами обрабатываемого в данный момент фрагмента.

person Cesar Loachamin    schedule 16.03.2018
comment
Поскольку он добавляет Transfer-encoding: chunked в ответ, есть ли способ удалить это тоже. Мне нужно получить ответ, который содержит только коды состояния. - person Methma; 16.03.2018
comment
@MPS не понимает, чего вы пытаетесь достичь, возможно, это связано с тем, как вы вызываете URL-адрес, если вы используете curl, который вы можете вызвать с помощью curl -I http://localhost:9000/test, чтобы попытаться получить только код состояния. - person Cesar Loachamin; 16.03.2018

Content-Length header is always set, unless it's 0 or -1;

Если вы проверите источник HttpExchange sendResponseHeaders() вы найдете этот фрагмент, который содержит соответствующую логику:

Как видите, когда contentLen == 0 и !http10, этот заголовок добавляется "Transfer-encoding", "chunked".

Вы можете использовать getResponseHeaders(), который возвращает изменяемую карту заголовков, чтобы установить любые заголовки ответов, кроме "Date" и "Transfer-encoding". Прочтите связанный исходный код, чтобы понять, почему.

207        if (contentLen == 0) {
208            if (http10) {
209                o.setWrappedStream (new UndefLengthOutputStream (this, ros));
210                close = true;
211            } else {
212                rspHdrs.set ("Transfer-encoding", "chunked");
213                o.setWrappedStream (new ChunkedOutputStream (this, ros));
214            }
215        } else {
216            if (contentLen == -1) {
217                noContentToSend = true;
218                contentLen = 0;
219            }
220            /* content len might already be set, eg to implement HEAD resp */
221            if (rspHdrs.getFirst ("Content-length") == null) {
222                rspHdrs.set ("Content-length", Long.toString(contentLen));
223            }
224            o.setWrappedStream (new FixedLengthOutputStream (this, ros, contentLen));
225        }

Если вам нужна большая гибкость, вам нужно использовать другие конструкции, а не простые HttpExchange. Классы поставляются с ограничениями, поведением по умолчанию и построены определенным образом.

person hovanessyan    schedule 16.03.2018
comment
В методе sendResponseHeaders он устанавливает два заголовка Date и «Content-Lenght» или «Transfer-Encoding» в зависимости от параметра contentLen и записывает эти заголовки в строку 226 выходного потока write (rspHdrs, tmpout);, поэтому даже вы можете изменить карту и удалить заголовки. ответ будет иметь те, потому что они были отправлены в выходной поток, я попытался очистить карту и не удалил заголовки - person Cesar Loachamin; 16.03.2018