2

Following is my sample HTTP server. I need to remove the 'Content-length:' header generated at the response. I have tried many approaches and not succeded. Is there any way to remove the content-length from server response?

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();
        }
    }
}
Methma
  • 152
  • 3
  • 13
  • What is the purpose of removing this header field. Because based on this only clients can read the content from your stream? that is amount of data your server sent . – Hakuna Matata Mar 16 '18 at 09:40
  • I need to generate a response for testing purpose – Methma Mar 16 '18 at 09:40
  • It should be like this. Without content length in the response. > POST / HTTP/1.1 > User-Agent: curl/7.29.0 > Accept: / > Content-Type: application/json > Content-Length: 115 > upload completely sent off: 115 out of 115 bytes < HTTP/1.1 200 OK – Methma Mar 16 '18 at 09:44
  • https://stackoverflow.com/questions/38176262/remove-content-length-and-transfer-encoding-headers-from-spring-servlet-http-res – Hakuna Matata Mar 16 '18 at 09:45
  • @MariaSekar the linked answer is for a Spring program - this example here uses core JDK class HttpExchange – hovanessyan Mar 16 '18 at 10:04

3 Answers3

1

A workaround could be:

t.sendResponseHeaders(200, 0);

Note that

If the response length parameter is 0, then chunked transfer encoding is used and an arbitrary amount of data may be sent.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • The problem is I need a response which only contain status code. Transfer-encoding: chunked should not be there. – Methma Mar 16 '18 at 09:50
  • @MPS, why do you need no headers in the response? it's confusing to me. what are you trying to achieve? – Andrew Tobilko Mar 16 '18 at 10:08
0

You have to send 0 in the response length, as specified in the javadoc for the sendResponseHeaders:

responseLength - if > 0, specifies a fixed response body length and that exact number of bytes must be written to the stream acquired from getResponseBody(), or else if equal to 0, then chunked encoding is used, and an arbitrary number of bytes may be written. if <= -1, then no response body length is specified and no response body may be written.

t.sendResponseHeaders(200, 0);

This means it would not send to the browser the length of the response and also not send the Content-Length header instead it sends the response as chunked encoding that as you indicate this is for a test it could be fine.

Chunked transfer encoding is a streaming data transfer mechanism available in version 1.1 of the Hypertext Transfer Protocol (HTTP). In chunked transfer encoding, the data stream is divided into a series of non-overlapping "chunks". The chunks are sent out and received independently of one another. No knowledge of the data stream outside the currently-being-processed chunk is necessary for both the sender and the receiver at any given time.

Cesar Loachamin
  • 2,740
  • 4
  • 25
  • 33
  • Since it's adding `Transfer-encoding: chunked` in response, is there any way to remove that too. I need to get a response which only contain the status codes. – Methma Mar 16 '18 at 09:53
  • @MPS don't understand what you're trying to achieve, maybe is in the way you call the url if you use curl you could call with `curl -I http://localhost:9000/test` to try to only get the status code – Cesar Loachamin Mar 16 '18 at 10:17
0
Content-Length header is always set, unless it's 0 or -1;

If you check the source of HttpExchange sendResponseHeaders() you will find this snippet, which contains the relevant logic:

As you can see when contentLen == 0 and !http10, this header is added "Transfer-encoding", "chunked".

You can use getResponseHeaders(), which returns a mutable map of headers, to set any response headers, except "Date" and "Transfer-encoding" - read the linked source code to see why.

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        }

If you need more flexibility, you need to use other constructs, rather than plain HttpExchange. Classes come with constraints, default behavior and built in a certain way.

hovanessyan
  • 30,580
  • 6
  • 55
  • 83
  • In the method `sendResponseHeaders` it set two headers `Date` and 'Content-Lenght` or 'Transfer-Encoding` depending on the `contentLen` parameter and it writes these headers to the output stream `write (rspHdrs, tmpout);` line 226, so even you can mutate the map and remove the headers the response will have those because they were sent to the output stream, I tried clearing the map and didn't remove the headers – Cesar Loachamin Mar 16 '18 at 10:24