乐于分享
好东西不私藏

better-auth apikey插件使用

better-auth apikey插件使用

使用原始sqlite

https://better-auth.com/docs/plugins/api-key#update-an-api-key

注意第三步,由于我们后端使用了Hono,这里新建一个auth-cli.ts配合auth生成schema,如下:

import {betterAuth} from "better-auth"import {dash} from "@better-auth/infra"import {apiKey} from "@better-auth/api-key";import Database from "better-sqlite3";const auth = betterAuth(      {        database: new Database("database.sqlite"),        secrets: [              { version: 1, value: "QDJZgrf8HvKYRwh39ZfpniinZi5vfCj0" }          ],        emailAndPassword: {            enabled: true,          },        plugins: [            dash(),            apiKey()          ]      }  );export default auth;

安装better-sqlite3

npm install better-sqlite3npm install -D @types/better-sqlite3

生成schema

npx auth generate --config ./src/lib/auth-cli.ts2026-07-15T06:14:58.021Z WARN **[Better Auth]:** [better-auth] Base URL is not set. Set the baseURL option or BETTER_AUTH_URL env, or use a dynamic baseURL with allowedHosts for multi-host setups. Without it the origin is derived from the incoming request, and callbacks and redirects may not work correctly.✔ **Do you want to generate the schema to** **./better-auth_migrations/2026-07-15T06-14-58.034Z.sql****?** … yes🚀 Schema was generated successfully!
  • • 最好能够添加“if not exists”
sed -i '' 's/create table /create table if not exists /g' ./better-auth_migrations/2026-07-15T06-14-58.034Z.sql

查看schema内容

create table if not exists "user" ("id" text not null primary key, "name" text not null, "email" text not null unique, "emailVerified" integer not null, "image" text, "createdAt" date not null, "updatedAt" date not null);create table if not exists "session" ("id" text not null primary key, "expiresAt" date not null, "token" text not null unique, "createdAt" date not null, "updatedAt" date not null, "ipAddress" text, "userAgent" text, "userId" text not null references "user" ("id") on delete cascade);create table if not exists "account" ("id" text not null primary key, "accountId" text not null, "providerId" text not null, "userId" text not null references "user" ("id") on delete cascade, "accessToken" text, "refreshToken" text, "idToken" text, "accessTokenExpiresAt" date, "refreshTokenExpiresAt" date, "scope" text, "password" text, "createdAt" date not null, "updatedAt" date not null);create table if not exists "verification" ("id" text not null primary key, "identifier" text not null, "value" text not null, "expiresAt" date not null, "createdAt" date not null, "updatedAt" date not null);create table if not exists "apikey" ("id" text not null primary key, "configId" text not null, "name" text, "start" text, "referenceId" text not null, "prefix" text, "key" text not null, "refillInterval" integer, "refillAmount" integer, "lastRefillAt" date, "enabled" integer, "rateLimitEnabled" integer, "rateLimitTimeWindow" integer, "rateLimitMax" integer, "requestCount" integer, "remaining" integer, "lastRequest" date, "expiresAt" date, "createdAt" date not null, "updatedAt" date not null, "permissions" text, "metadata" text);create index "session_userId_idx" on "session" ("userId");create index "account_userId_idx" on "account" ("userId");create index "verification_identifier_idx" on "verification" ("identifier");create index "apikey_configId_idx" on "apikey" ("configId");create index "apikey_referenceId_idx" on "apikey" ("referenceId");create index "apikey_key_idx" on "apikey" ("key");

备份线上数据库

wrangler d1 export better_auth_cloudflare_demo --remote --output="./backup.sql"

迁移schema到线上

wrangler d1 execute better_auth_cloudflare_demo --remote --file=./better-auth_migrations/2026-07-15T06-14-58.034Z.sql▲ [WARNING] **Proxy environment variables detected. We'll use your proxy for fetch requests.** ⛅️ wrangler 4.106.0 (update available 4.111.0)───────────────────────────────────────────────**Resource location:** remote ✔ **⚠️ This process may take some time, during which your D1 database will be unavailable to serve queries.**  **Ok to proceed?** … yes🌀 Executing on remote database better_auth_cloudflare_demo (25b30dd3-b35d-45fa-9fa9-7c2af8240024):🌀 To execute on your local development database, remove the --remote flag from your wrangler command.Note: if the execution fails to complete, your DB will return to its original state and you can safely retry.├ 🌀 Uploading 25b30dd3-b35d-45fa-9fa9-7c2af8240024.ecd456601eeae9cd.sql│ 🌀 Uploading complete.🌀 Starting import...🌀 Processed 11 queries.🚣 Executed 11 queries in 7.60ms (27 rows read, 16 rows written)   Database is currently at bookmark 00000011-00000006-000050a9-745ebcde7be90d22931c142a684adcd6.┌────────────────────────┬───────────┬──────────────┬────────────────────┐│ Total queries executed │ Rows read │ Rows written │ Database size (MB) │├────────────────────────┼───────────┼──────────────┼────────────────────┤│ 11                     │ 27        │ 16           │ 0.09               │└────────────────────────┴───────────┴──────────────┴────────────────────┘

测试

  • • 注册
curl -X POST http://localhost:8787/api/auth/sign-up/email \    -H 'Content-Type: application/json' \    -d '{"email":"test1@example.com","password":"12345678","name":"test"}'{"token":"TW2r49vYFVrXjYJKrHimsHEvblJXyjkb","user":{"name":"test","email":"test1@example.com","emailVerified":false,"image":null,"createdAt":"2026-07-16T02:49:58.678Z","updatedAt":"2026-07-16T02:49:58.680Z","id":"yfpSbmt6ZNLMmxI2mplC9IcM30UeZYEt"},"apiKey":{"id":"8BPh55jSSjpG0pkwKgD5dFaA4N1nBkFa","name":"test 的初始密钥","secretKey":"jHvNYYarROHBeTIyRrvzbnrxOfQTLkMvHBbjSZfoyBnSxXIlowCffOXvOqJDPkzt","expiresAt":null}}
  • • 访问,不携带secretKey
curl -X GET http://localhost:8787/api/user/profile{"error":"unauthorized"}
  • • 访问,携带secretKey
curl -X GET http://localhost:8787/api/user/profile \  -H "Authorization: Bearer jHvNYYarROHBeTIyRrvzbnrxOfQTLkMvHBbjSZfoyBnSxXIlowCffOXvOqJDPkzt"{"id":"yfpSbmt6ZNLMmxI2mplC9IcM30UeZYEt","name":"test","email":"test1@example.com","emailVerified":false,"image":null,"createdAt":"2026-07-16T02:49:58.678Z","updatedAt":"2026-07-16T02:49:58.680Z"}
  • • 访问,携带错误的secretKey,比如将最后一个字母修改掉
curl -X GET http://localhost:8787/api/user/profile \  -H "Authorization: Bearer jHvNYYarROHBeTIyRrvzbnrxOfQTLkMvHBbjSZfoyBnSxXIlowCffOXvOqJDPkza"{"success":false,"message":"未授权:无效或过期的 API Key"}

使用Drizzle方式

安装

npm install @better-auth/drizzle-adapternpm install drizzle-ormnpm install -D drizzle-kit tsx

代码架构

.├── drizzle.config.ts├── package-lock.json├── package.json├── README.md├── src│   ├── constants.ts│   ├── db│   │   ├── db.ts│   │   ├── drizzle│   │   │   ├── 0000_gifted_raza.sql│   │   │   └── meta│   │   │       ├── _journal.json│   │   │       └── 0000_snapshot.json│   │   └── schema.ts│   ├── index.ts│   ├── lib│   │   ├── auth-cli.ts│   │   └── auth.ts│   ├── middleware│   │   ├── apiKey.ts│   │   ├── cors.ts│   │   └── index.ts│   ├── routes│   │   ├── auth.ts│   │   ├── index.ts│   │   └── user.ts│   └── types.ts├── tsconfig.json├── worker-configuration.d.ts└── wrangler.jsonc

配置auth

auth

import { betterAuth } from "better-auth"import { dash } from "@better-auth/infra"import { apiKey } from "@better-auth/api-key";import { drizzleAdapter } from "better-auth/adapters/drizzle";import { createDb, type Database } from "../db/db";import * as schema from "../db/schema";import { TRUSTED_ORIGINS } from "../constants";export const createAuth = (env: Cloudflare.Env, existDb?: Database) => {    const db = existDb ?? createDb(env.better_auth_cloudflare_demo);    return betterAuth({        database: drizzleAdapter(db, {            provider: "sqlite",              schema          }),        emailAndPassword: {            enabled: true,          },        secrets: [              { version: 1, value: env.SECRET_KEY_V1 },          ],        basePath: "/api/auth",        baseURL: env.BETTER_AUTH_URL,        trustedOrigins: [...TRUSTED_ORIGINS],        rateLimit: {            enabled: true,            timeWindow: 60,            maxRequests: 10,          },        logger: {            disabled: true        },        plugins: [            apiKey({                enableSessionForAPIKeys: true, //用 session 方式进行中间件校验                    permissions: {                    defaultPermissions: {                        files: ["read"],                        users: ["read"],                      },                  },                rateLimit: {                    enabled: true,                    timeWindow: 60,                    maxRequests: 100                }              })          ]      });  };//获取动态 Auth 实例的类型  export type AuthInstance = ReturnType<typeof createAuth>;//推导 Session 和 User 的类型  export type SessionUser = AuthInstance["$Infer"]["Session"]["user"];//如果您在下游路由需要拿到 API Key 的元数据(如创建时间、权限列表、所属用户ID等),这样推导:  export type ApiKeyInfo = Awaited<ReturnType<AuthInstance["api"]["verifyApiKey"]>>["key"];

auth-cli

import {betterAuth} from "better-auth"import {dash} from "@better-auth/infra"import {apiKey} from "@better-auth/api-key";import {drizzleAdapter} from "better-auth/adapters/drizzle";import {drizzle} from "drizzle-orm/better-sqlite3";import Database from "better-sqlite3";import * as schema from "../db/schema";const sqlite = new Database("database.sqlite");const db = drizzle(sqlite, { schema });const auth = betterAuth({    database: drizzleAdapter(db, {        provider: "sqlite"    }),    emailAndPassword: {        enabled: true,      },    rateLimit: {        enabled: true,        timeWindow: 60,        maxRequests: 10,      },    plugins: [        apiKey({            enableSessionForAPIKeys: true,            permissions: {                defaultPermissions: {                    files: ["read"],                    users: ["read"],                  },              },            rateLimit: {                enabled: true,                timeWindow: 60,                maxRequests: 100            }          })      ]  });export default auth;
  • • 这个文件可以命名为auth-cli.ts,只是为了生成数据库schema件
  • • 和auth.ts内容基本保持一致
  • • 需要导出auth

db

  • • db通过drizzle的方式生成和访问,drizzle.config.ts内容如下:
import { defineConfig } from "drizzle-kit";export default defineConfig({    dialect: "sqlite",             // Cloudflare D1 底层是 SQLite      schema: "./src/db/schema.ts",  // 指向你通过脚本一键生成的 schema 文件      out: "./src/db/drizzle",       // 未来通过 drizzle-kit 生成的SQL代码的存放目录  });

生成schema

npx @better-auth/cli generate --config ./src/lib/auth-cli.ts --output ./src/db/schema.ts --yes2026-07-16T07:23:05.003Z WARN **[Better Auth]:** [better-auth] Base URL is not set. Set the baseURL option or BETTER_AUTH_URL env, or use a dynamic baseURL with allowedHosts for multi-host setups. Without it the origin is derived from the incoming request, and callbacks and redirects may not work correctly.🚀 Schema was overwritten successfully!
  • • 注意:执行这条指令会生成database.sqlite,删除即可
  • • 生成的schema内容如下
CREATE TABLE `account` (      `id` text PRIMARY KEY NOT NULL,      `account_id` text NOT NULL,      `provider_id` text NOT NULL,      `user_id` text NOT NULL,      `access_token` text,      `refresh_token` text,      `id_token` text,      `access_token_expires_at` integer,      `refresh_token_expires_at` integer,      `scope` text,      `password` text,      `created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,      `updated_at` integer NOT NULL,      FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade  );  --> statement-breakpoint  CREATE INDEX `account_userId_idx` ON `account` (`user_id`);--> statement-breakpoint  CREATE TABLE `apikey` (      `id` text PRIMARY KEY NOT NULL,      `config_id` text DEFAULT 'default' NOT NULL,      `name` text,      `start` text,      `reference_id` text NOT NULL,      `prefix` text,      `key` text NOT NULL,      `refill_interval` integer,      `refill_amount` integer,      `last_refill_at` integer,      `enabled` integer DEFAULT true,      `rate_limit_enabled` integer DEFAULT true,      `rate_limit_time_window` integer DEFAULT 60,      `rate_limit_max` integer DEFAULT 100,      `request_count` integer DEFAULT 0,      `remaining` integer,      `last_request` integer,      `expires_at` integer,      `created_at` integer NOT NULL,      `updated_at` integer NOT NULL,      `permissions` text,      `metadata` text  );  --> statement-breakpoint  CREATE INDEX `apikey_configId_idx` ON `apikey` (`config_id`);--> statement-breakpoint  CREATE INDEX `apikey_referenceId_idx` ON `apikey` (`reference_id`);--> statement-breakpoint  CREATE INDEX `apikey_key_idx` ON `apikey` (`key`);--> statement-breakpoint  CREATE TABLE `session` (      `id` text PRIMARY KEY NOT NULL,      `expires_at` integer NOT NULL,      `token` text NOT NULL,      `created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,      `updated_at` integer NOT NULL,      `ip_address` text,      `user_agent` text,      `user_id` text NOT NULL,      FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade  );  --> statement-breakpoint  CREATE UNIQUE INDEX `session_token_unique` ON `session` (`token`);--> statement-breakpoint  CREATE INDEX `session_userId_idx` ON `session` (`user_id`);--> statement-breakpoint  CREATE TABLE `user` (      `id` text PRIMARY KEY NOT NULL,      `name` text NOT NULL,      `email` text NOT NULL,      `email_verified` integer DEFAULT false NOT NULL,      `image` text,      `created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,      `updated_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL  );  --> statement-breakpoint  CREATE UNIQUE INDEX `user_email_unique` ON `user` (`email`);--> statement-breakpoint  CREATE TABLE `verification` (      `id` text PRIMARY KEY NOT NULL,      `identifier` text NOT NULL,      `value` text NOT NULL,      `expires_at` integer NOT NULL,      `created_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL,      `updated_at` integer DEFAULT (cast(unixepoch('subsecond') * 1000 as integer)) NOT NULL  );  --> statement-breakpoint  CREATE INDEX `verification_identifier_idx` ON `verification` (`identifier`);

生成sql

npx drizzle-kit generateNo config path provided, using default 'drizzle.config.ts'Reading config file '/Users/lixiaobo/cloudflare/better-auth-cloudflare-infra-demo/drizzle.config.ts'**5 tables****account** 13 columns 1 indexes 1 fks**apikey** 22 columns 3 indexes 0 fks**session** 8 columns 2 indexes 1 fks**user** 7 columns 1 indexes 0 fks**verification** 6 columns 1 indexes 0 fks[✓] Your SQL migration file ➜ **src/db/drizzle/0000_rainy_tony_stark.sql** 🚀

createDb

import { drizzle } from "drizzle-orm/d1";import * as schema from "./schema";/**   * 创建 Drizzle D1 实例 * 在每次请求时调用,绑定 Cloudflare D1 数据库 */export const createDb = (d1: Cloudflare.Env["better_auth_cloudflare_demo"]) => {    return drizzle(d1, { schema });  };// 推导 Drizzle 实例类型  export type Database = ReturnType<typeof createDb>;

middleware

cors,为了测试

import { cors } from "hono/cors";import {isTrustedOrigin} from "../constants";export const corsMiddleware = cors({    origin: (origin) => {        if(!origin){            return null;          }        return isTrustedOrigin(origin) ? origin: null;      },    allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],    maxAge: 600,    credentials: true, // 必须设为 true,支持 Better Auth 跨域写入 Cookie  });

apikey

import { createMiddleware } from "hono/factory";import {AuthVariables} from '../types';import {ApiKeyInfo, createAuth, SessionUser} from "../lib/auth";import {PUBLIC_PATH_PREFIXES} from "../constants";import { eq } from "drizzle-orm";import {user} from "../db/schema";import {createDb} from "../db/db";export const apiKeyMiddleware = createMiddleware<AuthVariables>(async (c, next) => {    // 初始化上下文状态      c.set("user", null);      c.set("apiKey", null);      c.set("authType", null);    const isPublic = PUBLIC_PATH_PREFIXES.some(prefix=> c.req.path.startsWith(prefix));    //白名单:如果请求是去往注册、登录或其他认证接口,直接放行,不检查 API Key      if (isPublic) {        return await next();      }    // 单次请求内只创建一次 db,供 createAuth 与用户查询复用      const db = createDb(c.env.better_auth_cloudflare_demo);    const auth = createAuth(c.env, db);    const reqHeaders = c.req.raw.headers;    const authHeader = c.req.header("Authorization");    try {        // 1. 优先校验:API Key (S2S 场景)          // RFC 6750: Bearer scheme 大小写不敏感,这里做大小写不敏感判断        if (authHeader) {              const match = /^Bearer\s+(.+)$/i.exec(authHeader);            if (match) {                const plainApiKey = match[1].trim();                const verifyResult = await auth.api.verifyApiKey({                    body: {                        key: plainApiKey                      }                  });                // Better Auth 校验通过会返回 { valid: true, key: ApiKeyObject }                  if (!verifyResult || !verifyResult.key) {                    // 提供了 Bearer 但校验失败:直接 401,不再降级到 Session,                      // 避免掩盖密钥配置错误或造成鉴权语义混淆                    return c.json({ success: false, message: "未授权:无效或过期的 API Key" }, 401);                  }                  c.set("apiKey", verifyResult.key as ApiKeyInfo);                  c.set("authType", "S2S");                const userId = verifyResult.key.referenceId;                const dbUser = await db                      .select({                        id: user.id,                        name: user.name,                        email: user.email,                        emailVerified: user.emailVerified,                        image: user.image,                        createdAt: user.createdAt,                        updatedAt: user.updatedAt,                      })                      .from(user)                      .where(eq(user.id, userId))                      .get();                if (!dbUser) {                    // API Key 有效但对应用户已删除/数据不一致:视为异常,直接拦截                      console.error(`API Key 校验通过但用户不存在: key.referenceId=${userId}`);                    return c.json({ success: false, message: "未授权:API Key 关联的用户不存在" }, 401);                  }                  c.set("user", dbUser as SessionUser);                return await next();              }            // 提供了 Authorization 头但不是 Bearer 形式,按无凭据处理          }        // 2. 降级校验:Session Cookie (SPA 场景)          const session = await auth.api.getSession({ headers: reqHeaders });        if (session && session.user) {              c.set("user", session.user as SessionUser);              c.set("authType", "SPA");            return await next(); // 鉴权成功,放行          }        // 3. 两者皆无,直接拦截          return c.json({ success: false, message: "未授权:请登录或提供有效的 API Key" }, 401);      } catch (error) {        console.error("认证中间件异常:", error);        return c.json({ success: false, message: "服务器内部错误" }, 500);      }  });

index

export {apiKeyMiddleware} from './apiKey'export {corsMiddleware} from './cors'

routes

auth

import { Hono } from 'hono'import { createAuth} from "../lib/auth";import { type AuthVariables } from "../types"; // 引入你已经写好的那个完整声明  export const authRouter = new Hono<AuthVariables>();export const AuthRouterPrefix = "/auth";// 1. 核心路由托管与注册拦截  authRouter.all("/*", async (c, next) => {    const auth = createAuth(c.env);    const response = await auth.handler(c.req.raw);    const isSignUp = (c.req.method === "POST") && (c.req.path.startsWith("/api/auth/sign-up/"));    if (!response.ok) return response;    if (isSignUp && response.ok) {        try {            const data = await response.clone().json() as any;            // ... 你的前置拦截和 apiKey 申请逻辑保持不变 ...              if (data?.user?.id) {                const apiKeyResult = await auth.api.createApiKey({                    body: { name: `${data.user.name || 'User'} 的初始密钥`, userId: data.user.id }                  });                const newBodyString = JSON.stringify({                      ...data,                    apiKey: {                        id: apiKeyResult.id,                        name: apiKeyResult.name,                        secretKey: apiKeyResult.key,                        expiresAt: apiKeyResult.expiresAt                    }                  });                // 克隆原有的 headers 实例                  const newHeaders = new Headers(response.headers);                // 删掉旧的、错误的长度标记!                  // 这样边缘运行时就会根据 newBodyString 的实际长度,在发送前帮我们自动重写该字段。                newHeaders.delete("content-length");                  return new Response(newBodyString, {                    status: response.status,                    headers: newHeaders // 👈 投递修正后、安全的全新 Headers 容器                  });              }          } catch (e) { console.error(e); }      }    return response;  });

user

import { Hono } from 'hono'import { type AuthVariables } from "../types";import {createAuth} from "../lib/auth";export const userRouter = new Hono<AuthVariables>();export const UserRouterPrefix = "/user";// GET /profile 接口  userRouter.get("/profile", async (c) => {    const user = c.get("user");    if (!user) {        return c.json({ error: "unauthorized" }, 401);      }    return c.json(user);  });  userRouter.put("/updateExpire", async (c) => {    const currentUser = c.get("user");    if (!currentUser) {        return c.json({ success: false, error: "unauthorized" }, 401);      }    const auth = createAuth(c.env);    try {        const reqBody = await c.req.json().catch(() => null) as            | { keyId?: unknown; userId?: unknown; expiresIn?: unknown }              | null;        if (!reqBody) {            return c.json({ success: false, error: "Invalid request body" }, 400);          }        const { keyId, userId, expiresIn } = reqBody;        if (typeof keyId !== "string" || keyId.length === 0) {            return c.json({ success: false, error: "Missing required fields: keyId" }, 400);          }        // 仅允许属主操作自己的 API Key,防止 IDOR          const ownerUserId = typeof userId === "string" && userId.length > 0            ? userId              : currentUser.id;        if (ownerUserId !== currentUser.id) {            return c.json({ success: false, error: "forbidden: can only operate on your own API Key" }, 403);          }        // expiresIn 为可选,默认 7 天;必须是有限正整数          const rawSeconds = expiresIn !== undefined ? Number(expiresIn) : 60 * 60 * 24 * 7;        if (!Number.isFinite(rawSeconds) || rawSeconds <= 0) {            return c.json({ success: false, error: "expiresIn must be a positive finite number (seconds)" }, 400);          }        const seconds = Math.floor(rawSeconds);        const apiKeyResult = await auth.api.updateApiKey({            body: {                  keyId,                userId: ownerUserId,                expiresIn: seconds,                enabled: true            }          });        return c.json({            success: true,            apiKey: {                id: apiKeyResult.id,                name: apiKeyResult.name,                expiresAt: apiKeyResult.expiresAt // 返回给前端最新的过期绝对时间戳/字符串              }          });      } catch (e) {        console.error("Update API Key error:", e);        return c.json({ success: false, error: "Internal Server Error" }, 500);      }  });

index

import { Hono } from 'hono'import { type AuthVariables } from "../types";import {authRouter, AuthRouterPrefix} from "./auth";import {userRouter, UserRouterPrefix} from "./user";export const apiRouter = new Hono<AuthVariables>();export const ApiRouterPrefix = "/api";  apiRouter.route(AuthRouterPrefix, authRouter);  apiRouter.route(UserRouterPrefix, userRouter);

src

constants

/**   * 允许匿名访问(无需 API Key 或 Session)的公开路由前缀白名单 */export const PUBLIC_PATH_PREFIXES = [    "/api/auth/",       // 认证相关(注册、登录、第三方回调等)      "/api/public/",     // 公开的开放数据接口      "/static/"          // 静态资源文件夹  ] as const;export const TRUSTED_ORIGINS=[    "http://localhost:5173",    "https://*.better-auth-cloudflare-ui-vue-demo.pages.dev"] as const;export function isTrustedOrigin (origin: string) {    return TRUSTED_ORIGINS.some(pattern => {            if (pattern.includes("*")) {                const regex = new RegExp("^" + pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$");                return regex.test(origin);              }            return pattern === origin;          }      )  }

types

import { type SessionUser, type ApiKeyInfo } from "./lib/auth";export type AuthVariables = {    Variables: {        user: SessionUser | null;        apiKey: ApiKeyInfo | null;        authType: "SPA" | "S2S" | null;      };    Bindings: Cloudflare.Env;  };

index

import { Hono } from 'hono'import {apiKeyMiddleware, corsMiddleware} from "./middleware";import type {AuthVariables} from "./types";import {apiRouter, ApiRouterPrefix} from "./routes";const app = new Hono<AuthVariables>()  app.use("*", corsMiddleware);  app.use("*", apiKeyMiddleware);  app.route(ApiRouterPrefix, apiRouter);if (process.env.NODE_ENV !== "production") {    console.log("=== 当前可用的 API 端点列表 ===");      app.routes.forEach(r => console.log(`[${r.method}]`.padEnd(8) + r.path));    console.log("===============================");  }export default app

部署和测试

生成数据库

  • • 生成本地数据库
wrangler d1 execute better_auth_cloudflare_demo --local --file=./src/db/drizzle/0000_rainy_tony_stark.sql

迁移sql到线上

  • • 创建线上数据库
 wrangler d1 create better-auth-cloudflare-demo▲ [WARNING] **Proxy environment variables detected. We'll use your proxy for fetch requests.** ⛅️ wrangler 4.106.0────────────────────✅ Successfully created DB 'better-auth-cloudflare-demo' in region APACCreated your new D1 database.To access your new D1 Database in your Worker, add the following snippet to your configuration file:{  "d1_databases": [    {      "binding": "better_auth_cloudflare_demo",      "database_name": "better-auth-cloudflare-demo",      "database_id": "43240d79-660b-401b-9174-90d9e33a791f"    }  ]}✔ **Would you like Wrangler to add it on your behalf?** … yes✔ **What binding name would you like to use?** … better_auth_cloudflare_demo✔ **For local dev, do you want to connect to the remote resource instead of a local resource?** … yes
  • • 创建表
wrangler d1 execute better_auth_cloudflare_demo --remote --file=/Users/lixiaobo/cloudflare/better-auth-cloudflare-infra-demo/src/db/drizzle/0000_gifted_raza.sql▲ [WARNING] **Proxy environment variables detected. We'll use your proxy for fetch requests.** ⛅️ wrangler 4.106.0 (update available 4.111.0)───────────────────────────────────────────────**Resource location:** remote ✔ **⚠️ This process may take some time, during which your D1 database will be unavailable to serve queries.**  **Ok to proceed?** … yes🌀 Executing on remote database better_auth_cloudflare_demo (43240d79-660b-401b-9174-90d9e33a791f):🌀 To execute on your local development database, remove the --remote flag from your wrangler command.Note: if the execution fails to complete, your DB will return to its original state and you can safely retry.├ 🌀 Uploading 43240d79-660b-401b-9174-90d9e33a791f.1c9a1c2321650333.sql│ 🌀 Uploading complete.🌀 Starting import...🌀 Processed 13 queries.🚣 Executed 13 queries in 6.15ms (21 rows read, 23 rows written)   Database is currently at bookmark 00000001-00000006-000050aa-3970c87809b19d5438d9291a4ef87ca5.┌────────────────────────┬───────────┬──────────────┬────────────────────┐│ Total queries executed │ Rows read │ Rows written │ Database size (MB) │├────────────────────────┼───────────┼──────────────┼────────────────────┤│ 13                     │ 21        │ 23           │ 0.09               │└────────────────────────┴───────────┴──────────────┴────────────────────┘

部署worker

 wrangler deploy▲ [WARNING] **Proxy environment variables detected. We'll use your proxy for fetch requests.** ⛅️ wrangler 4.106.0 (update available 4.111.0)───────────────────────────────────────────────Cloudflare collects anonymous telemetry about your usage of Wrangler. Learn more at https://github.com/cloudflare/workers-sdk/tree/main/packages/wrangler/telemetry.mdTotal Upload: 3274.38 KiB / gzip: 541.30 KiBWorker Startup Time: 76 msYour Worker has access to the following bindings:Binding                                                                           Resource                  env.better_auth_cloudflare_demo (better-auth-cloudflare-demo)                     D1 Database               env.BETTER_AUTH_URL ("https://better-auth-cloudflare-demo.s...")                  Environment Variable      Uploaded better-auth-cloudflare-demo (16.28 sec)Deployed better-auth-cloudflare-demo triggers (2.86 sec)  https://better-auth-cloudflare-demo.shakingwaves.workers.devCurrent Version ID: 3edce064-f6ad-408c-b2c2-1e9e4f176052

测试

  • • 注册
 curl -X POST https://better-auth-cloudflare-demo.shakingwaves.workers.dev/api/auth/sign-up/email -H 'Content-Type: application/json' -d '{"email":"test@example.com","password":"12345678","name":"test"}'{"token":"UxwoNKaRUVCTslXyzm1Kh5ojhQubaOwx","user":{"name":"test","email":"test@example.com","emailVerified":false,"image":null,"createdAt":"2026-07-16T11:02:47.317Z","updatedAt":"2026-07-16T11:02:47.317Z","id":"SKBS4MauWv1CsVXdg9eC6AqM5yDnUXzg"},"apiKey":{"id":"R3tKfvaHKVNOqEf8mLl8lD7lybdqryg0","name":"test 的初始密钥","secretKey":"wsVgNDpIpjQIUtYJmJgCtnvZHatAQmdqQwdQQjpImqMuphMHhSwqqFwSkXrcdOos","expiresAt":null}}
  • • 访问,不携带secretKey
curl -X GET https://better-auth-cloudflare-demo.shakingwaves.workers.dev/api/user/profile{"success":false,"message":"未授权:请登录或提供有效的 API Key"}
  • • 访问,携带secretKey
curl -X GET https://better-auth-cloudflare-demo.shakingwaves.workers.dev/api/user/profile -H "Authorization: Bearer wsVgNDpIpjQIUtYJmJgCtnvZHatAQmdqQwdQQjpImqMuphMHhSwqqFwSkXrcdOos"{"id":"SKBS4MauWv1CsVXdg9eC6AqM5yDnUXzg","name":"test","email":"test@example.com","emailVerified":false,"image":null,"createdAt":"2026-07-16T11:02:47.317Z","updatedAt":"2026-07-16T11:02:47.317Z"}

例子

截止日期

curl -X POST https://better-auth-cloudflare-demo.shakingwaves.workers.dev/api/auth/sign-up/email -H 'Content-Type: application/json' -d '{"email":"test2@example.com","password":"12345678","name":"test"}'{"token":"eqX199U7Ppjlw2dHQY0VQZ2XR2uobTiS","user":{"name":"test","email":"test2@example.com","emailVerified":false,"image":null,"createdAt":"2026-07-17T02:23:52.512Z","updatedAt":"2026-07-17T02:23:52.512Z","id":"pinIEjvmZJ9arISFI8aoQcDAWaZtZskk"},"apiKey":{"id":"0w5HUyfHMEbf6FuNlREsrLgI1U0UM5xw","name":"test 的初始密钥","secretKey":"rCoYYJHzMPCBBmoDvEOkiodTYspzSqBputRbgzJDUSoMtcyokIdVngKgaYsBgDPy","expiresAt":null}}**%**                                                       curl -X PUT https://better-auth-cloudflare-demo.shakingwaves.workers.dev/api/user/updateExpire \-H "Authorization: Bearer rCoYYJHzMPCBBmoDvEOkiodTYspzSqBputRbgzJDUSoMtcyokIdVngKgaYsBgDPy" \-H "Content-Type: application/json" \-d '{  "keyId": "0w5HUyfHMEbf6FuNlREsrLgI1U0UM5xw",  "userId": "pinIEjvmZJ9arISFI8aoQcDAWaZtZskk",  "expiresIn": 2592000}'{"success":true,"apiKey":{"id":"0w5HUyfHMEbf6FuNlREsrLgI1U0UM5xw","name":"test 的初始密钥","expiresAt":"2026-08-16T02:24:30.732Z"}}

类似调用次数和同时在线设备数等都可以实现

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-24 03:07:46 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/863538.html
  2. 运行时间 : 0.200586s [ 吞吐率:4.99req/s ] 内存消耗:4,769.42kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=42b4eb709f6afe6bf028af979b0a1c9e
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000497s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000709s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.013568s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000284s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000511s ]
  6. SELECT * FROM `set` [ RunTime:0.001867s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000597s ]
  8. SELECT * FROM `article` WHERE `id` = 863538 LIMIT 1 [ RunTime:0.006970s ]
  9. UPDATE `article` SET `lasttime` = 1784833666 WHERE `id` = 863538 [ RunTime:0.038593s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.005659s ]
  11. SELECT * FROM `article` WHERE `id` < 863538 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000612s ]
  12. SELECT * FROM `article` WHERE `id` > 863538 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000487s ]
  13. SELECT * FROM `article` WHERE `id` < 863538 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.001796s ]
  14. SELECT * FROM `article` WHERE `id` < 863538 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.035595s ]
  15. SELECT * FROM `article` WHERE `id` < 863538 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.017274s ]
0.202550s