daisuzz.log

JEP 408 Simple Web Server を試す

JDK18で提案されている、JEP 408: Simple Web Serverが気になり触ってみたので書いていきます。

JEP 408: Simple Web Serverでは、静的ファイルを提供する最小構成のWebサーバを起動するためのCLIツールをJavaの標準機能として提供することが提案されています。 このWebサーバはあくまでプロトタイプの実装やテストで使うことが想定されているので、本番環境での利用は想定されていません。

動作確認

今回は以下のバージョンで確認していきます。

$ java -version
openjdk version "18-ea" 2022-03-15
OpenJDK Runtime Environment (build 18-ea+23-1525)
OpenJDK 64-Bit Server VM (build 18-ea+23-1525, mixed mode, sharing)

jdk.httpserverをメインクラスとして指定することでサーバを起動できます。

$ java -m jdk.httpserver
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving /Users/daisuzz and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/

デフォルトではport番号が8000, IPアドレスループバックアドレスが設定されています。 起動したWebサーバは、起動時のカレントディレクトリと子ディレクトリを返す挙動になっています。

-pでport番号を変更できます。

$ java -m jdk.httpserver -p 8080
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving /Users/daisuzz and subdirectories on 127.0.0.1 port 8080
URL http://127.0.0.1:8080/

-bでバインドするアドレスを変更できます。

$ java -m jdk.httpserver -b 0.0.0.0
Serving /Users/daisuzz and subdirectories on 0.0.0.0 (all interfaces) port 8000
URL http://127.0.0.1:8000/

-dでWebサーバが返すディレクトリを指定できます。

$ java -m jdk.httpserver -d /
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving / and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/

WebサーバはHEADとGETメソッドのみに対応していて、そのほかのメソッドでリクエストした場合は501 - Not Implemented405 - Not Allowedレスポンスが返されるようになっています。

$  java -m jdk.httpserver -p 8080
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving /Users/daisuzz and subdirectories on 127.0.0.1 port 8080
URL http://127.0.0.1:8080/
127.0.0.1 - - [14/11月/2021:11:10:46 +0900] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [14/11月/2021:11:11:26 +0900] "POST / HTTP/1.1" 405 -
127.0.0.1 - - [14/11月/2021:11:11:35 +0900] "PUT / HTTP/1.1" 405 -
127.0.0.1 - - [14/11月/2021:11:11:41 +0900] "DELETE / HTTP/1.1" 405 -
127.0.0.1 - - [14/11月/2021:11:11:57 +0900] "HEAD / HTTP/1.1" 200 -

GETメソッドの場合、以下のルールでマッピングが行われます。

  • リクエストしたリソースがファイルの場合、ファイルの中身を返す

  • リクエストしたリソースがindexファイルを含んだディレクトリの場合、indexファイルの中身を返す

  • それ以外の場合、ディレクトリに配置されたファイルと子ディレクトリの名前を返す。ただし、シンボリックリンクや隠しファイルは返されない。

WebサーバはHTTPSに対応せず、HTTPのみに対応です。

ログ出力は-oで変更できます。デフォルトはinfononeにすると出力がされなくなります。verboseにすると、リクエストヘッダ, レスポンスヘッダ, リクエストされたリソースの絶対パスが追加で出力されます。

[daisuzz@MacBook-Pro] ~  java -m jdk.httpserver -p 8080 -o verbose
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving /Users/daisuzz and subdirectories on 127.0.0.1 port 8080
URL http://127.0.0.1:8080/
127.0.0.1 - - [14/11月/2021:10:59:41 +0900] "GET / HTTP/1.1" 200 -
Resource requested: /Users/daisuzz
> Accept-encoding: gzip, deflate, br
> Sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"
> Sec-fetch-dest: document
> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
> Sec-fetch-user: ?1
> Connection: keep-alive
> Sec-fetch-site: none
> Host: 127.0.0.1:8080
> Sec-fetch-mode: navigate
> Sec-ch-ua-platform: "macOS"
> User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
> Accept-language: ja-JP,ja;q=0.9,en-US;q=0.8,en;q=0.7
> Upgrade-insecure-requests: 1
> Sec-ch-ua-mobile: ?0
>
< Date: Sun, 14 Nov 2021 01:59:41 GMT
< Last-modified: Sun, 14 Nov 2021 01:59:37 GMT
< Content-type: text/html; charset=UTF-8
< Content-length: 1017
<

おわりに

Javaで簡単にWebサーバが起動できるようになることで、静的ファイルの見た目を確認するためのサーバや、事前に定義しておいたものを返すモックサーバをより簡単に立てることができます。 CLIで起動するWebサーバの挙動の詳細を設定できるAPIも提供されているので、また別の機会に遊んでみたいと思います。

参考資料

https://openjdk.java.net/jeps/408