2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CData API Serverを使って既存のWebサービスにRESTfulなAPIを追加してみた

Last updated at Posted at 2018-10-09

#はじめに
最近の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で構築しました。システムの構成は下記のとおりシンプルです。
legacySystem.PNG

これにAPI Serverを加えると下記のような構成になります。WebサービスとAPI Serverは独立した機能ですので、既存のWebサービスに与える影響は少なく済みます。
newSystem.PNG

Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY

##画面構成

  • ログイン画面
    login.PNG

  • メイン画面
    郵便番号、住所を検索、閲覧、追加、削除することができます。
    main.PNG

  • プロフィール画面
    ユーザ名の確認、パスワードの変更を行うことができます。
    profile.PNG

#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です。
APIServerLogin.PNG

先ほど「tomcat-user.xml」に追加した管理ユーザでログインすることができます。この管理コンソールからAPI Serverの各種操作を行うことができます。初めは「情報」タブでライセンスアクティベーションが必要な旨のメッセージが表示されます。今回は評価版を使用するので「30日の評価版をアクティベート」をクリックします。この時、ライセンスサーバーとの通信が発生するため、インターネットに接続できる環境が必要です。評価版のライセンスが取得できると「プロダクトキー」の欄に文字列が表示されます。
APIServerActivation.png

#APIを生成する
##接続の追加
次にAPI Serverの「設定 > 接続」タブを開き、「+接続の追加」ボタンをクリックします。接続可能なDatabase一覧が表示されますので「MySQL」をクリックします。

下記のような画面が表示されますので、住所検索サービスが使用するMySQLの情報を入力し「変更を保存」をクリックします。

項目 設定値
名前 任意
Server MySQLサーバのFQDN
Port MySQLサーバのポート番号
Database MySQLのデータベース名
User MySQLのアカウント
Password MySQLのパスワード

保存後は下記のように接続が追加されたことが確認できます。
Connection4.PNG

##リソースの追加
「設定 > リソース」タブを開き、「リソースを追加...」ボタンをクリックします。
Resource.PNG

ここでは作成済みのデータ接続の一覧が表示されますので、先ほど作成した接続名を選択し「次へ」をクリックします。
Resource2.PNG

次の画面では、選択したデータベースの中のテーブル一覧が表示されますので、ここから適当なテーブルを選択します。住所検索サービスで使用するテーブルは「address」のみなので、これを選択し「次へ」をクリックします。
Resource3.PNG

最後に許可する操作と取得するフィールドを選択します。今回は操作は全て許可、フィールドも全て取得するので、デフォルトのまま「保存」をクリックします。「ユーザーの許可」もデフォルトのままです。
Resource6.PNG

保存後は下記のようにリソースが追加されたことを確認できます。
Resource5.PNG

メニューの「API」をクリックすると下記のようにAPIの仕様について確認することができます。また同時に左側ペインの「リソース」の欄に追加したリソースに紐づくURLが表示されます。
API2.PNG

この“/api.rsc/address”が生成されたデータアクセス用APIのURLです。これだけの操作でMySQLの「address」テーブルにアクセスするAPIが作られました。管理コンソール上でこのURLをクリックすると、各操作の具体例などを確認することができます。
API3.PNG

データアクセス用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」ユーザを「設定 > ユーザー」タブから追加します。「権限」は全てにチェックし、その他はデフォルトのままです。
User2_arrow.png

保存後は、下記のようにadminユーザーの「認証トークン」が表示されます。これで現在管理コンソールにログインしている「admin」ユーザに認証トークンを発行したわけです。管理用APIにアクセスする際はこのトークンを使用します。
User3.png

##管理用APIの仕様書
ここまでの作業で「admin」ユーザは管理用APIへアクセスできるようになりました。管理コンソールにログインしたまま、ブラウザから下記のURLにアクセスしてみます。

http://localhost:8080/apiserver/admin.rst

下記のように管理用APIの仕様と操作可能なリソースを確認することができます。
Manage.PNG

これでAPI Serverの設定は完了です。
ここまでの作業を下記にまとめます。

  • 住所検索サービスが使用しているMySQLのaddressテーブルにアクセスするためのAPIを生成した
  • adminユーザのみがアクセスできる管理用APIを有効化した

#住所検索サービスの拡張
データアクセス用APIを使用するには認証トークンが必要ですので、下記のように住所検索サービスの各ユーザが認証トークンを取得できるようにプロフィール画面にフォームを追加します。

変更前
profile3.PNG

変更後
profile2.PNG

上記の画面のユーザ名「tanaka」は認証トークンを未取得なので「Web API」のフォームは空白です。ここで「認証トークン取得」をクリックすると、下記のように、管理用APIを使って生成・取得した認証トークンと共に必要な情報が表示されます。
profile6.PNG

このために、サーバサイドでは、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」をクリックします。下記のように画面下にはレスポンスが表示され、住所データが取得できていることが分かります。

postman_user.PNG

さらに、フィルターを付加してみます。下記のように、URLのクエリストリングとして、JSON ODataフォーマットでフィルタ条件を記述します。この例では、郵便番号(フィールド名:zip)が“9800811”に一致する、という条件でデータを取得しています。

 http://localhost:8080/apiserver/api.rsc/address?$filter=zip eq '9800811'

postman4.PNG

#補足
管理用APIを使ってユーザを追加するリクエストをPOSTMANを使って見てみます。

  • リクエストタイプ :POST

  • URL : http://localhost:8080/apiserver/admin.rsc/Users/

  • リクエストヘッダー

    • 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

postman.PNG
postman2.PNG

このリクエストに対し、下記のようなレスポンスが得られます。「AuthToken」が認証トークン、「Privileges」が許可された操作の情報です。
postman3.PNG

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?