コメントAPIの構築
このチュートリアルでは、D1を使用して静的ブログサイトにコメントを追加する方法を学びます。これを行うために、新しいD1データベースを構築し、コメントの作成と取得を可能にするJSON APIを構築します。
Cloudflareの開発者製品用のコマンドラインツールであるC3 ↗を使用して、新しいディレクトリを作成し、新しいWorkerプロジェクトを初期化します:
npm create cloudflare@latest -- d1-exampleyarn create cloudflare@latest d1-examplepnpm create cloudflare@latest d1-exampleFor setup, select the following options:
- For What would you like to start with?, choose
Hello Worldの例. - For Which template would you like to use?, choose
Hello World Worker. - For Which language do you want to use?, choose
JavaScript. - For Do you want to use git for version control?, choose
Yes. - For Do you want to deploy your application?, choose
No(we will be making some changes before deploying).
Workerの開発を開始するには、新しいプロジェクトディレクトリにcdします:
cd d1-exampleこのチュートリアルでは、APIを構築するためにExpress.jsスタイルのフレームワークであるHono ↗を使用します。このプロジェクトでHonoを使用するには、npmを使用してインストールします:
npm install honosrc/worker.jsで、新しいHonoアプリケーションを初期化し、次のエンドポイントを定義します:
GET /api/posts/:slug/commentsPOST /api/posts/:slug/comments
import { Hono } from "hono";
const app = new Hono();
app.get("/api/posts/:slug/comments", async (c) => { // 何かを行い、HTTPレスポンスを返します // オプションで、`c.req.param("slug")`を使用して何かを行います});
app.post("/api/posts/:slug/comments", async (c) => { // 何かを行い、HTTPレスポンスを返します // オプションで、`c.req.param("slug")`を使用して何かを行います});
export default app;次に、D1データベースを作成します。Wrangler v2では、コマンドラインから直接D1データベースを作成およびクエリできるwrangler d1サブコマンドがサポートされています。wrangler d1 createを使用して新しいデータベースを作成します:
npx wrangler d1 create d1-example作成したデータベースをWorkerコード内で参照するには、Wranglerの設定ファイルであるwrangler.tomlファイル内にbindingを作成します。バインディングを使用すると、コード内で変数名を使用してD1データベース、KV名前空間、R2バケットなどのCloudflareリソースにアクセスできます。wrangler.tomlで、DBというバインディングを設定し、database_nameとdatabase_idに接続します:
[[ d1_databases ]]binding = "DB" # Worker内で`env.DB`として利用可能database_name = "d1-example"database_id = "4e1c28a9-90e4-41da-8b4b-6cf36e5abb29"wrangler.tomlファイルでバインディングが設定されたので、コマンドラインおよびWorker関数内からデータベースと対話できます。
wrangler d1 executeを使用して直接SQLコマンドを発行してD1と対話します:
npx wrangler d1 execute d1-example --remote --command "SELECT name FROM sqlite_schema WHERE type ='table'"d1-exampleで実行中:
┌───────┐│ name │├───────┤│ d1_kv │└───────┘SQLファイルを渡すこともできます - 初期データのシーディングに最適です。schemas/schema.sqlを作成し、プロジェクト用の新しいcommentsテーブルを作成します:
DROP TABLE IF EXISTS comments;CREATE TABLE IF NOT EXISTS comments ( id integer PRIMARY KEY AUTOINCREMENT, author text NOT NULL, body text NOT NULL, post_slug text NOT NULL);CREATE INDEX idx_comments_post_slug ON comments (post_slug);
-- オプションで、以下のクエリのコメントを外してデータを作成します
-- INSERT INTO COMMENTS (author, body, post_slug) VALUES ('Kristian', '素晴らしい投稿!', 'hello-world');ファイルを作成したら、--fileフラグを使用してスキーマファイルをD1データベースに対して実行します:
npx wrangler d1 execute d1-example --remote --file schemas/schema.sql前のステップで、SQLデータベースを作成し、初期データでポピュレートしました。次に、Workers関数にルートを追加して、そのデータベースからデータを取得します。前のステップでのwrangler.toml設定に基づいて、D1データベースはDBバインディングを介してアクセス可能です。コード内でバインディングを使用してSQL文を準備し、実行します。たとえば、コメントを取得するために:
app.get("/api/posts/:slug/comments", async (c) => { const { slug } = c.req.param(); const { results } = await c.env.DB.prepare( ` select * from comments where post_slug = ? `, ) .bind(slug) .all(); return c.json(results);});上記のコードは、D1バインディングのprepare、bind、およびall関数を使用してSQL文を準備し、実行します。利用可能なすべてのメソッドのリストについては、D1クライアントAPIを参照してください。
この関数では、slug URLクエリパラメータを受け入れ、クエリパラメータに一致するpost_slug値を持つすべてのコメントを選択する新しいSQL文を設定します。次に、それをJSONレスポンスとして返すことができます。
前のステップでは、データへの読み取り専用アクセスを付与しました。データベースにデータを挿入して新しいコメントを作成するには、src/worker.jsに別のエンドポイントを定義します:
app.post("/api/posts/:slug/comments", async (c) => { const { slug } = c.req.param(); const { author, body } = await c.req.json();
if (!author) return c.text("新しいコメントの著者値が欠けています"); if (!body) return c.text("新しいコメントの本文値が欠けています");
const { success } = await c.env.DB.prepare( ` insert into comments (author, body, post_slug) values (?, ?, ?) `, ) .bind(author, body, slug) .run();
if (success) { c.status(201); return c.text("作成されました"); } else { c.status(500); return c.text("何かがうまくいきませんでした"); }});アプリケーションがデプロイの準備が整ったので、Wranglerを使用してプロジェクトをCloudflareネットワークにビルドしてデプロイします。
まず、wrangler whoamiを実行して、Cloudflareアカウントにログインしていることを確認します。ログインしていない場合、Wranglerはログインを促し、ローカルマシンから自動的に認証されたリクエストを行うために使用できるAPIキーを作成します。
ログインしたら、wrangler.tomlファイルが以下のように設定されていることを確認します。nameフィールドをお好みのプロジェクト名に変更できます:
name = "d1-example"main = "src/worker.js"compatibility_date = "2022-07-15"
[[ d1_databases ]]binding = "DB" # Worker内でenv.DBとして利用可能database_name = "<YOUR_DATABASE_NAME>"database_id = "<YOUR_DATABASE_UUID>"次に、npx wrangler deployを実行して、プロジェクトをCloudflareにデプロイします。
npx wrangler deploy正常にデプロイされたら、関連する投稿のコメントを取得するためにGETリクエストを行ってAPIをテストします。まだ投稿がないため、このレスポンスは空になりますが、それでもD1データベースへのリクエストが行われ、アプリケーションが正しくデプロイされたことを確認できます:
# 注意: あなたのworkers.devデプロイメントURLは異なる場合がありますcurl https://d1-example.signalnerve.workers.dev/api/posts/hello-world/comments[ { "id": 1, "author": "Kristian", "body": "コメントセクションからこんにちは!", "post_slug": "hello-world" }]このアプリケーションはAPIバックエンドであり、コメントの作成と表示のためにフロントエンドUIと一緒に使用するのが最適です。このバックエンドを事前構築されたフロントエンドUIでテストするには、example-frontendディレクトリ ↗の例UIを参照してください。特に、loadCommentsとsubmitComment関数 ↗は、このサイトのデプロイ版にリクエストを行います。つまり、フロントエンドを取得し、このチュートリアルのコードベースのデプロイ版のURLに置き換えて、自分のデータを使用できます。
フロントエンドからこのAPIと対話するには、バックエンドAPIで特定のクロスオリジンリソース共有(CORS)ヘッダーを有効にする必要があります。Honoを使用すると、アプリケーションのクロスオリジンリソース共有を有効にできます。corsモジュールをインポートし、src/worker.jsのAPIにミドルウェアとして追加します:
import { Hono } from "hono";import { cors } from "hono/cors";
const app = new Hono();app.use("/api/*", cors());これで、/api/*へのリクエストを行うと、Honoは自動的にCORSヘッダーを生成し、APIからのレスポンスに追加します。これにより、フロントエンドUIがエラーなしでAPIと対話できるようになります。
この例では、ブログを支えるコメントAPIを構築しました。このD1を使用したコメントAPIの完全なソースを見るには、cloudflare/workers-sdk/templates/worker-d1-api ↗を訪れてください。