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.