Web API

Web API とは、Web 上のシステム間インターフェース、つまりデータを受け渡しするための規約のことです。この Web API を実装することで、ブラウザなどから HTTP や HTTPS を通じてデータの受け渡しができるようになります。

Web API はサービス提供側が自由に実装するわけですが、多くのクラウドサービスでは、デザイン思想は REST スタイル、データフォーマットは JSON の Web API が提供されています。

Web API をスキャフォールディング

TreeFrog では、1つテーブルからデータを CRUD する Web API の足場を簡単に作ることができます。
例えば、次のようなテーブルがあったとします。

sqlite> .schema blog CREATE TABLE blog (id INTEGER PRIMARY KEY AUTOINCREMENT, title VARCHAR(20), body VARCHAR(200), created_at TIMESTAMP, updated_at TIMESTAMP, lock_revision INTEGER); 

このテーブルに対して、次のコマンドで Web API の足場を作ります。

$ tspawn api blog DriverType: QSQLITE DatabaseName: db/dbfile HostName: Database opened successfully created models/sqlobjects/blogobject.h created models/objects/blog.h created models/objects/blog.cpp updated models/models.pro created models/apiblogservice.h created models/apiblogservice.cpp updated models/models.pro created controllers/apiblogcontroller.h created controllers/apiblogcontroller.cpp updated controllers/controllers.pro 

コントローラやサービスクラスなどのソースファイルが生成されました。ここで作られる Web API のデータフォーマットは JSON になります。

Web API のエントリーポイントは次のようにコントローラ apiblogcontroller.h に定義されます。

class T_CONTROLLER_EXPORT ApiBlogController : public ApplicationController { Q_OBJECT public slots: void index(); // 一覧取得 void get(const QString &id); // 1件取得 void create(); // 新規登録 void save(const QString &id); // 保存(更新) void remove(const QString &id); // 1件削除 }; 

これらのエントリーポイントは次のとおりです。

/apiblog/index /apiblog/get/(id) /apiblog/create /apiblog/save/(id) /apiblog/remove/(id) 

Web API の動作確認

ソースをビルドし、サーバを起動します。

 $ make $ treefrog -e dev -d 

curl コマンドで Web API の動作確認してみましょう。

$ curl -sS http://localhost:8800/apiblog/index {"data":[]} 

何もデータが登録されていないので、空の JSON データが取得されました。

エントリーポイント追加

デフォルトのエントリーポイントに加え、config/routes.cfg に項目を記述することでエントリーポイントを追加することができます。例えば、次のように記述します。

# Method Entry-point Function get /api/blog/index ApiBlog.index get /api/blog/get/:param ApiBlog.get post /api/blog/create ApiBlog.create post /api/blog/save/:param ApiBlog.save post /api/blog/remove/:param ApiBlog.remove 

正しく追加されたかをチェックします。

$ treefrog --show-routes Available routes: get /api/blog/index -> apiblogcontroller.index() get /api/blog/get/:param -> apiblogcontroller.get(id) post /api/blog/create -> apiblogcontroller.create() post /api/blog/save/:param -> apiblogcontroller.save(id) post /api/blog/remove/:param -> apiblogcontroller.remove(id) 

GET や POST の他に PUT や DELETE も追加することができます。詳しくは URL ルーティング のページを参照してください。

curl コマンドで追加したエントリーポイントの動作確認してみましょう。

$ curl -sS http://localhost:8800/api/blog/index ← 追加したエントリーポイント {"data":[]} 

同じように、空の JSON データを取得することができました。

登録用の Web API

次にデータを 1 件登録してみましょう。curl コマンドで JSON データを POST します。

$ curl -sS -X POST -H "Content-Type: application/json" -d '{"title":"Hello","body":"hello world"}' http://localhost:8800/api/blog/create 

もう一度、一覧を取得してみます。

$ curl -sS http://localhost:8800/api/blog/index {"data":[{"body":"hello world","createdAt":"2022-05-25T16:39:02.142","id":1,"lockRevision":1,"title":"Hello","updatedAt":"2022-05-25T16:39:02.142"}]} 

今後は一覧のデータを正しく取得できました。

ID を指定してデータを取得してみましょう。

$ curl -sS http://localhost:8800/api/blog/get/1 {"data":{"body":"hello world","createdAt":"2022-05-25T16:39:02.142","id":1,"lockRevision":1,"title":"Hello","updatedAt":"2022-05-25T16:39:02.142"}} 

正しく取得できました。

返却するプロパティを制限する

スキャフォールディング後のソースでは、DB レコードのカラムの全データが返却されていましたが、返却データ(プロパティ)を制限してみましょう。

サービスクラス apiblogservice.cpp を編集します。

QJsonObject ApiBlogService::index() { auto blogList = Blog::getAll(); QJsonObject json = { {"data", tfConvertToJsonArray(blogList, {"id", "title", "body"})} }; // ←ここ return json; } QJsonObject ApiBlogService::get(int id) { auto blog = Blog::get(id); QJsonObject json = { {"data", blog.toJsonObject({"id", "title", "body"})} }; // ←ここ return json; } 

ビルド後に、curl コマンドで確認してみると、指定したプロパティのみ返却されています。

$ curl -sS http://localhost:8800/api/blog/index {"data":[{"body":"hello world","id":1,"title":"Hello"}]} $ curl -sS http://localhost:8800/api/blog/get/1 {"data":{"body":"hello world","id":1,"title":"Hello"}} 

まとめ

スキャフォールディングでシンプルな Web API を作成することができました。

実際のケースでは、このスキャフォールディングで作られた実装では不十分でしょう。例えば、2 つ以上のテーブルからデータを取得し、階層化された JSON データを返すことがあります。その場合はサービスクラスなどを適宜修正して、実装してください。