このチュートリアルでは、D1 データベースに対して安全にクエリを実行できる API の作成方法を学びます。
Worker や Pages プロジェクトの外から D1 データベースへアクセスしたい場合、アクセス制御をカスタマイズしたい場合、クエリ可能なテーブルを制限したい場合に役立ちます。
D1 組み込みの REST API は、グローバルな Cloudflare API レート制限 が適用されるため、管理用途に向いています。
Worker プロジェクトの外から D1 データベースへアクセスするには、Worker で API を作成します。アプリケーションはその API と安全にやり取りして、D1 クエリを実行できます。
- Cloudflare アカウント ↗ にサインアップします。
Node.js↗ をインストールします。- 既存の D1 データベースがあること。D1 の始め方 を参照してください。
Node.js のバージョン管理
権限の問題を避け、Node.js のバージョンを切り替えるには、Volta ↗ や
nvm ↗ などの Node バージョンマネージャーを使います。このガイドで後述する
Wrangler には、16.17.0 以降の Node バージョンが必要です。
API を作成してデプロイするための、新しい Worker を作成します。
-
次を実行して、
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
このチュートリアルでは、Express.js 風のフレームワークである Hono ↗ を使って 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 Auth ↗: API に認証を追加します。
- Logger ↗: リクエストとレスポンスの流れを監視できます。
- Pretty JSON ↗: JSON レスポンス本文の "JSON pretty print" を有効にします。
-
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 // Paste this code at the end of the src/index.ts file 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 をローカルでテストするには、2 つ目のターミナルを開きます。
-
2 つ目のターミナルで、次の cURL コマンドを実行します。
YOUR_API_KEYを.dev.varsファイルで設定した値に置き換えます。curl -H "Authorization: Bearer YOUR_API_KEY" "http://localhost:8787/api/all" --data '{}'次の出力になります。
/api/all endpoint -
1 つ目のターミナルで
xを押して、ローカルサーバーを停止します。
Hono アプリケーションの準備ができました。ほかのエンドポイントをテストしたり、必要に応じてエンドポイントを追加したりできます。この時点では、API はデータベースからの情報をまだ返しません。次の手順でデータベースを作成し、バインディングを追加し、データベースとやり取りするようにエンドポイントを更新します。
まだ D1 データベースがない場合は、wrangler d1 create で新しいデータベースを作成できます。
-
ターミナルで次を実行します。
npx wrangler d1 create d1-http-exampleCloudflare アカウントへのログインを求められる場合があります。ログインすると、コマンドは新しい D1 データベースを作成します。ターミナルに次のような出力が表示されます。
✅ Successfully created DB 'd1-http-example' in region EEUR Created your new D1 database. [[d1_databases]] binding = "DB" # i.e. available in your Worker on env.DB database_name = "d1-http-example" database_id = "1234567890"
表示された database_name と database_id を控えます。バインディング を作成して、このデータベースを参照します。
-
d1-httpフォルダーから、Wrangler の設定ファイルである Wrangler ファイルを開きます。 -
ファイルに次のバインディングを追加します。
database_nameとdatabase_idが正しいことを確認します。{ "d1_databases": [ { "binding": "DB", // i.e. available in your Worker on 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ファイルで、Bindings型にDB: D1Databaseを追加して更新します。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 your D1 database.','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 エンドポイントを更新します。
-
src/index.tsファイルのコードを、次のように更新します。src/index.tsts // Update the API routes /** * Executes the `stmt.run()` method. * 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); } }); /** * Executes the `db.exec()` method. * 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); } }); /** * Executes the `db.batch()` method. * 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 your D1 database.'\'','\''d1-http-api'\'')" }'
正しく実装されていれば、上記のコマンドは成功した結果になります。
期待どおりに動作するようになったので、最後の手順は Cloudflare ネットワークへのデプロイです。API のデプロイには Wrangler を使います。
-
ローカルではなく本番で API を使うには、リモート(本番)データベースにテーブルを追加する必要があります。本番データベースにテーブルを追加するには、次のコマンドを実行します。
npx wrangler d1 execute d1-http-example --file=./schemas/schema.sql --remoteCloudflare ダッシュボード > 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 コマンドを実行します。- シークレットの API キーとして、生成した
YOUR_API_KEYを使います。 DEPLOYED_APP_LINKは、Cloudflare ダッシュボード > Workers & Pages >d1-http> Settings > Domains & Routes でも確認できます。
curl -H "Authorization: Bearer YOUR_API_KEY" "https://DEPLOYED_APP_LINK/api/exec" --data '{"query": "SELECT 1"}' - シークレットの API キーとして、生成した
このチュートリアルでは、次を行いました。
- D1 データベースとやり取りする API を作成しました。
- この API を Workers へデプロイしました。外部アプリケーションからこの API を使い、D1 データベースに対してクエリを実行できます。このチュートリアルの完全なコードは GitHub ↗ にあります。
検証に Zod を使う類似の実装は、この GitHub リポジトリ ↗ で確認できます。D1 データベース向けの OpenAPI 準拠 API を構築する場合は、Cloudflare Workers OpenAPI 3.1 テンプレート ↗ を使ってください。