Cette page est la référence canonique de Chappe : artefacts Maven, modules JPMS exportés, API publique majeure, fichier de configuration YAML de la CLI, flags de la CLI, plugin de pré-compression. Pour la conformité RFC, voir Concepts et chappe-conformance dans le repo.
Artefacts Maven
| Artefact | Rôle |
|---|---|
|
API publique : |
|
Couche HTTP/1.1 + HTTP/2, TLS, |
|
Moteur serveur (virtual threads, protocol detection, lifecycle, |
|
Launcher CLI standalone |
|
Tests d’intégration (113 tests). |
|
Conformité HTTP (45 tests RFC 9110/9112/9113). |
|
Benchmarks comparatifs (Jetty, Helidon, JDK HttpServer). |
|
Plugin Maven : index O(1) + sidecars |
|
Exemples d’utilisation. |
Modules JPMS
| Module | Exports / declarations |
|---|---|
|
|
|
|
|
|
|
|
chappe-api n'`opens` rien. Aucun module n’expose son interne via réflexion : tout passe par les exports documentés ci-dessus.
API publique majeure (io.vidocq.chappe.api)
Server
public sealed interface Server extends AutoCloseable {
void start();
void stop();
int port();
static ServerBuilder builder();
}
ServerBuilder :
-
port(int) -
bindAddress(String) -
tls(SSLContext) -
alpnProtocols(String…) -
handler(Handler) -
executor(Executor)(par défaut : virtual threads) -
build()retourne unServer
Router
Router.builder()
.get(path, handler)
.post(path, handler)
.put(path, handler)
.delete(path, handler)
.patch(path, handler)
.head(path, handler) // auto pour GET aussi
.options(path, handler)
.group(prefix, sub -> sub.filter(...).get(...))
.mount(prefix, handler)
.filter(filter)
.notFound(handler)
.build();
Comportements :
-
405 Method Not Allowedautomatique avec headerAllowquand le path matche mais pas la méthode. -
Trailing slash transparent :
/userset/users/matchent la même route. -
Percent-decoding sur path params :
/users/John%20Doe→pathParam("id") = "John Doe".
Filter
public interface Filter {
Handler apply(Handler next);
static Filter addHeader(String name, String value);
static Filter addHeaderIf(BooleanSupplier when, String name, String value);
static Filter addHeaderIfEnv(String envVar, String expected, String name, String value);
static Filter gzip();
static Filter gzip(int threshold);
static Filter accessLog(); (1)
static Filter accessLog(Consumer<String> sink); (2)
default Filter andThen(Filter next);
}
| 1 | Logue chaque requête sur System.out au format Apache Combined Log Format étendu (cf. Observabilité). |
| 2 | Variante avec sink personnalisé (utile pour rediriger vers un logger applicatif). |
BuildInfo
public final class BuildInfo {
public static String version(); // ex: "0.1.0-SNAPSHOT"
public static String gitCommit(); // ex: "8d670fb0"
public static String buildTimestamp(); // ex: "2026-05-09T19:43:04Z"
public static String javaVersion(); // ex: "25.0.3"
public static String serverHeader(); // ex: "Chappe/0.1.0-SNAPSHOT+8d670fb0 (2026-05-09T19:43:04Z)"
}
Lu une fois au démarrage depuis META-INF/chappe-build.properties (généré par filtering Maven + git-commit-id-maven-plugin au build de chappe-api). Utilisé automatiquement par la couche HTTP pour injecter les headers Server et X-Chappe-Build.
StaticFileHandler
StaticFileHandler.builder()
.addPath(Path) // filesystem (zero-copy sendfile)
.addClasspath(String resourceRoot) // classpath (jar, module)
.cacheInMemory(boolean) // cache ETag pour ressources classpath
.cacheControl(String)
.preferPrecompressed(boolean) // sidecars .br / .gz si Accept-Encoding
.spaFallback(String) // 200 sur 404 (mode SPA)
.notFoundFile(String) // 404 sur 404 (mutuellement exclusif)
.indexFiles(String...)
.build();
AcceptEncoding
record Entry(String coding, double qvalue) {}
List<Entry> AcceptEncoding.parse(String header);
boolean AcceptEncoding.accepts(String header, String coding);
Algorithme RFC 9110 §12.5.3 : q-values, wildcard, identity implicite.
Configuration CLI chappe serve
Flags
| Flag | Effet |
|---|---|
|
charge un fichier YAML |
|
override |
|
override |
|
override |
|
override |
|
active le mode SPA (status 200 sur 404) |
|
override |
|
active/désactive la compression |
|
active/désactive l’access log Apache CLF sur stdout |
|
ajoute un header (répétable, merge dans |
|
aide |
Les flags ont priorité sur le YAML.
Variables d’environnement
| Variable | Effet |
|---|---|
|
active le bloc |
|
active l’access log (équivalent à |
Schéma YAML
server:
port: 8080
bind: 0.0.0.0
static:
root: /var/www/site
fallback: /404.html # status 404
spa-fallback: /index.html # status 200 (mutuellement exclusif avec fallback)
index-files: [index.html]
cache-control: "max-age=3600, public"
gzip: true # négocié via Accept-Encoding
headers:
always: # injectés sur chaque réponse
X-Content-Type-Options: "nosniff"
Referrer-Policy: "strict-origin-when-cross-origin"
staging: # actif si l'env var STAGING=true
X-Robots-Tag: "noindex, nofollow"
logging:
level: INFO
access-log: false
Subset documenté : maps imbriquées, listes inline [a, b] et bloc - item, scalaires string/int/bool, commentaires #. Pas d’anchors, de tags !!, de multilignes.
Observabilité
Headers de build
Toutes les réponses HTTP sortant de Chappe portent deux headers identifiant précisément le binaire qui les a produites :
Server: Chappe/0.1.0-SNAPSHOT+8d670fb0 (2026-05-09T19:43:04Z)
X-Chappe-Build: Chappe/0.1.0-SNAPSHOT+8d670fb0 (2026-05-09T19:43:04Z)
Format : Chappe/<version Maven>+<short hash Git>(<build timestamp ISO-8601 UTC>). Lu une fois au démarrage via BuildInfo (cf. API publique).
-
Serverest le header standard. Il peut être réécrit par un reverse proxy en amont (NPM, openresty, Cloudflare). -
X-Chappe-Builddouble l’info dans un header non-standard que les proxies ne réécrivent généralement pas — utile pour identifier le binaire derrière un reverse proxy qui fixe son propreServer.
Idempotence : si l’application a déjà fixé l’un de ces headers dans la Response, Chappe ne l’écrase pas.
Access log
Activable via --access-log (CLI), CHAPPE_ACCESS_LOG=true (env) ou logging.access-log: true (YAML). La CLI prime sur l’env qui prime sur le YAML.
Format : Apache Combined Log Format étendu, sortie sur System.out (capté par Docker/Portainer) :
1.2.3.4 - yann.blazart@gmail.com [09/May/2026:18:50:54 +0000] "GET /a.png HTTP/1.1" 200 877719 12ms
Résolution des champs :
-
IP cliente :
X-Forwarded-For(premier hop) →X-Real-IP→Request.remoteAddress()→-. -
User authentifié :
X-Forwarded-User→Gap-Auth(oauth2-proxy) →-. -
Size :
Response.body().contentLength()(ou-si streamé/chunked). -
Durée : nanosecondes mesurées par le filter en outermost wrapper, capture le status final même quand le handler lève une exception.
Le filter est exposé en API publique via Filter.accessLog() / Filter.accessLog(Consumer<String>) (cf. ci-dessus) ; le launcher CLI l’applique en outermost.
Plugin Maven : pré-compression
<plugin>
<groupId>io.vidocq.chappe</groupId>
<artifactId>chappe-static-index-maven-plugin</artifactId>
<executions>
<execution>
<goals><goal>index</goal></goals>
<configuration>
<compress>gzip</compress> <!-- défaut: none -->
<compressThreshold>1024</compressThreshold>
</configuration>
</execution>
</executions>
</plugin>
Génère :
-
META-INF/chappe-static-index.properties— index O(1) (chemin → taille + ETag). -
Sidecars
.gzpour les fichiers > seuil.
Servis zero-copy par StaticFileHandler.preferPrecompressed(true).
Capacités HTTP
| Spec | État | Notes |
|---|---|---|
RFC 9110 (HTTP Semantics) |
✅ |
Date, HEAD/204/304, 405+Allow, Host, 100-continue |
RFC 9112 (HTTP/1.1) |
✅ |
request parsing, chunked, keep-alive, pipelining |
RFC 9113 (HTTP/2) |
✅ |
framing, flow control, lifecycle, GOAWAY, SETTINGS, CONTINUATION |
RFC 7541 (HPACK) |
✅ |
table statique, table dynamique, Huffman encode/decode |
RFC 9114 (HTTP/3) |
⏳ |
planifié — voir lien:https://codeberg.org/Vidocq/chappe/blob/main/BUG.md[BUG.md] |
RFC 8441 (WebSocket H2) |
⏳ |
planifié |
Compatibilité
-
Java : 25 (LTS), aucun flag preview requis (
ScopedValueest final depuis JEP 506). -
Maven : 3.9.16 (POM
modelVersion 4.0.0). -
JPMS strict : aucun classpath, aucun
--add-opens.
Bugs et benchmarks
-
lien:https://codeberg.org/Vidocq/chappe/blob/main/BUG.md[BUG.md] — bugs reproductibles, statut, repro minimal.
-
lien:https://codeberg.org/Vidocq/chappe/blob/main/BENCH.md[BENCH.md] — chiffres de performance, hardware, JVM, commande.
Source
Tout le code et la roadmap sont sur https://codeberg.org/Vidocq/chappe.