Ultra-fast HTTP server for Flight Framework - Built on Web Standards
npm install @flightdev/httpbash
npm install @flightdev/http
`
---
Quick Start
`typescript
import { createServer } from '@flightdev/http';
import { serve } from '@flightdev/http/node';
const app = createServer();
app.get('/', (c) => c.json({ message: 'Hello Flight!' }));
app.get('/users/:id', (c) => {
return c.json({ userId: c.params.id });
});
app.post('/users', async (c) => {
const body = await c.req.json();
return c.json({ created: true, user: body }, 201);
});
serve(app, { port: 3000 });
console.log('Server running at http://localhost:3000');
`
---
Routing
Register routes using HTTP method helpers:
`typescript
app.get('/path', handler); // GET
app.post('/path', handler); // POST
app.put('/path', handler); // PUT
app.patch('/path', handler); // PATCH
app.delete('/path', handler); // DELETE
app.options('/path', handler); // OPTIONS
app.head('/path', handler); // HEAD
// All methods
app.all('/path', handler);
// Multiple methods
app.on(['GET', 'POST'], '/path', handler);
`
$3
`typescript
// Static path
app.get('/about', handler);
// Single parameter
app.get('/users/:id', handler);
// Multiple parameters
app.get('/posts/:year/:month/:slug', handler);
// Optional parameter
app.get('/files/:path?', handler);
// Wildcard (catch-all)
app.get('/assets/*', handler);
// Named wildcard
app.get('/docs/:path*', handler);
`
---
Route Parameters
Access route parameters from the context:
`typescript
// Route: /users/:id/posts/:postId
app.get('/users/:id/posts/:postId', (c) => {
const { id, postId } = c.params;
return c.json({ userId: id, postId });
});
// Wildcard parameters
// Route: /files/*
// Request: /files/images/photo.jpg
app.get('/files/*', (c) => {
const path = c.params['*']; // "images/photo.jpg"
return c.text(File: ${path});
});
`
$3
`typescript
import type { Context } from '@flightdev/http';
interface UserParams {
id: string;
postId: string;
}
app.get('/users/:id/posts/:postId', (c: Context) => {
c.params.id; // string (typed)
c.params.postId; // string (typed)
});
`
---
Middleware
Middleware functions run before route handlers:
`typescript
// Global middleware (runs on all routes)
app.use(async (c, next) => {
const start = performance.now();
const response = await next();
const duration = performance.now() - start;
console.log(${c.req.method} ${c.req.url} - ${duration.toFixed(2)}ms);
return response;
});
// Path-specific middleware
app.use('/api/*', async (c, next) => {
// Only runs on /api/* routes
return next();
});
`
$3
`typescript
const authMiddleware = async (c, next) => {
const token = c.header('Authorization')?.replace('Bearer ', '');
if (!token) {
return c.json({ error: 'Unauthorized' }, 401);
}
const user = await verifyToken(token);
if (!user) {
return c.json({ error: 'Invalid token' }, 401);
}
// Store user in context for later use
c.set('user', user);
return next();
};
// Apply to specific routes
app.use('/api/*', authMiddleware);
// Access in route handler
app.get('/api/profile', (c) => {
const user = c.get('user');
return c.json(user);
});
`
$3
Multiple middleware functions run in order:
`typescript
app.get('/protected',
authMiddleware,
rateLimitMiddleware,
validationMiddleware,
(c) => {
return c.json({ data: 'secret' });
}
);
`
---
Context API
The context object provides access to request data and response helpers:
`typescript
app.get('/demo', (c) => {
// Request object (Web Standard)
c.req; // Request
c.req.method; // "GET"
c.req.url; // Full URL
// Route parameters
c.params; // { id: "123" }
c.params.id; // "123"
// Query parameters
c.query('page'); // "1" or undefined
c.query('page', '1'); // "1" (with default)
c.queries('tags'); // ["a", "b"] (array)
// Headers
c.header('Content-Type'); // "application/json"
c.header('X-Custom'); // Custom header value
// Cookies
c.cookie('session'); // Cookie value
// Context storage
c.set('key', 'value'); // Store value
c.get('key'); // Retrieve value
return c.json({ ok: true });
});
`
---
Request Handling
$3
`typescript
app.post('/api/users', async (c) => {
const body = await c.req.json();
// body is parsed JSON
return c.json({ received: body });
});
`
$3
`typescript
app.post('/upload', async (c) => {
const form = await c.req.formData();
const name = form.get('name');
const file = form.get('file'); // File object
return c.json({ name, fileName: file?.name });
});
`
$3
`typescript
app.post('/webhook', async (c) => {
const text = await c.req.text();
return c.text(Received: ${text});
});
`
$3
`typescript
app.post('/binary', async (c) => {
const buffer = await c.req.arrayBuffer();
return c.json({ bytes: buffer.byteLength });
});
`
---
Response Helpers
`typescript
// JSON response
c.json({ data: 'value' });
c.json({ created: true }, 201);
c.json({ error: 'Not found' }, 404);
// Text response
c.text('Hello, World!');
c.text('Created', 201);
// HTML response
c.html('Hello
');
c.html('...', 200);
// Redirect
c.redirect('/new-location');
c.redirect('/login', 302); // Temporary (default)
c.redirect('/moved', 301); // Permanent
// No Content
c.body(null, 204);
// Custom response
return new Response(body, {
status: 200,
headers: { 'X-Custom': 'value' },
});
// Set response headers
c.header('X-Request-Id', requestId);
c.header('Cache-Control', 'max-age=3600');
// Set cookies
c.cookie('session', token, {
httpOnly: true,
secure: true,
sameSite: 'Strict',
maxAge: 60 60 24, // 1 day
});
`
---
Error Handling
$3
`typescript
app.onError((error, c) => {
console.error('Error:', error);
if (error instanceof ValidationError) {
return c.json({ error: error.message }, 400);
}
return c.json({ error: 'Internal Server Error' }, 500);
});
`
$3
`typescript
app.notFound((c) => {
return c.json({
error: 'Not Found',
path: new URL(c.req.url).pathname,
}, 404);
});
`
$3
`typescript
import { HTTPException } from '@flightdev/http';
app.get('/protected', (c) => {
if (!c.get('user')) {
throw new HTTPException(401, 'Unauthorized');
}
return c.json({ secret: 'data' });
});
`
---
Sub-Routers
Organize routes into modules:
`typescript
// routes/users.ts
import { createServer } from '@flightdev/http';
export const users = createServer();
users.get('/', (c) => c.json({ users: [] }));
users.get('/:id', (c) => c.json({ id: c.params.id }));
users.post('/', (c) => c.json({ created: true }));
// main.ts
import { createServer } from '@flightdev/http';
import { users } from './routes/users';
const app = createServer();
// Mount sub-router
app.route('/api/users', users);
// Routes:
// GET /api/users
// GET /api/users/:id
// POST /api/users
`
---
Runtime Adapters
$3
`typescript
import { createServer } from '@flightdev/http';
import { serve } from '@flightdev/http/node';
const app = createServer();
serve(app, {
port: 3000,
hostname: '0.0.0.0',
});
`
$3
`typescript
import { createServer } from '@flightdev/http';
import { serve } from '@flightdev/http/bun';
const app = createServer();
serve(app, { port: 3000 });
// Or use Bun's native API
Bun.serve({
port: 3000,
fetch: app.fetch,
});
`
$3
`typescript
import { createServer } from '@flightdev/http';
import { serve } from '@flightdev/http/deno';
const app = createServer();
serve(app, { port: 3000 });
// Or use Deno's native API
Deno.serve({ port: 3000 }, app.fetch);
`
$3
`typescript
import { createServer } from '@flightdev/http';
const app = createServer();
// ... define routes
export default {
fetch: app.fetch,
};
`
---
Static Files
Serve static files from a directory:
`typescript
import { serveStatic } from '@flightdev/http/static';
// Serve from 'public' directory
app.use('/static/*', serveStatic({ root: './public' }));
// With options
app.use('/assets/*', serveStatic({
root: './assets',
maxAge: 60 60 24, // 1 day cache
index: 'index.html',
}));
`
---
CORS
Enable Cross-Origin Resource Sharing:
`typescript
import { cors } from '@flightdev/http/cors';
// Allow all origins
app.use(cors());
// Specific origins
app.use(cors({
origin: 'https://example.com',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
headers: ['Content-Type', 'Authorization'],
credentials: true,
maxAge: 86400,
}));
// Dynamic origin
app.use(cors({
origin: (origin) => {
return origin.endsWith('.example.com');
},
}));
`
---
API Reference
$3
Create a new Flight HTTP server.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| strict | boolean | true | Strict routing (trailing slash matters) |
| getPath | function | - | Custom path extraction |
$3
| Method | Description |
|--------|-------------|
| c.req | Web Standard Request object |
| c.params | Route parameters |
| c.query(name, default?) | Get query parameter |
| c.queries(name) | Get all values for query param |
| c.header(name) | Get request header |
| c.cookie(name) | Get cookie value |
| c.set(key, value) | Store value in context |
| c.get(key) | Retrieve value from context |
| c.json(data, status?) | JSON response |
| c.text(text, status?) | Text response |
| c.html(html, status?) | HTML response |
| c.redirect(url, status?) | Redirect response |
| c.body(body, status?) | Raw body response |
$3
| Method | Description |
|--------|-------------|
| app.get/post/put/delete/patch(path, ...handlers) | Register route |
| app.all(path, ...handlers) | All HTTP methods |
| app.on(methods[], path, ...handlers) | Specific methods |
| app.use(...middleware) | Add middleware |
| app.use(path, ...middleware) | Path-specific middleware |
| app.route(path, subRouter) | Mount sub-router |
| app.notFound(handler) | Custom 404 handler |
| app.onError(handler) | Custom error handler |
| app.fetch(request)` | Handle request (Web Standard) |