Bun.serve(). It’s powered by a fork of uWebSockets and includes support for HTTP/1.1, HTTP/2, HTTPS, WebSockets, and Server-Sent Events.
Basic HTTP Server
const server = Bun.serve({
port: 3000,
fetch(req) {
return new Response("Welcome to Bun!");
},
});
console.log(`Listening on ${server.url}`);
Server Configuration
Port and Hostname
Bun.serve({
port: 8080, // Default: 3000
hostname: "0.0.0.0", // Default: "0.0.0.0" (all interfaces)
fetch(req) {
return new Response("Hello");
},
});
Unix Domain Sockets
Bun.serve({
unix: "/tmp/bun.sock",
fetch(req) {
return new Response("Unix socket server");
},
});
Request Handling
Accessing Request Data
Bun.serve({
async fetch(req) {
const url = new URL(req.url);
const method = req.method;
const headers = req.headers;
// Parse request body
const body = await req.text();
// or: await req.json();
// or: await req.formData();
// or: await req.arrayBuffer();
return new Response(`${method} ${url.pathname}`);
},
});
Route Parameters with BunRequest
import type { BunRequest } from "bun";
Bun.serve({
routes: {
"/users/:id": (req: BunRequest<"/users/:id">) => {
return new Response(`User ID: ${req.params.id}`);
},
},
});
Response Types
Text Response
return new Response("Hello World", {
headers: { "Content-Type": "text/plain" },
});
JSON Response
return Response.json({ message: "Hello" });
File Response
return new Response(Bun.file("./index.html"));
Stream Response
const stream = new ReadableStream({
start(controller) {
controller.enqueue("Hello ");
controller.enqueue("World");
controller.close();
},
});
return new Response(stream);
HTTPS/TLS
Bun.serve({
port: 443,
tls: {
cert: Bun.file("./cert.pem"),
key: Bun.file("./key.pem"),
ca: Bun.file("./ca.pem"), // Optional
},
fetch(req) {
return new Response("Secure!");
},
});
Error Handling
Bun.serve({
fetch(req) {
throw new Error("Something went wrong");
},
error(error) {
return new Response(`Error: ${error.message}`, {
status: 500,
});
},
});
Server Object
TheBun.serve() function returns a Server object:
const server = Bun.serve({
fetch(req) {
return new Response("Hello");
},
});
// Server properties
server.port; // 3000
server.hostname; // "0.0.0.0"
server.url; // URL { href: "http://0.0.0.0:3000/" }
server.protocol; // "http" | "https" | null
server.development; // boolean
server.id; // string
server.pendingRequests; // number
server.pendingWebSockets; // number
// Stop the server
await server.stop();
// Stop and close all connections
await server.stop(true);
Hot Reloading
const server = Bun.serve({
id: "my-server", // Required for hot reload
fetch(req) {
return new Response("Hello");
},
});
// Reload the server with new handlers
server.reload({
fetch(req) {
return new Response("Updated!");
},
});
Development Mode
Bun.serve({
development: true, // Shows detailed error pages
fetch(req) {
return new Response("Dev mode");
},
});
Request IP and Timeout
Bun.serve({
fetch(req, server) {
// Get client IP address
const address = server.requestIP(req);
console.log(address); // SocketAddress { address: "127.0.0.1", port: 54321, family: "IPv4" }
// Set request timeout (in seconds)
server.timeout(req, 30);
return new Response("OK");
},
});
Publishing to WebSockets
You can publish messages to WebSocket topics from the HTTP handler:Bun.serve({
websocket: {
message(ws, message) {
ws.subscribe("chat");
},
},
fetch(req, server) {
if (req.method === "POST") {
const message = await req.text();
// Publish to all subscribers
server.publish("chat", message);
return new Response("Published");
}
return new Response("Send POST");
},
});
Reference Counting
const server = Bun.serve({
fetch(req) {
return new Response("Hello");
},
});
// Don't keep process alive
server.unref();
// Keep process alive again
server.ref();
Type Signatures
interface Server<WebSocketData> {
readonly port: number | undefined;
readonly hostname: string | undefined;
readonly url: URL;
readonly protocol: "http" | "https" | null;
readonly development: boolean;
readonly id: string;
readonly pendingRequests: number;
readonly pendingWebSockets: number;
stop(closeActiveConnections?: boolean): Promise<void>;
reload<R extends string>(options: Serve.Options<WebSocketData, R>): Server<WebSocketData>;
upgrade(request: Request, options?: { headers?: HeadersInit; data?: WebSocketData }): boolean;
publish(topic: string, data: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer, compress?: boolean): number;
subscriberCount(topic: string): number;
requestIP(request: Request): SocketAddress | null;
timeout(request: Request, seconds: number): void;
ref(): void;
unref(): void;
}