Chuyển đến nội dung chính

Lesson 4: API Gateway with Hono — Routes, Middleware, Auth

Build HTTP server with Hono: routing, middleware chain, CORS, rate limiting. JWT authentication, password hashing, OAuth2 flow. Request validation and error handling.

🧠 AI & ML — Lesson 3 Lesson 4: API Gateway with Hono — Routes, Middleware, Auth

Building AI Agent Platform from Zero — Real battle with xClaw

Part 1: Monorepo Architecture & Platform

xdev.asia

Introduction

Hono is a lightweight HTTP framework that runs on the Web Standards API — fast, light, and type-safe. xClaw uses Hono as API Gateway — entry point for all HTTP requests.


1. Hono Server Setup

// packages/gateway/src/gateway.ts
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';

export function createGateway() {
  const app = new Hono();

  // Global middleware
  app.use('*', logger());
  app.use('*', cors({
    origin: process.env.CORS_ORIGINS?.split(',') ?? ['http://localhost:3001'],
    credentials: true,
  }));

  // Health check
  app.get('/health', (c) => {
    return c.json({
      status: 'ok',
      uptime: process.uptime(),
      timestamp: new Date().toISOString(),
    });
  });

  // Auth routes (public)
  app.post('/auth/login', loginHandler);
  app.post('/auth/register', registerHandler);

  // Protected API routes
  const api = new Hono();
  api.use('*', authMiddleware);   // JWT verification
  api.use('*', rbacMiddleware);   // Permission checking

  api.post('/chat', chatHandler);
  api.get('/models', modelsHandler);
  api.route('/workflows', workflowRoutes);
  api.route('/knowledge', knowledgeRoutes);
  api.route('/monitoring', monitoringRoutes);

  app.route('/api', api);
  return app;
}

2. JWT Authentication

// packages/gateway/src/auth.ts
import { sign, verify } from 'hono/jwt';
import { compare, hash } from 'bcrypt';

async function loginHandler(c: Context) {
  const { email, password } = await c.req.json();

  const user = await findUserByEmail(email);
  if (!user) return c.json({ error: 'Invalid credentials' }, 401);

  const valid = await compare(password, user.passwordHash);
  if (!valid) return c.json({ error: 'Invalid credentials' }, 401);

  const token = await sign(
    { sub: user.id, tenantId: user.tenantId, email: user.email },
    process.env.JWT_SECRET!,
  );

  return c.json({ token, user: { id: user.id, name: user.name, email: user.email } });
}

// Auth middleware
async function authMiddleware(c: Context, next: Next) {
  const header = c.req.header('Authorization');
  if (!header?.startsWith('Bearer ')) {
    return c.json({ error: 'Unauthorized' }, 401);
  }

  const token = header.slice(7);
  const payload = await verify(token, process.env.JWT_SECRET!);
  c.set('user', payload);
  await next();
}

3. RBAC Middleware

function requirePermission(...permissions: string[]) {
  return async (c: Context, next: Next) => {
    const user = c.get('user');
    const userPerms = await getUserPermissions(user.sub, user.tenantId);

    for (const perm of permissions) {
      if (!userPerms.includes(perm)) {
        return c.json({ error: 'Forbidden', required: perm }, 403);
      }
    }

    await next();
  };
}

// Usage
api.post('/workflows', requirePermission('workflows:create'), createWorkflowHandler);
api.delete('/workflows/:id', requirePermission('workflows:delete'), deleteWorkflowHandler);

4. Summary

  • Hono — lightweight, Web Standards, middleware chain
  • JWT auth — stateless authentication
  • RBAC middleware — permission-based access control per route
  • Error handling — consistent JSON error responses

Next article: LLM Router — Adapter Pattern for multi-provider LLM.