branch:
index.ts
2246 bytesRaw
import type { AgentOptions } from "agents";
import { routeAgentRequest } from "agents";
import type { Context, Env } from "hono";
import { env } from "hono/adapter";
import { createMiddleware } from "hono/factory";
/**
* Configuration options for the Cloudflare Agents middleware
*/
type AgentMiddlewareContext<E extends Env> = {
/** Cloudflare Agents-specific configuration options */
options?: AgentOptions<E>;
/** Optional error handler for caught errors */
onError?: (error: Error) => void;
};
/**
* Creates a middleware for handling Cloudflare Agents WebSocket and HTTP requests
* Processes both WebSocket upgrades and standard HTTP requests, delegating them to Cloudflare Agents
*/
export function agentsMiddleware<E extends Env = Env>(
ctx?: AgentMiddlewareContext<E>
) {
return createMiddleware<E>(async (c, next) => {
try {
const handler = isWebSocketUpgrade(c)
? handleWebSocketUpgrade
: handleHttpRequest;
const response = await handler(c, ctx?.options);
return response === null ? await next() : response;
} catch (error) {
if (ctx?.onError) {
ctx.onError(error as Error);
return next();
}
throw error;
}
});
}
/**
* Checks if the incoming request is a WebSocket upgrade request
* Looks for the 'upgrade' header with a value of 'websocket' (case-insensitive)
*/
function isWebSocketUpgrade(c: Context): boolean {
return c.req.header("upgrade")?.toLowerCase() === "websocket";
}
/**
* Handles WebSocket upgrade requests
* Returns a WebSocket upgrade response if successful, null otherwise
*/
async function handleWebSocketUpgrade<E extends Env>(
c: Context<E>,
options?: AgentOptions<E>
) {
const response = await routeAgentRequest(
c.req.raw,
env(c) satisfies Env,
options
);
if (!response?.webSocket) {
return null;
}
return new Response(null, {
status: 101,
webSocket: response.webSocket
});
}
/**
* Handles standard HTTP requests
* Forwards the request to Cloudflare Agents and returns the response
*/
async function handleHttpRequest<E extends Env>(
c: Context<E>,
options?: AgentOptions<E>
) {
return routeAgentRequest(c.req.raw, env(c) satisfies Env, options);
}