npm package: @flight-framework/http
Description: Ultra-fast HTTP server for Flight Framework - Built on Web Standards
Author: Flight Contributors
Latest version: 0.0.4
Deprecated: DEPRECATED: Movido a @flightdev/http

# @flight-framework/http

HTTP server for Flight Framework. Built on Web Standard APIs with radix-tree routing for maximum performance. Runs on Node.js, Bun, and Deno.

## Table of Contents

- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Routing](#routing)
- [Route Parameters](#route-parameters)
- [Middleware](#middleware)
- [Context API](#context-api)
- [Request Handling](#request-handling)
- [Response Helpers](#response-helpers)
- [Error Handling](#error-handling)
- [Sub-Routers](#sub-routers)
- [Runtime Adapters](#runtime-adapters)
- [Static Files](#static-files)
- [CORS](#cors)
- [API Reference](#api-reference)
- [License](#license)

---

## Features

- Radix-tree routing for fast path matching
- Native Request/Response APIs (Web Standard)
- Multi-runtime support: Node.js, Bun, Deno
- Middleware with async/await
- Type-safe route parameters
- Built-in helpers for JSON, HTML, redirects
- Zero external runtime dependencies
- Full TypeScript support

---

## Installation

```bash
npm install @flight-framework/http
```

---

## Quick Start

```typescript
import { createServer } from '@flight-framework/http';
import { serve } from '@flight-framework/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);
```

### Route Patterns

```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}`);
});
```

### Type-Safe Parameters

```typescript
import type { Context } from '@flight-framework/http';

interface UserParams {
    id: string;
    postId: string;
}

app.get('/users/:id/posts/:postId', (c: Context<UserParams>) => {
    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();
});
```

### Authentication Middleware

```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);
});
```

### Middleware Chain

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

### JSON Body

```typescript
app.post('/api/users', async (c) => {
    const body = await c.req.json();
    // body is parsed JSON
    return c.json({ received: body });
});
```

### Form Data

```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 });
});
```

### Raw Text

```typescript
app.post('/webhook', async (c) => {
    const text = await c.req.text();
    return c.text(`Received: ${text}`);
});
```

### Raw Binary

```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('<h1>Hello</h1>');
c.html('<!DOCTYPE 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

### Global Error Handler

```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);
});
```

### 404 Not Found

```typescript
app.notFound((c) => {
    return c.json({ 
        error: 'Not Found',
        path: new URL(c.req.url).pathname,
    }, 404);
});
```

### Throwing Errors

```typescript
import { HTTPException } from '@flight-framework/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 '@flight-framework/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 '@flight-framework/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

### Node.js

```typescript
import { createServer } from '@flight-framework/http';
import { serve } from '@flight-framework/http/node';

const app = createServer();

serve(app, { 
    port: 3000,
    hostname: '0.0.0.0',
});
```

### Bun

```typescript
import { createServer } from '@flight-framework/http';
import { serve } from '@flight-framework/http/bun';

const app = createServer();

serve(app, { port: 3000 });

// Or use Bun's native API
Bun.serve({
    port: 3000,
    fetch: app.fetch,
});
```

### Deno

```typescript
import { createServer } from '@flight-framework/http';
import { serve } from '@flight-framework/http/deno';

const app = createServer();

serve(app, { port: 3000 });

// Or use Deno's native API
Deno.serve({ port: 3000 }, app.fetch);
```

### Cloudflare Workers

```typescript
import { createServer } from '@flight-framework/http';

const app = createServer();

// ... define routes

export default {
    fetch: app.fetch,
};
```

---

## Static Files

Serve static files from a directory:

```typescript
import { serveStatic } from '@flight-framework/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 '@flight-framework/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

### createServer(options?)

Create a new Flight HTTP server.

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `strict` | `boolean` | `true` | Strict routing (trailing slash matters) |
| `getPath` | `function` | - | Custom path extraction |

### Context Methods

| 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 |

### App Methods

| 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) |

---

## License

MIT