JEP proposed to target JDK 18: 408: Simple Web Server
julia.boes at oracle.com
Mon Oct 11 17:18:06 UTC 2021
On 09/10/2021 17:32, Simone Bordet wrote:> As a Jetty Project co-lead, and
> * the number of perils in URL parsing
> * the number of perils in URL decoding
> * the number of perils in URL to file-system Path conversions, which
> are file-system/os dependent
> * the number of perils in file-system aliasing, also file-system/os dependent
> I really wonder if this JEP is going to be an OpenJDK liability, also
Let me start by saying that this JEP does not add new functionality, but rather
exposes existing implementations. The Simple Web Server is located in
jdk.httpserver/com.sun.net.httpserver, a package that has been there since 2006
(JDK 1.6) and that is officially supported.
The original motivation for the jdk.httpserver module was to support web
services callbacks, which can indeed get dangerous quite quickly. The Simple Web
Server however is very different, it only serves static files and only supports
the idempotent GET and HEAD requests. As such it is much easier to secure.
With regard to the security considerations, let me summarize the central points
from the JEP, which in their sum help us be confident about this enhancement.
When started on the command-line, the server binds to the loopback address by
default. This prevents accidental exposure on the network; any other bind
address has to be explicitly specified, e.g. all interfaces.
The server uses a single thread, the HttpServer's default configuration. This
limits the risk of the server compromising machine performance. For similar
reasons, the server uses a backlog value of 50, the maximum number of incoming
TCP connections the system will queue internally.
The server only supports the idempotent GET and HEAD requests. Any other
requests receive a 501 - Not Implemented or a 405 - Not Allowed response.
*File System Access*
Server creation only succeeds if the root directory to be served (root path)
passes all of the following checks: Path.isAbsolute, Files.exists,
Upon server creation, a file server handler is created with the root path, and
is mapped to the root URI path "/" in the form of a context. This is the single
context of the server, so all requests are mapped to the file server handler.
When a request is received, the handler retrieves a file system path (resource
path) by resolving the request path against the root path, ensuring that neither
the root path nor the context path are escaped.
The server strictly serves files from the root directory and its subdirectories
only, no other files from the file system are served.
If a resource path is retrieved, the following checks are applied to itself and
all its segments: Files.exists, !Files.isHidden, !Files.isSymlink, Files.isReadable.
A 404 - Not Found response is sent if any of the above checks fail.
The requested resource is either a file, in which case its content is served, or
a directory, in which case the files in the directory are listed in HTML. In the
case of listing of directory content, a file is not included if it is either
hidden or a symlink.
*Sanitize Request URI*
The request URI that is reflected back in the response body is sanitized so that
special characters are replaced with their HTML encoded equivalents.
The server is a plain HTTP server (no authentication, access control, encryption
with SSL). The API doc underlines that the server is "intended for testing,
development and debugging purposes only". With this, developers are informed
about the minimal scope of the server.
When running the server on the command line, information is printed to about the
server and each exchange. This allows the developer to check that server
configuration and file system access are as expected. Upon start up, information
about the server is printed to the command line (in particular the local address
and the absolute path of the directory served). Additionally information is
printed for each exchange (in particular the absolute path of the requested
> I am not sure what this JEP proposes is really needed, as there are
> plenty of other options outside the JDK.
It is true that plenty of alternatives exist, I mention some of them in the JEP.
While that can be an argument for not "reinventing the wheel", it can also be an
argument for the opposite: The variety of existing choices is a testament to the
recognized need and usefulness of such a tool. If such a static server is
commonly used in a variety of scenarios, why should it not be in the JDK,
particularly if it's merely an extension of the existing server implementation
One of the goals of this JEP is to "Reduce developer activation energy and make
the JDK more approachable". We think a low-theshold tool that provides
tried-and-tested minimal functionality is a good way to achieve this. It can
appeal to a new generation of developers and keeps Java attractive.
More information about the jdk-dev