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.
Java 18's Simple Web Server is a minimal HTTP static file server that was added in JEP 408 to the jdk. httpserver module. It serves a single directory hierarchy, and it serves only static files over HTTP/1.1; dynamic content and other HTTP versions are not supported.
Since Java SE 6, there's a builtin HTTP server in Sun Oracle JRE. The Java 9 module name is jdk.httpserver
. The com.sun.net.httpserver
package summary outlines the involved classes and contains examples.
Here's a kickoff example copypasted from their docs. You can just copy'n'paste'n'run it on Java 6+.
(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)
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. Moreover, this specific HttpServer
must be present in every JDK so there is absolutely no means of "portability" issue like as would happen with sun.*
package. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With