| name | bun-http-server |
| description | Use when building HTTP servers with Bun.serve, handling requests/responses, implementing routing, creating REST APIs, or configuring fetch handlers. |
| metadata | {"version":"1.0.0"} |
| license | MIT |
Bun HTTP Server
Bun has a built-in high-performance HTTP server via Bun.serve().
Quick Start
const server = Bun.serve({
port: 3000,
fetch(req) {
return new Response("Hello World!");
},
});
console.log(`Server running at http://localhost:${server.port}`);
Request Handling
Bun.serve({
fetch(req) {
const url = new URL(req.url);
console.log(req.method);
console.log(url.pathname);
console.log(url.searchParams.get("id"));
console.log(req.headers.get("Content-Type"));
return new Response("OK");
},
});
Body Parsing
Bun.serve({
async fetch(req) {
const json = await req.json();
const form = await req.formData();
const text = await req.text();
const buffer = await req.arrayBuffer();
const blob = await req.blob();
return new Response("Received");
},
});
Response Types
Bun.serve({
fetch(req) {
const url = new URL(req.url);
switch (url.pathname) {
case "/json":
return Response.json({ message: "Hello" });
case "/html":
return new Response("<h1>Hello</h1>", {
headers: { "Content-Type": "text/html" },
});
case "/redirect":
return Response.redirect("/new-location", 302);
case "/file":
return new Response(Bun.file("./image.png"));
case "/stream":
return new Response(
new ReadableStream({
start(controller) {
controller.enqueue("chunk1");
controller.();
controller.();
},
})
);
:
(, { : });
}
},
});
Simple Routing
Bun.serve({
fetch(req) {
const url = new URL(req.url);
const path = url.pathname;
const method = req.method;
if (method === "GET" && path === "/") {
return new Response("Home");
}
if (method === "GET" && path === "/api/users") {
return Response.json([{ id: 1, name: "Alice" }]);
}
const userMatch = path.match(/^\/api\/users\/(\d+)$/);
if (method === "GET" && userMatch) {
const userId = userMatch[1];
return Response.json({ id: userId });
}
return new Response("Not Found", { status: 404 });
},
});
Error Handling
Bun.serve({
fetch(req) {
try {
throw new Error("Something went wrong");
} catch (error) {
return new Response(
JSON.stringify({ error: error.message }),
{
status: 500,
headers: { "Content-Type": "application/json" }
}
);
}
},
error(error) {
return new Response(`Error: ${error.message}`, { status: 500 });
},
});
Server Options
const server = Bun.serve({
port: 3000,
hostname: "0.0.0.0",
development: true,
tls: {
key: Bun.file("./key.pem"),
cert: Bun.file("./cert.pem"),
},
unix: "/tmp/my-socket.sock",
maxRequestBodySize: 1024 * 1024 * 10,
fetch(req) {
return new Response("OK");
},
});
Server Methods
const server = Bun.serve({ ... });
console.log(server.port);
console.log(server.hostname);
console.log(server.url);
await server.stop();
server.reload({
fetch(req) {
return new Response("Updated!");
},
});
console.log(server.pendingRequests);
Routing with routes (Bun 1.2+)
The examples above use the classic fetch(req) handler with manual URL
parsing, which still works. As of Bun 1.2, the canonical way to declare
route maps is the routes option, with dynamic params available on
req.params:
Bun.serve({
routes: {
"/api/users": {
GET: () => Response.json([{ id: 1, name: "Alice" }]),
POST: async (req) => Response.json(await req.json(), { status: 201 }),
},
"/api/users/:id": (req) => {
const { id } = req.params;
return Response.json({ id });
},
},
fetch(req) {
return new Response("Not Found", { status: 404 });
},
});
Use routes for new code; keep fetch as a fallback for unmatched paths.
Static Files
Bun.serve({
fetch(req) {
const url = new URL(req.url);
if (url.pathname.startsWith("/static/")) {
const filePath = `./public${url.pathname.replace("/static", "")}`;
const file = Bun.file(filePath);
if (await file.exists()) {
return new Response(file);
}
return new Response("Not Found", { status: 404 });
}
return new Response("API");
},
});
CORS
function corsHeaders() {
return {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
};
}
Bun.serve({
fetch(req) {
if (req.method === "OPTIONS") {
return new Response(null, { headers: corsHeaders() });
}
return new Response("OK", { headers: corsHeaders() });
},
});
Common Errors
| Error | Cause | Fix |
|---|
EADDRINUSE | Port in use | Use different port or kill process |
Cannot read body | Body already consumed | Read body once only |
CORS error | Missing headers | Add CORS headers |
413 Payload Too Large | Body exceeds limit | Increase maxRequestBodySize |
When to Load References
Load references/tls-config.md when:
- HTTPS/TLS setup
- Certificate configuration
- mTLS authentication
Load references/streaming.md when:
- Server-sent events
- Streaming responses
- Chunked transfer encoding