コンテンツにスキップ

コメントAPIの構築

Last reviewed: almost 2 years ago

このチュートリアルでは、D1を使用して静的ブログサイトにコメントを追加する方法を学びます。これを行うために、新しいD1データベースを構築し、コメントの作成と取得を可能にするJSON APIを構築します。

前提条件

Cloudflareの開発者製品用のコマンドラインツールであるC3を使用して、新しいディレクトリを作成し、新しいWorkerプロジェクトを初期化します:

Terminal window
npm create cloudflare@latest -- d1-example

For 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します:

Terminal window
cd d1-example

1. Honoをインストール

このチュートリアルでは、APIを構築するためにExpress.jsスタイルのフレームワークであるHonoを使用します。このプロジェクトでHonoを使用するには、npmを使用してインストールします:

Terminal window
npm install hono

2. Honoアプリケーションを初期化

src/worker.jsで、新しいHonoアプリケーションを初期化し、次のエンドポイントを定義します:

  • GET /api/posts/:slug/comments
  • POST /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;

3. データベースを作成

次に、D1データベースを作成します。Wrangler v2では、コマンドラインから直接D1データベースを作成およびクエリできるwrangler d1サブコマンドがサポートされています。wrangler d1 createを使用して新しいデータベースを作成します:

Terminal window
npx wrangler d1 create d1-example

作成したデータベースをWorkerコード内で参照するには、Wranglerの設定ファイルであるwrangler.tomlファイル内にbindingを作成します。バインディングを使用すると、コード内で変数名を使用してD1データベース、KV名前空間、R2バケットなどのCloudflareリソースにアクセスできます。wrangler.tomlで、DBというバインディングを設定し、database_namedatabase_idに接続します:

[[ d1_databases ]]
binding = "DB" # Worker内で`env.DB`として利用可能
database_name = "d1-example"
database_id = "4e1c28a9-90e4-41da-8b4b-6cf36e5abb29"

wrangler.tomlファイルでバインディングが設定されたので、コマンドラインおよびWorker関数内からデータベースと対話できます。

4. D1と対話

wrangler d1 executeを使用して直接SQLコマンドを発行してD1と対話します:

Terminal window
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データベースに対して実行します:

Terminal window
npx wrangler d1 execute d1-example --remote --file schemas/schema.sql

5. 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バインディングのpreparebind、およびall関数を使用してSQL文を準備し、実行します。利用可能なすべてのメソッドのリストについては、D1クライアントAPIを参照してください。

この関数では、slug URLクエリパラメータを受け入れ、クエリパラメータに一致するpost_slug値を持つすべてのコメントを選択する新しいSQL文を設定します。次に、それをJSONレスポンスとして返すことができます。

6. データを挿入

前のステップでは、データへの読み取り専用アクセスを付与しました。データベースにデータを挿入して新しいコメントを作成するには、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("何かがうまくいきませんでした");
}
});

7. Honoアプリケーションをデプロイ

アプリケーションがデプロイの準備が整ったので、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にデプロイします。

Terminal window
npx wrangler deploy

正常にデプロイされたら、関連する投稿のコメントを取得するためにGETリクエストを行ってAPIをテストします。まだ投稿がないため、このレスポンスは空になりますが、それでもD1データベースへのリクエストが行われ、アプリケーションが正しくデプロイされたことを確認できます:

Terminal window
# 注意: あなたのworkers.devデプロイメントURLは異なる場合があります
curl https://d1-example.signalnerve.workers.dev/api/posts/hello-world/comments
[
{
"id": 1,
"author": "Kristian",
"body": "コメントセクションからこんにちは!",
"post_slug": "hello-world"
}
]

8. オプションのフロントエンドでテスト

このアプリケーションはAPIバックエンドであり、コメントの作成と表示のためにフロントエンドUIと一緒に使用するのが最適です。このバックエンドを事前構築されたフロントエンドUIでテストするには、example-frontendディレクトリの例UIを参照してください。特に、loadCommentssubmitComment関数は、このサイトのデプロイ版にリクエストを行います。つまり、フロントエンドを取得し、このチュートリアルのコードベースのデプロイ版の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を訪れてください。