Setting Content Type in Java HttpServer response
Asked Answered
D

3

6

I have a java echo httpserver up.

It works with test sites, but the client code I'm working with fails to get the data.

The server works perfectly with https://www.hurl.it/

The client works perfectly with https://requestb.in/ and http://httpbin.org/post

When combining the two I get a response with a status code of 200, but no metadata / body content shows up in the client even though it's being sent.

My only guess is because the content type isn't included, the client might be picky about that.

How can i specify the content type in my response?

(A note, the client sends a single string to the server with a POST as a parameter along with some header info. This code is currently setup to only return the body content/parameter.)

Any ideas appreciated!

import static java.net.HttpURLConnection.HTTP_OK;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.util.List;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

/**
* Echo the body of an HTTP request back as the HTTP response. This is merely
* a simple exercise of the Secret Sun Web Server. As configured, the URL to
* access it is http://localhost:8000/echo.
* 
* @author Andrew Cowie
*/
public final class Test
{
public static void main(String[] args) throws IOException {
    final InetSocketAddress addr;
    final HttpServer server;

    addr = new InetSocketAddress(8000);

    server = HttpServer.create(addr, 10);
    server.createContext("/echo", new EchoHandler());
    server.start();
}
}

class EchoHandler implements HttpHandler
{
public void handle(HttpExchange t) throws IOException {
    final InputStream is;
    final OutputStream os;
    StringBuilder buf;
    int b;
    final String request, response;

    buf = new StringBuilder();

    /*
     * Get the request body and decode it. Regardless of what you are
     * actually doing, it is apparently considered correct form to consume
     * all the bytes from the InputStream. If you don't, closing the
     * OutputStream will cause that to occur
     */

    is = t.getRequestBody();

    while ((b = is.read()) != -1) {
        buf.append((char) b);
    }

    is.close();

    if (buf.length() > 0) {
        request = URLDecoder.decode(buf.toString(), "UTF-8");
    } else {
        request = null;
    }

    /*
     * Construct our response:
     */

    buf = new StringBuilder();
    //buf.append("<html><head><title>HTTP echo server</title></head><body>");
    //buf.append("<p><pre>");
    //buf.append(t.getRequestMethod() + " " + t.getRequestURI() + " " + t.getProtocol() + "\n");

    /*
     * Process the request headers. This is a bit involved due to the
     * complexity arising from the fact that headers can be repeated.
     */

    Headers headers = t.getRequestHeaders();

    for (String name : headers.keySet()) {
        List<String> values = headers.get(name);

        for (String value : values) {
            //buf.append(name + ": " + value + "\n");
        }
    }

    /*
     * If there was an actual body to the request, add it:
     */

    if (request != null) {
        //buf.append("\n");
        buf.append(request);
    }

    //buf.append("</pre></p>");
    //buf.append("</body></html>\n");

    response = buf.toString();
    System.out.println(response);

    /*
     * And now send the response. We could have instead done this
     * dynamically, using 0 as the response size (forcing chunked
     * encoding) and writing the bytes of the response directly to the
     * OutputStream, but building the String first allows us to know the
     * exact length so we can send a response with a known size. Better :)
     */

    t.sendResponseHeaders(HTTP_OK, response.length());

    os = t.getResponseBody();

    os.write(response.getBytes());

    /*
     * And we're done!
     */

    os.close();
    t.close();
}

}

Deach answered 31/7, 2016 at 0:19 Comment(0)
A
6

Try to add

t.getResponseHeaders().put("Content-Type", "text/html"); 

before writing

Arbitrate answered 23/12, 2016 at 11:57 Comment(0)
P
0

It seems the interface has been changed since the answer. In Java 11 you need:

t.getRequestHeaders().put("Content-Type", Collections.singletonList("text/html"));
Postmistress answered 22/4, 2021 at 12:30 Comment(2)
Shouldn’t it be getResponseHeaders() rather than getRequestHeaders()?Bobbinet
Damn, it took me so much time to notice its request instead of response. Also, one can use .set() with plain String as a header value.Pyles
P
0

In Java 17 either:

t.getResponseHeaders().set("Content-Type", "text/html");

Or:

t.getResponseHeaders().put("Content-Type", Collections.singletonList("text/html"));

Also, adding works, though being more specific:

t.getResponseHeaders().add("Content-Type", "text/html");

Sources:

Pyles answered 9/9, 2022 at 21:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.