まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

タグ:parameter

IBM Bluemix から SaaS で提供されている API Management サービスを使うと、普通に提供されている Web API に対して、その提供範囲を一部だけに限定(例えば GET/POST で提供されている API のうち、POST のものだけを公開)したり、認証機能を追加したり、(利用頻度や回数などの)アクセス制限をかけたり、API 利用状況をモニタリングする機能をラッピングする形で提供できるようになります。この辺りに関してはこちらのブログエントリにまとめているので参照ください:
IBM Bluemix の API Management サービス


この API Management サービスを使って既存の API をラッピングした場合、既存の Web API で指定していたURL パラメータやパスパラメータを、ラッピング後にどのように指定すればよいか?という疑問が生じます。その辺りについて調べてまとめてみました。結論としては「あまり意識せずに使える」ことになります。


例えば、既にこのような Web API が存在していたとします:{item_id} の部分に ID を指定して GET リクエストすることで、指定した ID のレコードを取得できる、というものです:
http://xx.xx.xx.xx/abc/items/{item_id}

実際にウェブブラウザでリクエストした例がこちらです。この例では 1 という {item_id} を指定して目的のレコードを取得していますが、この 1 の部分を適宜変えることで目的のレコードを変更することができるような API になっている、という前提です:
2016020701


このような Web API を API Management でラッピングする場合、この {item_id} というパスパラメータの存在をどのように指定すればよいか? というのが本ブログエントリの目的です。

結論はかなり簡単で、API を定義する際のパスにパラメータを {xxx} 形式で指定します。またその実装においてもプロキシー URL を指定する際に同じパラメータを使って指定します。

具体的には以下のような /get 関数を定義します。公開する API の形式を /get/{item_id} のように指定し、その実装のプロキシーURL において、 http://xx.xx.xx.xx/abc/items/{item_id} のようにそのまま指定するようにします。これで /get/ の後に1つパラメータを受け取って動くような挙動になっていることを指定したことになります:
2016020703



また、URL パラメータはラッピング API を作成する際には特に宣言しなくても、そのまま使えます。例えば以下の URL を GET リクエストすると、レコードの一覧が取得できるような API が存在していて、limit=XX の部分で取得レコード数を指定できるような仕様になっていると仮定します:
http://xx.xx.xx.xx/abc/items?limit=100

この Web API を API Management でラッピングする場合は、URL パラメータのことは意識せずに、そのまま API を定義できます。下の例では公開 API に /list というパスを指定し、その実装のプロキシー URL は http://xx.xx.xx.xx/abc/items (URL パラメータ部分を省略したもの)までをそのまま指定します。これで /list 関数も定義できました:
2016020704


このような指定方法で作成/公開したラッピングの API で、パスパラメータや URL パラメータを指定するには以下のようにします。まずは公開したラッピング API は Bluemix 内では「カスタム API 」として利用可能になっています(API Management で公開後に再ログインする必要があります)。まずはこのカスタム API を自分のランタイムにバインドしておきます:
2016020705


バインドが成功すると、ランタイム内のサービスにカスタム API が追加できているはずです:
2016020706


次にこの API を利用する際に必要な client_id と client_secret を確認します。メニューから「環境変数」を選び、このカスタム API を利用するための credentials 情報を確認します。そして url, client_id, client_secret の3つの値を確認してメモしておきます(この値はランタイムの環境変数 VCAP_SERVICES から参照できるので、アプリケーション内で動的に取得も可能です):
2016020707


では実際に API Management を使って公開された API をパラメータを付けて利用してみましょう。まずレコードの ID をパス内で指定してレコードを取得する API の場合は、その ID をそのまま URL の最後に指定してブラウザでアクセスします。なお API Management 管理下の API にアクセスするには client_id と client_secret の値が必要なので、上記の環境変数から取得したそれぞれの値をそれぞれ指定して、以下のようなアドレスにウェブブラウザでアクセスします(以下は {item_id} に 1 を指定した例です):
(環境変数の url の値)/get/1?client_id=(環境変数 client_id の値)&client_secret=(環境変数 client_secret の値)

すると、上記のラッピング前の Web API で実行した時と同じ結果を確認することができます。{item_id} の値を変更しても、正しい値が得られるはずです。これでパスパラメータについては API Management で管理できることがわかりました:
2016020708


もう1つの、URL パラメータを指定する例も確認してみます。今度も client_id と client_secret と、更に limit の値も含めて URL パラメータに指定して、以下の様なアドレスにアクセスします(以下は limit に 10 を指定した例です):
(環境変数の url の値)/list?client_id=(環境変数 client_id の値)&client_secret=(環境変数 client_secret の値)&limit=2

この場合もラッピング前の Web API で実行した時と同じ結果が確認できるはずです(limit の値を変更すると、指定した数を上限とする結果セットが得られるはずです)。URL パラメータについては特に何もしなくても API Management に引き継いで管理できることが確認できました:
2016020709


結論として、API Management でパラメータを使う場合は、以下の様な指定が必要です:
(1) URL パラメータの場合は、特に指定不要でそのまま
(2) パスパラメータの場合は、指定するパラメータを { } で括ったものを API 定義とプロキシー URL の両方に指定する





StrongLoopLoopBack を使うと、データベースのモデルを定義するだけで CRUD の REST API を生成し、OpenAPI(Swagger) スタイルのドキュメントと併せて簡単に公開できます。この辺りについては以前のブログエントリを参照してください:
CentOS に StrongLoop をインストールする


ところで、LoopBack を使って公開された API にはパラメータで挙動を指定できるものもあります。例えばモデルの一覧を取得する GET リクエストでは一覧を絞り込むためのクエリーを指定したり、取得結果の数やオフセットを指定することも可能です:
2016020601


そのための方法を紹介します。例えば items というテーブルに対して LoopBack で CRUD の API を作成したと仮定します。items の一覧を取得するには以下の様な URL に対する HTTP リクエストを GET で実行することになります(XX.XX.XX.XX は LoopBack が動いているサーバー):
http://XX.XX.XX.XX/api/items/

さて、一覧の検索条件(例えば id < 100)を指定する場合、SQL ではこのように指定することになります:
> select * from items where id < 100;

この条件を指定して上記の HTTP GET リクエストを実行するには、つまり id < 100 のものだけの一覧を API で取得するには、以下の様なパラメータを指定して実行します:
http://XX.XX.XX.XX/api/items?filter[where][id][lt]=100

filter という名前に [where] 句が指定され、更に条件である [id] が [lt] (Less Than) で 100 である、という条件が指定されていることになります。


一方、一覧の検索結果の取得数(例えば10件)を指定する場合、SQL(MySQL) ではこのように指定します:
> select * from items limit 10;

この条件を指定して HTTP GET リクエストを実行するには、以下の様なパラメータを指定して実行します:
http://XX.XX.XX.XX/api/items?filter[limit]=10

filter という名前に [limit] 句が指定され、その値が 10 である、という条件が指定されていることになります。なんとなくコツが分かってきましたか?

ちなみに一覧の検索結果の取得数を 50 件目からの 10 件、とするには SQL(MySQL) ではこのように指定します:
> select * from items limit 50, 10;

limit 句を指定し、オフセットが 0 以外の場合は limit 数の前にオフセット数を指定します。これを API のパラメータで指定するには以下のようにします:
http://XX.XX.XX.XX/api/items?filter[limit]=10&filter[offset]=50

クエリーや結果取得の条件は同時に指定することができます。例えば「 id < 100 のものをオフセット 50 で10 件取得」するのであれば、API ではこのように指定します:
http://XX.XX.XX.XX/api/items?filter[where][id][lt]=100&filter[limit]=10&filter[offset]=50

filter の使い方、なんとなくコツがわかってきましたか? 使っているデータベースの種類は何で、そのデータベースでは SQL ではどういった指定になるか、をイメージできるとわかりやすいです。


このパラメータに関する API ドキュメントはこちら:
https://docs.strongloop.com/display/public/LB/Where+filter
 

このページのトップヘ