JWebserver - Launch the Java Simple Web Server

 

Introducing jwebserver

jwebserver - a tool that offers a minimal HTTP server, serving a single directory hierarchy, and intended for prototyping, testing, and debugging.

 

Synopsis

jwebserver [options]

options See options for the jwebserver below.

The following options are available:

--bind-address addr or —b addr Specifies the address to bind to. The default address is 127.0.0.1 or ::1 (loopback). In case you need all interfaces, you can use -b 0.0.0.0 or -b ::.

--directory dir or —d dir Specifies the directory to serve. The default value is current directory.

--help or —h Prints out a full help message.

--output level or —o level Specifies the output format and can be one of none | info | verbose. The default value is info.

--port port or -p port Specifies the port to listen on. The default port value is 8000.

--version Prints out the abbreviated version string of the tool.

 

Description

jwebserver is a JDK tool that provides a minimal HTTP server that you can use for prototyping, testing, and debugging. The tool serves only static files and looks into a single directory hierarchy over HTTP/1.1; dynamic content and other HTTP versions are not supported. The module jdk.httpserver contains jwebserver, and can alternatively be started with java -m jdk.httpserver because it is based on the web server implementation in the com.sun.net.httpserver package. The SimpleFileServer class offers a programmatic way to retrieve the server and its components for reuse and extension. Checkout the working with the Simple Web Server API section.

The requests method served are only idempotent HEAD and GET. If you will try any other requests, you will receive a 501 - Not Implemented or a 405 - Not Allowed response. The tool maps GET requests to the directory being served, as follows:

  • In case the requested resource is a file, its content is served.
  • If the requested resource is a directory that contains an index file, the content of that index file is served.
  • Otherwise, the response will contain the names of all files and subdirectories of the directory. Symbolic links and hidden files are not listed or served.

jwebserver has MIME types automatically configured, using a built-in table. For example, .html files are served as text/html and .java files are served as text/plain.

 

Command Line Examples

jwebserver can help you with:

  • Web development testing, when you need a local testing server to simulate a client-server set up.

    jwebserver
    Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
    Serving /cwd and subdirectories on 127.0.0.1 port 8000
    URL: http://127.0.0.1:8000/
    
  • Web-service or application testing, where you use static files as API stubs in a directory structure to mirror RESTful URLs and contain dummy data.

jwebserver -p 9000
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving /youtube-jdk21 and subdirectories on 127.0.0.1 port 9000
URL http://127.0.0.1:9000/
127.0.0.1 - - [09/Jul/2023:13:02:05 +0200] "GET /api/activity.json HTTP/1.1" 200 -
127.0.0.1 - - [09/Jul/2023:13:02:06 +0200] "GET /api/activity.json HTTP/1.1" 200 -

static_endpoint

  • Informal browsing and sharing of files across systems to, e.g., search a directory on a remote server from your local machine.
jwebserver -b 0.0.0.0
Serving /work and subdirectories on 0.0.0.0 (all interfaces) port 8000
URL http://192.168.178.41:8000/

While the command-line tool is useful, you can also use the Simple Web Server (i.e., server, handler, and filter) with existing code via its API.

 

Working with the Simple Web Server API

In addition to the jwebserver command-line tool, the Simple Web Server provides an API in order for you to programmatically create and customize the server and its components. Earlier, you observed how the command jwebserver serves the files of the current working directory. Yet, what you sometimes need that directory structure to simulate expected response patterns and physically not preserve the mocks. You can achieve that behavior by using Google's Java in-memory file system Jimfs to create in-memory resources and serve them with the Simple Web Server:

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.UUID;

import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import com.sun.net.httpserver.SimpleFileServer;

import static com.sun.net.httpserver.SimpleFileServer.OutputLevel;

public class InMemoryFileServer {
    private static final InetSocketAddress LOOPBACK_ADDR =
            new InetSocketAddress(InetAddress.getLoopbackAddress(), 8080);
    public static final String JSON_FILE_NAME = "thing.json";
    public static final String DIR_PATH = "some/other";

    public static void main( String[] args ) throws Exception {
        Path root = createDirectoryHierarchy();
        var server = SimpleFileServer.createFileServer(LOOPBACK_ADDR,  root, OutputLevel.VERBOSE);
        server.start();
        System.out.printf("http://%s:%d%n", server.getAddress().getHostString(), server.getAddress().getPort());
    }

    private static Path createDirectoryHierarchy() throws IOException {
        String json = """
                {
                  "activity": "Go for a run",
                  "type": "recreational",
                  "participants": 1,
                  "distance": "%d km",
                  "key": "%s",
                }
                """;
        FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
        Path root = fs.getPath("/");
        Path dir = Files.createDirectories(root.resolve(DIR_PATH));
        Path filePath = fs.getPath(JSON_FILE_NAME);
        Path innerMockFile = Files.createFile(dir.resolve(filePath));

        Files.write(innerMockFile,json.formatted(12, UUID.randomUUID().toString()).getBytes(), StandardOpenOption.WRITE);
        Path mockFile = Files.createFile(dir.getParent().resolve(filePath));

        Files.write(mockFile,json.formatted(10, UUID.randomUUID().toString()).getBytes(), StandardOpenOption.WRITE);
        return root;
    }
}

Run the previous code snippet in the command line via:

$ java InMemoryFileServer.java
> http://127.0.0.1:8080

The example above serves a JSON response stored in server's memory, thus saving disk space while providing the necessary for API stubbing. You can find another way to serve in memory assets in Christian Stein's article where he is implementing com.sun.net.httpserver.HttpHandler to serve in-memory assets. More programmatic examples on using the Simple Web Server API are available in Julia Boes' article on https://inside.java.

 

More Learning


Last update: January 4, 2024