Skip to content

Hono Adapter

@guardcore/hono provides Hono middleware that runs on Node.js and edge runtimes (Cloudflare Workers, Deno, Vercel Edge).

Terminal window
pnpm add @guardcore/hono

Creates a Hono MiddlewareHandler. Lazy-initializes on first request.

import { createGuardMiddleware } from '@guardcore/hono';
const middleware = createGuardMiddleware({
config: { /* SecurityConfig */ },
});
app.use('*', middleware);

Options:

FieldTypeRequiredDescription
configSecurityConfigYesSecurity configuration
agentHandlerAgentHandlerProtocolNoTelemetry agent
geoIpHandlerGeoIPHandlerNoGeoIP handler for country filtering
guardDecoratorSecurityDecoratorNoDecorator instance for per-route config

Configures CORS using Hono’s built-in hono/cors middleware (no additional packages needed).

import { configureCors, SecurityConfigSchema } from '@guardcore/hono';
const config = SecurityConfigSchema.parse({
enableCors: true,
corsAllowOrigins: ['https://app.example.com'],
});
configureCors(app, config);

The Hono adapter is designed for edge runtimes:

  • Uint8Array bodies — No Buffer dependency. Bodies are read via req.arrayBuffer() and wrapped in Uint8Array.
  • Lazy initialization — The security engine initializes on the first request, not at import time. This avoids cold-start issues.
  • Optional Redis — Set enableRedis: false for edge deployments. Rate limiting and IP bans work in-memory per isolate.
  • re2-wasm — Works in all runtimes via WebAssembly. Falls back to native RegExp if unavailable.

Hono does not expose req.ip like other frameworks. The adapter reads client IP from c.env.remoteAddr if available:

const connectingIp = c.env?.remoteAddr ?? null;
const guardReq = new HonoGuardRequest(c.req, connectingIp);

For Cloudflare Workers, use the geoResolver config option to read from cf.country:

const middleware = createGuardMiddleware({
config: {
enableRedis: false,
rateLimit: 100,
rateLimitWindow: 60,
blockedCountries: ['RU', 'CN'],
geoResolver: (ip: string) => {
return null;
},
},
});

Or provide a custom geoResolver that reads from Cloudflare’s cf object at the route level.

After calling next(), the adapter captures the response for:

  • Security header injection
  • Metrics collection
  • Behavioral return rule processing

Response bodies are not captured on the Hono adapter (only status and headers) to avoid buffering issues on edge runtimes.

import { Hono } from 'hono';
import { serve } from '@hono/node-server';
import {
createGuardMiddleware,
configureCors,
SecurityDecorator,
SecurityConfigSchema,
} from '@guardcore/hono';
const app = new Hono();
const config = SecurityConfigSchema.parse({
enableRedis: false,
rateLimit: 100,
rateLimitWindow: 60,
enablePenetrationDetection: true,
enableCors: true,
corsAllowOrigins: ['https://app.example.com'],
excludePaths: ['/health'],
});
const guard = new SecurityDecorator(config);
configureCors(app, config);
app.use('*', createGuardMiddleware({ config, guardDecorator: guard }));
app.get('/health', (c) => c.json({ status: 'ok' }));
app.get('/api/data', (c) => c.json({ data: 'protected' }));
serve({ fetch: app.fetch, port: 3000 });
import { Hono } from 'hono';
import { createGuardMiddleware } from '@guardcore/hono';
type Env = {
remoteAddr: string;
};
const app = new Hono<{ Bindings: Env }>();
app.use('*', createGuardMiddleware({
config: {
enableRedis: false,
rateLimit: 50,
rateLimitWindow: 60,
enablePenetrationDetection: true,
blockedUserAgents: ['sqlmap', 'nikto'],
},
}));
app.get('/', (c) => c.json({ message: 'Protected by @guardcore' }));
export default app;

Deploy with:

Terminal window
wrangler deploy