JEP408 Un Simple Serveur Web en java

avertissement MAJ 2022-01 : La version finale de la JEP a été intégré dans le JDK 18. Des changements ont été apportées. Plus d’informations sur le billet consacré

Contexte

Nous allons nous projeter dans le futur en étudiant cette JEP, candidate pour le JDK 17. Le but est de mettre à disposition un petit serveur web qui renvoie simplement des pages statiques. Lors du développement web, il peut être intéressant d’avoir un serveur web pour

  • renvoyer des pages statiques (comme une page html chargeant des scripts javascript)

  • renvoyer des réponses JSON d’exemples pour tester la communication avec une autre API

Donc, l’idée est que le developpeur Java soit aussi pourvu que les développeurs d’autres langages.

Ligne de commande

Pour démarrer le serveur, il suffit de taper la commande suivante :

java -m jdk.httpserver

Nous obtenons le message suivant :

Serving /current/directory on http://127.0.0.1:8000/

Des options seront disponibles :

  • (-b) pour préciser l’interface réseau

  • (-p) pour préciser le numéro de port

  • (-h) pour afficher le message d’aide

  • (-o : none | default | verbose) pour afficher des informations lors de traitement des requêtes

En activant la journalisation, nous obtenons pour chaque requête le message équivalent :

127.0.0.1 - - [10/Feb/2021:14:34:11 +0000] "GET /some/subdirectory/" 200

astuce Cela veut dire que ce n’est pas une commande supplémentaire. Nous utilisons tout simplement la JVM.

Implémentation

L’idée serait d’utiliser le module jdk.httpserver qui contient l’API public com.sun.net.httpserver.

avertissement Le serveur répondrait uniquement aux méthodes HEAD et GET (requêtes idempotentes).

API

Le principe serait d’avoir une classe SimpleFileServer ayant l’interface suivante :

package com.sun.net.httpserver;

public final class SimpleFileServer {
    public static HttpServer createFileServer(int port, Path root,
                                              OutputLevel outputLevel) {...}
    public static HttpHandler createFileHandler(Path root) {...}
    public static Filter createOutputFilter(OutputStream out,
                                            OutputLevel outputLevel) {...}
    ...
}

En utilisant la commande jshell, il suffirait d’écrire

jshell> var server = SimpleFileServer.createFileServer(8080,
   ...> Path.of("/some/path"), OutputLevel.VERBOSE);
jshell> server.start()

Cela est simple et efficace.

Pour autant, il serait possible d’étendre le comportement de base en créeant notre propre serveur en passant notre intance de HttpHandler

public static HttpServer create(InetSocketAddress addr,
                                int backlog,
                                String root,
                                HttpHandler handler,
                                Filter... filters) throws IOException {...}

Cette dernière pourrait être construite à partir de la classe suivante :

package com.sun.net.httpserver;

public class HttpHandlers {
    public static HttpHandler handleOrElse(Predicate<Request> handlerTest,
                                           HttpHandler handler,
                                           HttpHandler fallbackHandler)
        throws IOException {...}
    public static HttpHandler adaptRequest(HttpHandler handler,
                                           UnaryOperator<Request> operator)
    {...}
}

avertissement D’autres alternatives seront envisagées pendant la phase de prototypage.

Dans tous les cas, j’ai hâte de pouvoir jouer avec !