CAKE20

AI Web PaaS

Hook

This is an HTTP Hook written in server/hooks.

Request Hook

  • *.hook.ts runs in front of every HTTP handler without creating a URL.
  • Hook files are executed in ascending order of name, and next() is the next hook or Call handler.
  • It is used for authentication, request recording, header processing, and common context configuration.
// server/hooks/client-ip.hook.ts
export default async (
  request: Request,
  context: ApiContext,
  next: HookNext
) => {
  context.clientIp = request.headers.get("cf-connecting-ip")
    || request.headers.get("x-real-ip")
    || request.headers.get("x-forwarded-for")?.split(",")[0]?.trim()
    || "local";

  return next();
};

file name convention

  • *.task.ts runs at config.cron time.
  • *.job.ts is registered as job.<file name>(data).
  • *.hook.ts runs in front of all HTTP handlers.
  • server/routes/*.ws.ts handles two-way WebSocket connections.
  • server/routes/*.sse.ts sends events from the server to the client.
  • Existing server/events and server/jobs files are moved to their respective standard folders.
  • The Task, WebSocket, and SSE samples start with active: false, but the editor's Test execution can be used regardless of active status.
server/hooks/
  client-ip.hook.ts # HTTP request hook
server/routes/
  hello.ts         # GET /hello
  chat.ws.ts       # WebSocket endpoint /chat
  stream.sse.ts    # SSE endpoint /stream
server/tasks/
  check.task.ts    # cron scheduled task
  report.job.ts    # XLSX Create Asynchronous Task

SSE basic structure

  • timer.interval is set in the range of 100 to 3,600,000 ms.
  • Heartbeat 10 seconds, 100 simultaneous connections and browser retry 3,000ms Runtime internal fixed value.
// server/routes/stream.sse.ts
export const config = {
  active: false,
  auth: false,
  timer: {
    active: true,
    immediate: true,
    interval: 1_000
  }
};

export const onOpen = async (stream: SseStream) => {
  await stream.push({ event: "open", data: { time: now() } });
};

export const onTimer = async (stream: SseStream, count: number) => {
  await stream.push({ event: "tick", data: { count, time: now() } });
};

export const onClose = (stream: SseStream) => {
  console.log("SSE Closed:", stream.id);
};