Elide sert du HTTP depuis un gestionnaire fetch ou depuis node:http ; cette page construit un même service des deux
façons.
Deux façons de servir
| Gestionnaire fetch | node:http | |
|---|---|---|
| Entrée | export default { fetch } ou Elide.serve({ fetch }) | http. |
| Requête et réponse | Request, Response du Web | IncomingMessage, ServerResponse |
| HTTPS et HTTP/2 | Options cert et key | Non disponible |
--contexts | Oui | Non ; la deuxième copie échoue avec EADDRINUSE |
// server.ts
export default {
port: Number(process.env.PORT ?? 3000),
fetch(request: Request): Response {
return new Response("hello\n");
},
};// node-server.ts
import { createServer } from "node:http";
const port = Number(process.env.PORT ?? 3000);
createServer((req, res) => {
res.writeHead(200, { "content-type": "text/plain" });
res.end("hello\n");
}).listen(port, "127.0.0.1");elide run server.ts
curl -i http://127.0.0.1:3000/HTTP/1.1 200 OK
Content-Type: text/plain;charset=UTF-8
content-length: 6
server: elide
date: Sat, 10 Oct 2026 00:18:12 GMT
helloelide run node-server.ts répond à la même requête avec Transfer-Encoding: chunked et Connection: keep-alive.
Adresse d’écoute de chaque style lorsque vous n’en indiquez aucune :
| Serveur | Adresse par défaut |
|---|---|
export default { fetch } sous elide run | 127.0.0.1:8080 |
export default { fetch } sous elide serve / elide dev | 127.0.0.1:8080 / 127.0.0.1:3000 ; --host et --port la remplacent |
Elide. | 0.0.0.0 sur port |
Routes, JSON et streaming
URLPattern, Request.json(), Response.json() et les corps ReadableStream sont des globales. Ce serveur expose une
API, une réponse en streaming et des fichiers statiques depuis public/ :
// app.ts
import { readFile } from "node:fs/promises";
import { extname, join, normalize } from "node:path";
const users = new URLPattern({ pathname: "/api/users/:id" });
const types: Record<string, string> = {
".html": "text/html; charset=utf-8",
".css": "text/css",
".js": "text/javascript",
};
async function api(request: Request): Promise<Response | null> {
const url = new URL(request.url);
const match = users.exec(url);
if (match && request.method === "GET") {
return Response.json({ id: match.pathname.groups.id });
}
if (url.pathname === "/api/users" && request.method === "POST") {
const body = await request.json();
return Response.json({ created: body.name }, { status: 201 });
}
if (url.pathname === "/api/ticks") {
let n = 0;
const stream = new ReadableStream({
async pull(controller) {
controller.enqueue(new TextEncoder().encode(`tick ${++n}\n`));
await new Promise((r) => setTimeout(r, 200));
if (n === 3) controller.close();
},
});
return new Response(stream, { headers: { "content-type": "text/plain" } });
}
return null;
}
async function file(pathname: string): Promise<Response> {
const path = join("public", normalize(pathname === "/" ? "/index.html" : pathname));
try {
const body = await readFile(path);
return new Response(body, { headers: { "content-type": types[extname(path)] ?? "application/octet-stream" } });
} catch {
return new Response("not found\n", { status: 404 });
}
}
export default {
port: Number(process.env.PORT ?? 3000),
async fetch(request: Request): Promise<Response> {
return (await api(request)) ?? file(new URL(request.url).pathname);
},
};elide run app.ts
curl http://127.0.0.1:3000/api/users/42
curl -X POST -H 'content-type: application/json' -d '{"name":"ada"}' http://127.0.0.1:3000/api/users
curl -N http://127.0.0.1:3000/api/ticks{"id":"42"}
{"created":"ada"}
tick 1
tick 2
tick 3Le POST répond 201 Created. Les trois ticks arrivent à 200 ms d’intervalle. / renvoie public/index.html, et un
fichier absent renvoie 404.
La même API sur node:http lit le corps avec node:stream/consumers et diffuse avec res.write :
// node-app.ts
import { createServer } from "node:http";
import { text } from "node:stream/consumers";
createServer(async (req, res) => {
if (req.method === "POST" && req.url === "/api/users") {
const body = JSON.parse(await text(req));
res.writeHead(201, { "content-type": "application/json" });
res.end(JSON.stringify({ created: body.name }));
return;
}
if (req.url === "/api/ticks") {
res.writeHead(200, { "content-type": "text/plain" });
for (let n = 1; n <= 3; n++) {
res.write(`tick ${n}\n`);
await new Promise((r) => setTimeout(r, 200));
}
res.end();
return;
}
res.writeHead(404).end();
}).listen(Number(process.env.PORT ?? 3000), "127.0.0.1");Pour ne servir que des fichiers, utilisez elide serve ./public ; voir Serveur de développement.
Erreurs
Un gestionnaire fetch qui lève une exception ou dont la promesse est rejetée répond 500 Internal Server Error et
continue de servir. L’erreur n’est pas affichée : interceptez-la et journalisez-la vous-même.
curl -i -d 'not json' http://127.0.0.1:3000/api/usersHTTP/1.1 500 Internal Server Error
Content-Type: text/plain; charset=utf-8
content-length: 21
server: elide
date: Sat, 10 Oct 2026 00:34:28 GMT
Internal Server ErrorTLS
Passez des chaînes PEM en cert et key à Elide.serve, ou comme propriétés de l’objet exporté. La clé doit être au
format PKCS#8 non chiffré (BEGIN PRIVATE KEY). Les clients qui proposent HTTP/2 l’obtiennent.
// tls.ts
import { readFileSync } from "node:fs";
Elide.serve({
port: Number(process.env.PORT ?? 8443),
cert: readFileSync("cert.pem", "utf8"),
key: readFileSync("key.pem", "utf8"),
fetch(request) {
return new Response("hello over tls\n");
},
});elide run tls.ts
curl -i --cacert cert.pem https://localhost:8443/HTTP/2 200
content-type: text/plain;charset=UTF-8
content-length: 15
server: elide
date: Sat, 10 Oct 2026 00:18:52 GMT
hello over tlselide serve et elide dev n’ont pas d’options TLS, et elide.pkl n’a pas de paramètres TLS. https.createServer
lève :
Error: HTTPS server is not supported in this runtime (no host TLS listener); use http.createServer behind a TLS terminator, or https client APIs.Plusieurs contextes
--contexts=N exécute N copies d’une application à gestionnaire fetch sur un même port, sous Linux. Chaque copie a
son propre état de module :
// counter.ts
let count = 0;
export default {
fetch(): Response {
count += 1;
return new Response(`${count}\n`);
},
};elide serve --no-tui --contexts=4 counter.ts
for i in 1 2 3 4 5 6 7 8; do curl -s http://127.0.0.1:8080/; done1
1
2
2
3
4
1
2Gardez l’état partagé dans une base de données ou un autre service. --contexts=auto dimensionne selon les cœurs du
CPU ; engine.contexts dans elide.pkl le fixe par projet
(Contextes du moteur).
Frameworks
Installez-les avec elide install --ecosystems=npm.
| Framework | État |
|---|---|
| Hono | Fonctionne : export default { fetch: app. ou export default app. |
| Express 5 | Le routage, res.json, express.raw() et la lecture manuelle de req fonctionnent. express.json() et express.text() arrêtent le processus avec TypeError: Buffer.. |
| Fastify 5 | Échoue à l’import : Error: No such built-in module: node:http2. |
// hono-app.ts
import { Hono } from "hono";
const app = new Hono();
app.get("/users/:id", (c) => c.json({ id: c.req.param("id") }));
app.post("/users", async (c) => c.json({ created: (await c.req.json()).name }, 201));
export default {
port: Number(process.env.PORT ?? 3000),
fetch: app.fetch,
};Exemples
- Gestionnaire HTTP
- Routes avec URLPattern
- Serveur local et fetch
- Server-sent events
- Limites de requêtes
- Serveur multi-contexte