在本教程中,您将学习如何创建 API,使您能够安全地对 D1 数据库运行查询。
如果您想在 Worker 或 Pages 项目之外访问 D1 数据库、自定义访问控制 和/或 限制可查询的表,这很有用。
D1 内置的 REST API 最适合管理用途,因为适用全局 Cloudflare API 速率限制。
要在 Worker 项目之外访问 D1 数据库,您需要使用 Worker 创建 API。然后您的应用可以安全地与此 API 交互以运行 D1 查询。
- 注册 Cloudflare 账户 ↗。
- 安装
Node.js↗。 - 拥有现有 D1 数据库。请参阅 D1 快速入门教程。
Node.js version manager
使用像 Volta ↗ 或 nvm ↗ 这样的 Node 版本管理器,以避免权限问题并方便更改 Node.js 版本。本指南稍后讨论的 Wrangler 要求 Node 版本为 16.17.0 或更高。
创建新 Worker 以创建和部署 API。
-
运行以下命令创建名为
d1-http的 Worker:npm create cloudflare@latest -- d1-httpyarn create cloudflare d1-httppnpm create cloudflare@latest d1-http进行设置时,请选择以下选项:
- 对于 What would you like to start with?,选择
Hello World example。 - 对于 Which template would you like to use?,选择
Worker only。 - 对于 Which language do you want to use?,选择
TypeScript。 - 对于 Do you want to use git for version control?,选择
Yes。 - 对于 Do you want to deploy your application?,选择
No(部署前我们还会做一些修改)。
- 对于 What would you like to start with?,选择
-
进入您的新项目目录以开始开发:
cd d1-http
在本教程中,您将使用 Hono ↗(Express.js 风格框架)构建 API。
-
要在此项目中使用 Hono,请使用
npm进行安装:npm i honoyarn add honopnpm add honobun add hono
您需要一个 API 密钥来对 API 发起经过身份验证的调用。为了确保 API 密钥的安全,请将其添加为机密(secret)。
-
对于本地开发,请在
d1-http的根目录中创建一个.dev.vars文件。 -
如下所示,在文件中添加您的 API 密钥。
.dev.varsbash API_KEY="YOUR_API_KEY"将
YOUR_API_KEY替换为有效的字符串值。您也可以使用以下命令生成此值。openssl rand -base64 32
要初始化应用程序,您需要导入所需的包、初始化一个新的 Hono 应用程序,并配置以下中间件:
- Bearer 身份验证 ↗:向 API 添加身份验证。
- Logger ↗:允许监控请求和响应流。
- Pretty JSON ↗:为 JSON 响应体启用 “JSON 美化打印”。
-
将
src/index.ts文件的内容替换为以下代码。src/index.tsts import { Hono } from "hono"; import { bearerAuth } from "hono/bearer-auth"; import { logger } from "hono/logger"; import { prettyJSON } from "hono/pretty-json"; type Bindings = { API_KEY: string; }; const app = new Hono<{ Bindings: Bindings }>(); app.use("*", prettyJSON(), logger(), async (c, next) => { const auth = bearerAuth({ token: c.env.API_KEY }); return auth(c, next); });
-
将以下代码片段添加到您的
src/index.ts中。src/index.tsts // 将此代码粘贴在 src/index.ts 文件的末尾 app.post("/api/all", async (c) => { return c.text("/api/all endpoint"); }); app.post("/api/exec", async (c) => { return c.text("/api/exec endpoint"); }); app.post("/api/batch", async (c) => { return c.text("/api/batch endpoint"); }); export default app;这将添加以下端点:
- POST
/api/all - POST
/api/exec - POST
/api/batch
- POST
-
通过运行以下命令启动开发服务器:
npm run devyarn run devpnpm run dev -
要在本地测试 API,请打开第二个终端。
-
在第二个终端中,执行以下 cURL 命令。将
YOUR_API_KEY替换为您在.dev.vars文件中设置的值。curl -H "Authorization: Bearer YOUR_API_KEY" "http://localhost:8787/api/all" --data '{}'您应该得到以下输出:
/api/all endpoint -
在第一个终端中按
x停止本地服务器运行。
Hono 应用现已设置完成。您可以测试其他端点并根据需要添加更多端点。API 尚未从您的数据库返回任何信息。在后续步骤中,您将创建数据库、添加绑定并更新端点以与数据库交互。
如果您还没有 D1 数据库,您可以使用 wrangler d1 create 创建一个新的数据库。
-
在终端中,运行:
npx wrangler d1 create d1-http-example系统可能会要求您登录 Cloudflare 账户。登录后,该命令将创建一个新的 D1 数据库。您应该在终端中看到类似的输出。
✅ Successfully created DB 'd1-http-example' in region EEUR Created your new D1 database. [[d1_databases]] binding = "DB" # 即在您的 Worker 中可通过 env.DB 使用 database_name = "d1-http-example" database_id = "1234567890"
记下显示的 database_name 和 database_id。您将通过创建绑定(binding)来引用数据库。
-
在您的
d1-http文件夹中,打开 Wrangler 配置文件。 -
在文件中添加以下绑定。确保
database_name和database_id正确无误。{ "d1_databases": [ { "binding": "DB", // 即在您的 Worker 中可通过 env.DB 使用 "database_name": "d1-http-example", "database_id": "1234567890" } ] }[[d1_databases]] binding = "DB" database_name = "d1-http-example" database_id = "1234567890" -
在您的
src/index.ts文件中,通过添加DB: D1Database来更新Bindings类型。type Bindings = { DB: D1Database; API_KEY: string; };
您现在可以在 Hono 应用程序中访问数据库了。
要在新创建的数据库中创建表:
-
在您的
d1-http文件夹内创建一个名为schemas的新文件夹。 -
创建一个名为
schema.sql的新文件,并将以下 SQL 语句粘贴到该文件中。schema.sqlsql DROP TABLE IF EXISTS posts; CREATE TABLE IF NOT EXISTS posts ( id integer PRIMARY KEY AUTOINCREMENT, author text NOT NULL, title text NOT NULL, body text NOT NULL, post_slug text NOT NULL ); INSERT INTO posts (author, title, body, post_slug) VALUES ('Harshil', 'D1 HTTP API', 'Learn to create an API to query 您的 D1 数据库.','d1-http-api');该代码会删除名为
posts的现有表(如果存在),然后创建一个具有id、author、title、body和post_slug字段的新表posts。接着使用INSERT语句填充表。 -
在终端中,执行以下命令以创建此表:
npx wrangler d1 execute d1-http-example --file=./schemas/schema.sql
成功执行后,一个新表将被添加到您的数据库中。
您的应用现在可以访问 D1 数据库。在此步骤中,您将更新 API 端点以查询数据库并返回结果。
-
In your
src/index.tsfile, update the code as follow.src/index.tsts // 更新 API routes /** * 执行 stmt.run() 方法。 * https://developers.cloudflare.com/d1/worker-api/prepared-statements/#run */ app.post('/api/all', async (c) => { return c.text("/api/all endpoint"); try { let { query, params } = await c.req.json(); let stmt = c.env.DB.prepare(query); if (params) { stmt = stmt.bind(params); } const result = await stmt.run(); return c.json(result); } catch (err) { return c.json({ error: `Failed to run query: ${err}` }, 500); } }); /** * 执行 db.exec() 方法。 * https://developers.cloudflare.com/d1/worker-api/d1-database/#exec */ app.post('/api/exec', async (c) => { return c.text("/api/exec endpoint"); try { let { query } = await c.req.json(); let result = await c.env.DB.exec(query); return c.json(result); } catch (err) { return c.json({ error: `Failed to run query: ${err}` }, 500); } }); /** * 执行 db.batch() 方法。 * https://developers.cloudflare.com/d1/worker-api/d1-database/#batch */ app.post('/api/batch', async (c) => { return c.text("/api/batch endpoint"); try { let { batch } = await c.req.json(); let stmts = []; for (let query of batch) { let stmt = c.env.DB.prepare(query.query); if (query.params) { stmts.push(stmt.bind(query.params)); } else { stmts.push(stmt); } } const results = await c.env.DB.batch(stmts); return c.json(results); } catch (err) { return c.json({ error: `Failed to run query: ${err}` }, 500); } }); ...
在上述代码中,端点已被更新以接收 query 和 params。这些查询和参数会被传递给相应的函数,以便与数据库进行交互。
- 如果查询成功,您将从数据库收到结果。
- 如果发生错误,将返回错误消息。
既然 API 可以查询数据库了,您可以在本地对其进行测试。
-
通过执行以下命令启动开发服务器:
npm run devyarn run devpnpm run dev -
在新的终端窗口中,执行以下 cURL 命令。确保将
YOUR_API_KEY替换为正确的值。/api/allsh curl -H "Authorization: Bearer YOUR_API_KEY" "http://localhost:8787/api/all" --data '{"query": "SELECT title FROM posts WHERE id=?", "params":1}'/api/batchsh curl -H "Authorization: Bearer YOUR_API_KEY" "http://localhost:8787/api/batch" --data '{"batch": [ {"query": "SELECT title FROM posts WHERE id=?", "params":1},{"query": "SELECT id FROM posts"}]}'/api/execsh curl -H "Authorization: Bearer YOUR_API_KEY" "localhost:8787/api/exec" --data '{"query": "INSERT INTO posts (author, title, body, post_slug) VALUES ('\''Harshil'\'', '\''D1 HTTP API'\'', '\''Learn to create an API to query 您的 D1 数据库.'\'','\''d1-http-api'\'')" }'
如果一切实现正确,上述命令应该会产生成功的输出。
一切按预期工作后,最后一步是将其部署到 Cloudflare 网络。您将使用 Wrangler 部署 API。
-
要在生产环境中使用 API 而不是本地使用,您需要将表添加到远程(生产)数据库中。要将表添加到生产数据库,请运行以下命令:
npx wrangler d1 execute d1-http-example --file=./schemas/schema.sql --remote您现在应该可以在 Cloudflare 仪表板 > Storage & Databases(存储与数据库) > D1 ↗ 上查看该表。
-
要将应用程序部署到 Cloudflare 网络,请运行以下命令:
npx wrangler deploy⛅️ wrangler 3.78.4 (update available 3.78.5) ------------------------------------------------------- Total Upload: 53.00 KiB / gzip: 13.16 KiB Your worker has access to the following bindings: - D1 Databases: - DB: d1-http-example (DATABASE_ID) Uploaded d1-http (4.29 sec) Deployed d1-http triggers (5.57 sec) [DEPLOYED_APP_LINK] Current Version ID: [BINDING_ID]部署成功后,您将在终端中获取已部署应用的链接(
DEPLOYED_APP_LINK)。请记录下来。 -
生成要在生产环境中使用的全新 API 密钥。
openssl rand -base64 32[YOUR_API_KEY] -
执行
wrangler secret put命令向部署的项目中添加 API 密钥机密。npx wrangler secret put API_KEY✔ Enter a secret value:终端将提示您输入密码机密值。
-
输入您的 API 密钥的值(
YOUR_API_KEY)。现在您的 API 密钥将被添加到您的项目中。使用此值,您可以向已部署的 API 发起安全的 API 调用。✔ Enter a secret value: [YOUR_API_KEY]🌀 Creating the secret for the Worker "d1-http" ✨ Success! Uploaded secret API_KEY -
要测试它,请使用正确的
YOUR_API_KEY和DEPLOYED_APP_LINK运行以下 cURL 命令。- 使用您生成的
YOUR_API_KEY作为机密 API 密钥。 - 您也可以在 Cloudflare 仪表板 > Workers & Pages >
d1-http> Settings(设置) > Domains & Routes(域与路由) 中找到您的DEPLOYED_APP_LINK。
curl -H "Authorization: Bearer YOUR_API_KEY" "https://DEPLOYED_APP_LINK/api/exec" --data '{"query": "SELECT 1"}' - 使用您生成的
在本教程中,您已完成:
- 创建了一个与您的 D1 数据库交互的 API。
- 将此 API 部署到 Workers。您可以在外部应用程序中使用此 API 来针对您的 D1 数据库执行查询。本教程的完整代码可以在 GitHub ↗ 上找到。
您可以在 此 GitHub 仓库 ↗ 中查看使用 Zod 进行验证的类似实现。如果您想为您的 D1 数据库构建符合 OpenAPI 标准的 API,您应该使用 Cloudflare Workers OpenAPI 3.1 模板 ↗。