A modern, lightweight, and type-safe HTTP server framework for Node.js, built with TypeScript. It provides a clean API for routing, request handling, and response generation, with built-in support for body parsing, validation, and Server-Sent Events (SSE).
- Intuitive Routing: Easy-to-use API for defining routes (
GET,POST,PUT,DELETE,PATCH). - Type-Safe Request Handling: Built-in TypeScript support for request bodies and parameters.
- Automatic Body Parsing: Seamlessly parses JSON and Form data (
multipart/form-data,application/x-www-form-urlencoded). - Schema Validation: Integrated support for Zod schemas to validate request bodies.
- Rich Response Helpers: Utility methods for sending JSON, text, files, streams, and Server-Sent Events (SSE).
- CORS Support: Built-in configuration for Cross-Origin Resource Sharing.
- Sub-Routers: Composable architecture using
server.use()to mount routers on specific paths. - Standard Web APIs: Built on top of standard Web APIs like
URLPattern,ReadableStream, andHeaders.
To install package:
npm install github:zuenkoma/http-serverimport { Server, ServerResponse } from 'http-server';
const server = new Server();
server.get('/', () => {
return ServerResponse.text('Hello World!');
});
server.get('/json', () => {
return ServerResponse.json({ message: 'This is JSON' });
});
server.listen(3000).then(() => {
console.log('Server running on http://localhost:3000');
});The req object passed to handlers provides type-safe access to the request details. It is based on standard Web APIs.
req.method: The HTTP method (e.g.,GET,POST).req.url.path: The path of the URL (e.g.,/users).req.url.params: Route parameters (e.g.,{ id: '123' }).req.url.search:URLSearchParamsobject for query strings.req.headers: StandardHeadersobject.req.body: The parsed request body.
server.get('/users/:id', (req) => {
const id = req.url.params.id;
const type = req.url.search.get('type');
return ServerResponse.json({ id, type });
});The server automatically parses request bodies based on the Content-Type header. You can also validate the body using Zod schemas.
import { z } from 'zod';
import { Server, ServerResponse } from 'http-server';
const server = new Server();
// Define a schema for validation
const UserSchema = z.object({
name: z.string(),
age: z.number()
});
server.post('/users', async (req) => {
// req.body is automatically parsed and typed if a schema is provided
const user = req.body;
return ServerResponse.json({ created: user }, { status: 201 });
}, { schema: UserSchema });
server.listen(3000);The server supports the following content types for automatic parsing:
application/json: Parsed into a JSON object.application/x-www-form-urlencoded: Parsed into a key-value object.multipart/form-data: Parsed into a key-value object (supports file uploads).- Other types: Available as a
ReadableStreaminreq.body.
Create modular applications by mounting routers on specific paths using server.use().
import { Server, Router, ServerResponse } from 'http-server';
const server = new Server();
const api = new Router();
api.get('/status', () => ServerResponse.json({ status: 'ok' }));
// Mount the router at /api
server.use('/api', api); // Handles /api/status
server.listen(3000);Handle multiple methods or all methods for a specific path:
// Handle multiple methods
server.route(['GET', 'POST'], '/items', (req) => {
if (req.method === 'POST') {
// Handle creation
}
// Handle listing
});
// Handle any method
server.all('/log', (req) => {
console.log(`${req.method} ${req.url.path}`);
return ServerResponse.empty();
});ServerResponse provides static methods for creating various types of responses:
ServerResponse.text(string): Send plain text.ServerResponse.json(data): Send a JSON response.ServerResponse.file(path): Stream a file with automatic MIME type detection.ServerResponse.redirect(url): Redirect to another URL.ServerResponse.empty(): Send an empty response (e.g., 204).ServerResponse.bytes(buffer): Send raw bytes.ServerResponse.blob(blob): Send a Blob object.ServerResponse.eventsJSON(stream): Send Server-Sent Events (SSE) from a stream of objects.ServerResponse.eventsText(stream): Send Server-Sent Events (SSE) from a stream of strings.
server.get('/file', () => {
return ServerResponse.file('./test/static/test.txt');
});
server.get('/redirect', () => {
return ServerResponse.redirect('/new-location');
});import { Server, ServerResponse } from 'http-server';
const server = new Server();
server.get('/events', () => {
const stream = new ReadableStream({
start(controller) {
setInterval(() => {
controller.enqueue({ data: 'ping' });
}, 1000);
}
});
return ServerResponse.eventsJSON(stream);
});Enable CORS for specific routes:
server.get('/api/data', () => {
return ServerResponse.json({ data: 'secure' });
}, { allowCrossOrigin: true });Throw StatusError to return specific HTTP status codes and messages.
import { Server, StatusError } from 'http-server';
const server = new Server();
server.get('/protected', (req) => {
const authorized = false;
if (!authorized) {
throw new StatusError(401, 'Unauthorized');
}
});You can also provide a custom error handler when creating the server or router:
const server = new Server({
errorHandler: (error, req) => {
console.error(`Error processing ${req.url.path}:`, error);
return ServerResponse.json({ error: 'Something went wrong' }, { status: 500 });
}
});Methods to manage the server instance:
// Start the server
await server.listen(3000);
// Get the bound port (useful if listening on port 0)
const port = server.getPort();
// Stop the server
await server.close();