Cette page démarre un serveur HTTP Chappe en moins de 30 lignes de Java, puis enchaîne sur un handler typé, le service de fichiers statiques et un test de charge minimal avec wrk.
Pré-requis
-
Java 25 — Temurin recommandé.
-
Maven 3.9.16 — épinglé via
.sdkmanrcà la racine du repochappe. -
sdk envau niveau du repo charge la bonne version JDK et Maven. Simvnéchoue avecmodelVersion 4.1.0 not supported, repasser à Maven 4 :sdk use maven 3.9.16. -
Optionnel :
wrkpour le test de charge final (brew install wrkou équivalent).
Coordonnées Maven
<dependency>
<groupId>io.vidocq.chappe</groupId>
<artifactId>chappe-api</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.vidocq.chappe</groupId>
<artifactId>chappe-core</artifactId>
<version>0.1.0-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.vidocq.chappe</groupId>
<artifactId>chappe-http</artifactId>
<version>0.1.0-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
chappe-api est l’API publique compilée en compile. chappe-core (moteur serveur) et chappe-http (protocoles HTTP/1.1 et HTTP/2) sont en runtime — découverts via ServiceLoader (ServerProvider).
Hello world
import io.vidocq.chappe.api.*;
void main() {
var router = Router.builder()
.get("/", _ -> Response.ok("Hello, Chappe!"))
.get("/users/{id}", req -> Response.ok("User " + req.pathParams().get("id")))
.build();
try (var server = Server.builder()
.port(8080)
.handler(router)
.build()) {
server.start();
Thread.currentThread().join();
}
}
L’instance Server est AutoCloseable ; start() ouvre le socket d’écoute et lance la boucle d’acceptation sur un virtual thread.
|
|
Premier handler typé
Pour lire un body JSON, écrire un POST, retourner un statut explicite :
import io.vidocq.chappe.api.*;
import java.nio.charset.StandardCharsets;
Router api = Router.builder()
.post("/users", req -> {
var body = new String(
req.body().asInputStream().readAllBytes(),
StandardCharsets.UTF_8
);
return Response.builder()
.status(StatusCode.CREATED)
.header("Content-Type", "application/json")
.body("{\"received\": " + body + "}")
.build();
})
.delete("/users/{id}", req -> Response.of(StatusCode.NO_CONTENT))
.build();
Servir un répertoire statique
var staticHandler = StaticFileHandler.builder()
.addPath(java.nio.file.Path.of("./public"))
.addClasspath("static")
.cacheInMemory(true)
.cacheControl("max-age=3600, public")
.build();
Server.builder().port(8080).handler(staticHandler).build().start();
StaticFileHandler détecte le MIME (26+ types), répond 304 Not Modified sur If-Modified-Since ou If-None-Match, et bloque le path traversal.
Build et lancement
sdk env # charge JDK 25 + Maven 3.9.16
./mvnw -ntp install -DskipTests
java \
--module-path target/lib:target/myapp.jar \
--module myapp/io.example.Main
Validation par wrk
Une fois le serveur en écoute sur 8080, valider qu’il accepte une charge minimale :
wrk -t4 -c100 -d10s http://localhost:8080/
Pour les chiffres de référence comparés à Jetty, Helidon et JDK HttpServer, voir lien:https://codeberg.org/Vidocq/chappe/blob/main/BENCH.md[BENCH.md].
Et après ?
-
Cas d’usage — TLS, HTTP/2, négociation de compression, virtual hosts, CLI.
-
Concepts —
RequestContext,Filter,Body, mount. -
Fonctionnement interne — pipelines HTTP/1.1, HTTP/2, HTTP/3.