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 jwebserver tool provides a minimal HTTP server, designed to be used for prototyping, testing, and debugging.

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.

java-home-bin

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.

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.

a-dir

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/

b-dir

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
}

Related posts

To top of page