跳转到内容
搜索文档

使用代理 Worker 构建访问 D1 的 API

最后更新 查看 MarkdownAgent 设置

在本教程中,您将学习如何创建 API,使您能够安全地对 D1 数据库运行查询。

如果您想在 Worker 或 Pages 项目之外访问 D1 数据库、自定义访问控制 和/或 限制可查询的表,这很有用。

D1 内置的 REST API 最适合管理用途,因为适用全局 Cloudflare API 速率限制。

要在 Worker 项目之外访问 D1 数据库,您需要使用 Worker 创建 API。然后您的应用可以安全地与此 API 交互以运行 D1 查询。

前提条件

  1. 注册 Cloudflare 账户 ↗。
  2. 安装 Node.js ↗。
  3. 拥有现有 D1 数据库。请参阅 D1 快速入门教程。

Node.js version manager

使用像 Volta ↗ 或 nvm ↗ 这样的 Node 版本管理器,以避免权限问题并方便更改 Node.js 版本。本指南稍后讨论的 Wrangler 要求 Node 版本为 16.17.0 或更高。

1. 创建新项目

创建新 Worker 以创建和部署 API。

  1. 运行以下命令创建名为 d1-http 的 Worker:

    npm 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(部署前我们还会做一些修改)。
  2. 进入您的新项目目录以开始开发:

    cd d1-http

2. 安装 Hono

在本教程中,您将使用 Hono ↗(Express.js 风格框架)构建 API。

  1. 要在此项目中使用 Hono,请使用 npm 进行安装:

    npm i hono

3. 添加 API_KEY

您需要一个 API 密钥来对 API 发起经过身份验证的调用。为了确保 API 密钥的安全,请将其添加为机密(secret)。

  1. 对于本地开发,请在 d1-http 的根目录中创建一个 .dev.vars 文件。

  2. 如下所示,在文件中添加您的 API 密钥。

    .dev.varsbash
    API_KEY="YOUR_API_KEY"

    将 YOUR_API_KEY 替换为有效的字符串值。您也可以使用以下命令生成此值。

    openssl rand -base64 32

4. 初始化应用程序

要初始化应用程序,您需要导入所需的包、初始化一个新的 Hono 应用程序,并配置以下中间件:

  1. 将 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);
    });

5. 添加 API 端点

  1. 将以下代码片段添加到您的 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
  2. 通过运行以下命令启动开发服务器:

    npm run dev
  3. 要在本地测试 API,请打开第二个终端。

  4. 在第二个终端中,执行以下 cURL 命令。将 YOUR_API_KEY 替换为您在 .dev.vars 文件中设置的值。

    curl -H "Authorization: Bearer YOUR_API_KEY" "http://localhost:8787/api/all" --data '{}'

    您应该得到以下输出:

    /api/all endpoint
  5. 在第一个终端中按 x 停止本地服务器运行。

Hono 应用现已设置完成。您可以测试其他端点并根据需要添加更多端点。API 尚未从您的数据库返回任何信息。在后续步骤中,您将创建数据库、添加绑定并更新端点以与数据库交互。

6. 创建数据库

如果您还没有 D1 数据库,您可以使用 wrangler d1 create 创建一个新的数据库。

  1. 在终端中,运行:

    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)来引用数据库。

7. 添加绑定

  1. 在您的 d1-http 文件夹中,打开 Wrangler 配置文件。

  2. 在文件中添加以下绑定。确保 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"
  3. 在您的 src/index.ts 文件中,通过添加 DB: D1Database 来更新 Bindings 类型。

    type Bindings = {
    	DB: D1Database;
    	API_KEY: string;
    };

您现在可以在 Hono 应用程序中访问数据库了。

8. 创建表

要在新创建的数据库中创建表:

  1. 在您的 d1-http 文件夹内创建一个名为 schemas 的新文件夹。

  2. 创建一个名为 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 语句填充表。

  3. 在终端中,执行以下命令以创建此表:

    npx wrangler d1 execute d1-http-example --file=./schemas/schema.sql

成功执行后,一个新表将被添加到您的数据库中。

9. 查询数据库

您的应用现在可以访问 D1 数据库。在此步骤中,您将更新 API 端点以查询数据库并返回结果。

  1. In your src/index.ts file, 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。这些查询和参数会被传递给相应的函数,以便与数据库进行交互。

  • 如果查询成功,您将从数据库收到结果。
  • 如果发生错误,将返回错误消息。

10. 测试 API

既然 API 可以查询数据库了,您可以在本地对其进行测试。

  1. 通过执行以下命令启动开发服务器:

    npm run dev
  2. 在新的终端窗口中,执行以下 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'\'')" }'

如果一切实现正确,上述命令应该会产生成功的输出。

11. 部署 API

一切按预期工作后,最后一步是将其部署到 Cloudflare 网络。您将使用 Wrangler 部署 API。

  1. 要在生产环境中使用 API 而不是本地使用,您需要将表添加到远程(生产)数据库中。要将表添加到生产数据库,请运行以下命令:

    npx wrangler d1 execute d1-http-example --file=./schemas/schema.sql --remote

    您现在应该可以在 Cloudflare 仪表板 > Storage & Databases(存储与数据库) > D1 ↗ 上查看该表。

  2. 要将应用程序部署到 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)。请记录下来。

  3. 生成要在生产环境中使用的全新 API 密钥。

    openssl rand -base64 32
    [YOUR_API_KEY]
  4. 执行 wrangler secret put 命令向部署的项目中添加 API 密钥机密。

    npx wrangler secret put API_KEY
    ✔ Enter a secret value:

    终端将提示您输入密码机密值。

  5. 输入您的 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
  6. 要测试它,请使用正确的 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"}'

摘要

在本教程中,您已完成:

  1. 创建了一个与您的 D1 数据库交互的 API。
  2. 将此 API 部署到 Workers。您可以在外部应用程序中使用此 API 来针对您的 D1 数据库执行查询。本教程的完整代码可以在 GitHub ↗ 上找到。

后续步骤

您可以在 此 GitHub 仓库 ↗ 中查看使用 Zod 进行验证的类似实现。如果您想为您的 D1 数据库构建符合 OpenAPI 标准的 API,您应该使用 Cloudflare Workers OpenAPI 3.1 模板 ↗。

这篇文档对您有帮助吗?