simple HTTP server in Java using only Java SE API

asker picture asker · Sep 17, 2010 · Viewed 404k times · Source

Is there a way to create a very basic HTTP server (supporting only GET/POST) in Java using just the Java SE API, without writing code to manually parse HTTP requests and manually format HTTP responses? The Java SE API nicely encapsulates the HTTP client functionality in HttpURLConnection, but is there an analog for HTTP server functionality?

Just to be clear, the problem I have with a lot of ServerSocket examples I've seen online is that they do their own request parsing/response formatting and error handling, which is tedious, error-prone, and not likely to be comprehensive, and I'm trying to avoid it for those reasons.

As an example of the manual HTTP manipulation that I'm trying to avoid:

http://java.sun.com/developer/technicalArticles/Networking/Webserver/WebServercode.html

Answer

BalusC picture BalusC · Sep 17, 2010

Since Java SE 6, there's a builtin HTTP server in Sun Oracle JRE. The com.sun.net.httpserver package summary outlines the involved classes and contains examples.

Here's a kickoff example copypasted from their docs (to all people trying to edit it nonetheless, because it's an ugly piece of code, please don't, this is a copy paste, not mine, moreover you should never edit quotations unless they have changed in the original source). You can just copy'n'paste'n'run it on Java 6+.

package com.stackoverflow.q3732109;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;

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

public class Test {

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

    static class MyHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange t) throws IOException {
            String response = "This is the response";
            t.sendResponseHeaders(200, response.length());
            OutputStream os = t.getResponseBody();
            os.write(response.getBytes());
            os.close();
        }
    }

}

Noted should be that the response.length() part in their example is bad, it should have been response.getBytes().length. Even then, the getBytes() method must explicitly specify the charset which you then specify in the response header. Alas, albeit misguiding to starters, it's after all just a basic kickoff example.

Execute it and go to http://localhost:8000/test and you'll see the following response:

This is the response


As to using com.sun.* classes, do note that this is, in contrary to what some developers think, absolutely not forbidden by the well known FAQ Why Developers Should Not Write Programs That Call 'sun' Packages. That FAQ concerns the sun.* package (such as sun.misc.BASE64Encoder) for internal usage by the Oracle JRE (which would thus kill your application when you run it on a different JRE), not the com.sun.* package. Sun/Oracle also just develop software on top of the Java SE API themselves like as every other company such as Apache and so on. Using com.sun.* classes is only discouraged (but not forbidden) when it concerns an implementation of a certain Java API, such as GlassFish (Java EE impl), Mojarra (JSF impl), Jersey (JAX-RS impl), etc.