Java : How to Use the Simple Web Server (jwebserver)
The Java Simple Web Server (jwebserver) has been added to the JDK tools from the JDK 18. The jwebserver is useful for a quick check of a web page. In this article, I will introduce the basic usage of the jwebserver.
Summary
The Java Simple Web Server (jwebserver) is one of the JDK tools. It can only serve static pages and files.
The jwebserver is a console application. In this article, run it on the Windows PowerShell.
The jwebserver is in the same location as the java and javac tools. Specifically, it is located in the bin directory of JAVA_HOME.
Basic use
Now let's use the jwebserver.
First, you prepare an index.html file in your working directory. The content is html text that displays "Java Simple Web Server!".
PS R:\java-work> cat .\index.html
<html>
<body>
Java Simple Web Server!
</body>
</html>
Next, you run the jwebserver with no options.
PS R:\java-work> jwebserver.exe
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving R:\java-work and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/
By default, the jwebserver serves on 127.0.0.1 port 8000. You try accessing http://127.0.0.1:8000/ by your web browser.
A page was displayed in the web browser. On the jwebserver side as well, you can see that there was a GET request and returned 200 OK.
PS R:\java-work> jwebserver.exe
...
127.0.0.1 - - [10/Jul/2024:14:49:44 +0900] "GET / HTTP/1.1" 200 -
Finally, you press Ctrl + C to stop the jwebserver.
PS R:\java-work>
Options
Help
Please see also : The jwebserver Command
PS R:\java-work> jwebserver.exe -h
Usage: jwebserver [-b bind address] [-p port] [-d directory]
[-o none|info|verbose] [-h to show options]
[-version to show version information]
Options:
-b, --bind-address - Address to bind to. Default: 127.0.0.1 (loopback).
For all interfaces use "-b 0.0.0.0" or "-b ::".
-d, --directory - Directory to serve. Default: current directory.
-o, --output - Output format. none|info|verbose. Default: info.
-p, --port - Port to listen on. Default: 8000.
-h, -?, --help - Prints this help message and exits.
-version, --version - Prints version information and exits.
To stop the server, press Ctrl + C.
Version
PS R:\java-work> jwebserver.exe -version
jwebserver 21.0.1
Bind Address
Options:
-b, --bind-address - Address to bind to. Default: 127.0.0.1 (loopback).
For all interfaces use "-b 0.0.0.0" or "-b ::".
An example of binding a private IP address (192.168.1.100).
PS R:\java-work> jwebserver.exe -b 192.168.1.100
Serving R:\java-work and subdirectories on 192.168.1.100 port 8000
URL http://192.168.1.100:8000/
final var uri = URI.create("http://192.168.1.100:8000/");
final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // http://192.168.1.100:8000/ GET
try (final var client = HttpClient.newHttpClient()) {
final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response); // (GET http://192.168.1.100:8000/) 200
}
Port
Options:
-p, --port - Port to listen on. Default: 8000.
An example of listening to 8888 port.
PS R:\java-work> jwebserver.exe -p 8888
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving R:\java-work and subdirectories on 127.0.0.1 port 8888
URL http://127.0.0.1:8888/
final var uri = URI.create("http://127.0.0.1:8888/");
final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // http://127.0.0.1:8888/ GET
try (final var client = HttpClient.newHttpClient()) {
final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response); // (GET http://127.0.0.1:8888/) 200
}
Output
Options:
-o, --output - Output format. none|info|verbose. Default: info.
An example of a verbose output format.
PS R:\java-work> jwebserver.exe -o verbose
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving R:\java-work and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/
final var uri = URI.create("http://127.0.0.1:8000/");
final var request = HttpRequest.newBuilder(uri).build();
System.out.println(request); // http://127.0.0.1:8000/ GET
try (final var client = HttpClient.newHttpClient()) {
final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response); // (GET http://127.0.0.1:8000/) 200
}
A verbose output.
PS R:\java-work> jwebserver.exe -o verbose
...
127.0.0.1 - - [10/Jul/2024:14:58:32 +0900] "GET / HTTP/1.1" 200 -
Resource requested: R:\java-work
> Connection: Upgrade, HTTP2-Settings
> Http2-settings: AAEAAEAAAAIAAAABAAMAAABkAAQBAAAAAAUAAEAA
> Host: 127.0.0.1:8000
> User-agent: Java-http-client/21.0.1
> Upgrade: h2c
>
< Date: Wed, 10 Jul 2024 05:58:32 GMT
< Last-modified: Wed, 10 Jul 2024 05:40:38 GMT
< Content-type: text/html
< Content-length: 58
<
Directory
You prepare two directories, a-dir and b-dir, and index.html files.
Options:
-d, --directory - Directory to serve. Default: current directory.
PS R:\java-work> cat .\a-dir\index.html
AAA!
PS R:\java-work> cat .\b-dir\index.html
BBB!
First, you start the jwebserver with a-dir as the current directory.
PS R:\java-work> jwebserver.exe -d R:\java-work\a-dir
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving R:\java-work\a-dir and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/
You try accessing http://127.0.0.1:8000/ with your web browser.
Next, you start the jwebserver with b-dir as the current directory.
PS R:\java-work> jwebserver.exe -d R:\java-work\b-dir
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving R:\java-work\b-dir and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/
You try accessing http://127.0.0.1:8000/ with your web browser.
Not supported
POST, DELETE
The jwebserver supports HTTP methods GET and HEAD.
An example of the POST method.
PS R:\java-work> jwebserver.exe
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving R:\java-work and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/
127.0.0.1 - - [10/Jul/2024:15:03:56 +0900] "POST / HTTP/1.1" 405 -
final var uri = URI.create("http://127.0.0.1:8000/");
final var request = HttpRequest.newBuilder(uri)
.POST(HttpRequest.BodyPublishers.ofString("xyz"))
.build();
System.out.println(request); // http://127.0.0.1:8000/ POST
try (final var client = HttpClient.newHttpClient()) {
final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response); // (POST http://127.0.0.1:8000/) 405
}
HTTPS
The jwebserver only supports HTTP protocol. HTTPS is not supported.
PS R:\java-work> jwebserver.exe
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving R:\java-work and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/
final var uri = URI.create("https://127.0.0.1:8000/");
final var request = HttpRequest.newBuilder(uri)
.timeout(Duration.ofSeconds(5))
.build();
try (final var client = HttpClient.newHttpClient()) {
final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
} catch (HttpTimeoutException e) {
System.out.println("HttpTimeoutException!");
}
// Result
// ↓
//HttpTimeoutException!
HTTP/2
The jwebserver only supports HTTP/1.1. HTTP/2 is not supported.
PS R:\java-work> jwebserver.exe
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving R:\java-work and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/
127.0.0.1 - - [10/Jul/2024:15:11:02 +0900] "GET / HTTP/1.1" 200 -
final var uri = URI.create("http://127.0.0.1:8000/");
final var request = HttpRequest.newBuilder(uri).build();
try (final var client = HttpClient.newHttpClient()) {
System.out.println(client.version()); // HTTP_2
final var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response); // (GET http://127.0.0.1:8000/) 200
System.out.println(response.version()); // HTTP_1_1
}