#はじめに
最近のWebサービスは外部のサービスと連携することが当たり前になってきています。そのためにはAPI機能が必要になるわけですが、APIを持たないWebサービスも数多くあるかと思います。追加しようにもコストも時間も必要ですし、使いづらいAPIは使ってもらえません。そこで本記事では、CData API Serverを使って、Webサービスに加える修正は最小限に抑えて、API機能を追加する方法を解説します。CData API Serverはプログラミング不要で各種データベースからWeb APIを自動生成することができます。
#前提
- PC上でTomcatが起動する状態である。
- インターネットが使える環境である。
- もし、環境構成は難しいけれど、実際にサービス・API Serverをちょっと触ってみたい! 見てみたい! という方はこちらまでご連絡ください。(メールアドレス:support@cdata.co.jp)
#使用するCData製品
#Webサービス
デモ用に作成した住所検索サービスを使います。MySQLが持つ住所データを検索、閲覧、追加、削除することができます。Node.js+Express+Bootstrapで構築しました。システムの構成は下記のとおりシンプルです。
これにAPI Serverを加えると下記のような構成になります。WebサービスとAPI Serverは独立した機能ですので、既存のWebサービスに与える影響は少なく済みます。
Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
##画面構成
#API Serverをインストールする
今回はJava版を使用しますので、こちらからパッケージをダウンロードしてください。解凍すると「.war」ファイルが得られるので、これを下記のフォルダにコピーします。
<TomcatRootFolder>/webapps/
次に「tomcat-users.xml」を開き、下記の1行を追加してください。
<TomcatRootFolder>/conf/tomcat-users.xml
<user name="admin" password="xxx" roles="cdata_admin,admin-gui,manager-gui,manager-status,manager-script,manager-jmx" />
Tomcatを起動し、ブラウザから“localhost:8080/apiserver/”にアクセスし、下記のように表示されれば成功です。
※今回はTomcatはデフォルトのまま使用しますのでポート番号は8080です。
先ほど「tomcat-user.xml」に追加した管理ユーザでログインすることができます。この管理コンソールからAPI Serverの各種操作を行うことができます。初めは「情報」タブでライセンスアクティベーションが必要な旨のメッセージが表示されます。今回は評価版を使用するので「30日の評価版をアクティベート」をクリックします。この時、ライセンスサーバーとの通信が発生するため、インターネットに接続できる環境が必要です。評価版のライセンスが取得できると「プロダクトキー」の欄に文字列が表示されます。
#APIを生成する
##接続の追加
次にAPI Serverの「設定 > 接続」タブを開き、「+接続の追加」ボタンをクリックします。接続可能なDatabase一覧が表示されますので「MySQL」をクリックします。
下記のような画面が表示されますので、住所検索サービスが使用するMySQLの情報を入力し「変更を保存」をクリックします。
項目 | 設定値 |
---|---|
名前 | 任意 |
Server | MySQLサーバのFQDN |
Port | MySQLサーバのポート番号 |
Database | MySQLのデータベース名 |
User | MySQLのアカウント |
Password | MySQLのパスワード |
##リソースの追加
「設定 > リソース」タブを開き、「リソースを追加...」ボタンをクリックします。
ここでは作成済みのデータ接続の一覧が表示されますので、先ほど作成した接続名を選択し「次へ」をクリックします。
次の画面では、選択したデータベースの中のテーブル一覧が表示されますので、ここから適当なテーブルを選択します。住所検索サービスで使用するテーブルは「address」のみなので、これを選択し「次へ」をクリックします。
最後に許可する操作と取得するフィールドを選択します。今回は操作は全て許可、フィールドも全て取得するので、デフォルトのまま「保存」をクリックします。「ユーザーの許可」もデフォルトのままです。
保存後は下記のようにリソースが追加されたことを確認できます。
メニューの「API」をクリックすると下記のようにAPIの仕様について確認することができます。また同時に左側ペインの「リソース」の欄に追加したリソースに紐づくURLが表示されます。
この“/api.rsc/address”が生成されたデータアクセス用APIのURLです。これだけの操作でMySQLの「address」テーブルにアクセスするAPIが作られました。管理コンソール上でこのURLをクリックすると、各操作の具体例などを確認することができます。
データアクセス用APIの生成は以上で完了です。このようにAPIの生成自体は非常に簡単です。
#管理用API
またAPI Serverには、只今作成したデータアクセス用APIとは別に、管理用APIがあります。管理コンソールと同じことを行えますので、ここまで手動で行ってきた設定作業を自動化することができます。
##管理用APIを有効化する
デフォルトでは管理用APIはオフになっています。web.xmlファイルをエディタなどで開き、下記の1行を適当な位置に追加します。
<TomcatRootFolder>/webapp/apiserver/WEB-INF/web.xml
<security-constraint>
<display-name>Restrict direct access to the Management API</display-name>
<web-resource-collection>
<web-resource-name>Management API</web-resource-name>
<url-pattern>/admin.rsc/*</url-pattern>
<url-pattern>/admin.rst/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>cdata_admin</role-name> <!-- この1行 -->
</auth-constraint>
</security-constraint>
Tomcatを再起動後、先ほどと同じユーザで再度ログインし、管理APIアクセス用の「admin」ユーザを「設定 > ユーザー」タブから追加します。「権限」は全てにチェックし、その他はデフォルトのままです。
保存後は、下記のようにadminユーザーの「認証トークン」が表示されます。これで現在管理コンソールにログインしている「admin」ユーザに認証トークンを発行したわけです。管理用APIにアクセスする際はこのトークンを使用します。
##管理用APIの仕様書
ここまでの作業で「admin」ユーザは管理用APIへアクセスできるようになりました。管理コンソールにログインしたまま、ブラウザから下記のURLにアクセスしてみます。
http://localhost:8080/apiserver/admin.rst
下記のように管理用APIの仕様と操作可能なリソースを確認することができます。
これでAPI Serverの設定は完了です。
ここまでの作業を下記にまとめます。
- 住所検索サービスが使用しているMySQLのaddressテーブルにアクセスするためのAPIを生成した
- adminユーザのみがアクセスできる管理用APIを有効化した
#住所検索サービスの拡張
データアクセス用APIを使用するには認証トークンが必要ですので、下記のように住所検索サービスの各ユーザが認証トークンを取得できるようにプロフィール画面にフォームを追加します。
上記の画面のユーザ名「tanaka」は認証トークンを未取得なので「Web API」のフォームは空白です。ここで「認証トークン取得」をクリックすると、下記のように、管理用APIを使って生成・取得した認証トークンと共に必要な情報が表示されます。
このために、サーバサイドでは、GET/POSTリクエスト受信時に下記のような処理を実行するURL、/apiusr を1つ追加します。
- GET /apiusr
管理用API、/admin.rsc/Users にGETリクエストを送信し、取得した全ユーザの情報の中から当該ユーザの情報のみを返します。住所検索サービスでは、プロフィールページロード時に使われます。管理用APIを使用するサーバサイド(Node.js)のコードは下記のとおりです。HTTPクライアントはhttpモジュールです。
var getAPIUserInfo = function(username) {
return new Promise((resolve, reject) => {
var conf = utils.getconf(); // 認証コード等の情報をファイルから読み出し
var options = {
hostname: conf.apiserver_host,
port: parseInt(conf.apiserver_port),
path: "/apiserver/admin.rsc/Users",
method: "GET",
headers: {
"Content-Type": "application/json;charset=utf-8",
"x-cdata-authtoken": conf.apiserver_token,
},
};
var body = "";
var req = http.request(options, (res) => {
res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
var result = JSON.parse(body).value.find(v => v.UserName == username);
if(result !== undefined) resolve(result);
else resolve(null);
});
});
req.on("error", (err) => {
reject(err);
});
req.end();
});
}
- POST /apiusr
管理用API “/admin.rsc/Users”にPOSTリクエストを送信し、API Serverのユーザを新規作成します。成功すると、作成されたユーザの情報が得られるので、これをそのまま返します。情報検索サービスでは「認証トークン取得」ボタンクリック時に使われます。管理用APIを使用するサーバサイド(Node.js)のコードは下記のとおりです。
var createAPIUser = function(username) {
return new Promise((resolve, reject) => {
var conf = utils.getconf(); // 認証コード等の情報をファイルから読み出し
var options = {
hostname: conf.apiserver_host,
port: parseInt(conf.apiserver_port),
path: "/apiserver/admin.rsc/Users",
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
"x-cdata-authtoken": conf.apiserver_token,
},
};
var body = "";
var req = http.request(options, (res) => {
res.on("data", chunk => {
body += chunk;
});
res.on("end", () => {
var result = JSON.parse(body);
if("error" in result) throw new Error(result.error.message);
else resolve(result);
});
});
req.on("error", (err) => {
reject(err);
});
var postdata = JSON.stringify({
"@odata.type":"CDataAPI.Users.rsd",
"UserName": username,
"Privileges": "GET,POST,DELETE",
});
req.write(postdata);
req.end();
});
}
住所検索サービスの拡張は以上で終了です。
このようにAPI Serverを使うことで既存のWebサービスにAPI機能をアドオンすることができます。認証トークンを発行する手続きは必要なので、Webサービスを少々修正する必要はあるかと思いますが、一からAPIを実装する手間ほどではないでしょう。
住所検索サービスのソースコードはこちらから入手できます。
#ユーザに公開されたAPIを使ってみる
POSTMANを使って、公開されたデータアクセス用APIを使ってみます。住所検索サービスのプロフィール画面に表示されている情報を各項目に入力して「Send」をクリックします。下記のように画面下にはレスポンスが表示され、住所データが取得できていることが分かります。
-
リクエストタイプ : GET
-
リクエストヘッダー
- x-cdata-authtoken : 認証トークン
- Content-Type : application/json;charset=utf-8
さらに、フィルターを付加してみます。下記のように、URLのクエリストリングとして、JSON ODataフォーマットでフィルタ条件を記述します。この例では、郵便番号(フィールド名:zip)が“9800811”に一致する、という条件でデータを取得しています。
http://localhost:8080/apiserver/api.rsc/address?$filter=zip eq '9800811'
#補足
管理用APIを使ってユーザを追加するリクエストをPOSTMANを使って見てみます。
-
リクエストタイプ :POST
-
リクエストヘッダー
- x-cdata-authtoken : API Server adminユーザの認証トークン
- Content-Type : application/json;charset=utf-8
-
Body(JSON形式)
- "@odata.type" : "CDataAPI.Users.rsd" ※これは固定
- "UserName" : 新規に作成するユーザ名
- "Privileges" : ユーザに許可する操作 ※今回のWebサービスではGET/POST/DELETE
このリクエストに対し、下記のようなレスポンスが得られます。「AuthToken」が認証トークン、「Privileges」が許可された操作の情報です。