プログラム

blanketでmochaで書いたテストのカバレッジを測定する

mochaで書いたテストのカバレッジ(網羅率)を取るにはどうしたらよいのかと思っていたところ、blanketというのを見つけたので試してみました。

早速、blanketとmochaでテストを走らせた際にカバレッジを表示させられる様にするためのレポーターを追加します。

$ npm install --save-dev blanket
$ npm install --save-dev mocha-spec-cov-alt

blanketの設定をpackage.jsonに追記します。data-cover-neverにはカバレッジ測定の対象としないディレクトリを明記します。ここではテストが入っているディレクトリとnpmのパッケージがインストールされているディレクトリを除外しています。

  "config": {
"blanket": {
"pattern": [
""
],
"data-cover-never": [
"node_modules",
"test"
]
}
}

更に npm test を実行する際の設定を以下の様に修正します。mochaを呼び出す際に以下の2つのオプションを追加します。

  • レポーターにmocha-spec-cov-altを指定 -R mocha-spec-cov-alt
  • 実行時にblanketを読み込む様に指定 --require blanket

修正例としては以下の様な形。

  "scripts": {
"test": "NODE_ENV=\"testing\" mocha -R mocha-spec-cov-alt --recursive --require blanket "
},

ここまででテストのカバレッジがmochaの実行結果として表示される様になります。*1

npm test を実行すると

f:id:hideack:20150801114446p:plain

といった形でテストの末尾にカバレッジが表示される様になります。

参考

blanketjs.org

github.com

*1:コメントに従ってscripts修正しました

Google docsのスプレッドシート上に記載されたURLのいいね数を取得する

Google docsネタ第2弾 エントリ。

仕事でGoogle docsにメモられたURLにつけられたfacebookのいいね数をとりたいなと思ったので、以下の様なスクリプトgoogle docsで作成して解決。

スプレッドシートの「ツールスクリプトエディタ」で空のプロジェクトを使って以下の様なスクリプトを書きます。

function fb(uri) {
var cache = CacheService.getPublicCache();
var cacheKey = "fb:like:" + uri;
var likeNum;
likeNum = cache.get(cacheKey);
if (likeNum == null) {
var apiUrl = "http://api.facebook.com/method/fql.query?format=json&query=select+total_count+from+link_stat+where+url%3D%22";
apiUrl += uri;
apiUrl += "%22";
var responseJson = UrlFetchApp.fetch(apiUrl);
var items = Utilities.jsonParse(responseJson.getContentText());
likeNum = items[0].total_count;
if (isFinite(likeNum)) {
cache.put(cacheKey, likeNum, 60 * 60 * 8);
}
}
return likeNum;
}

味噌は使っているのがGoogle docsということで、同じ社内のネットワークから複数の人が同時にスプレッドシートを開いて閲覧することは当然あるわけでそうするとそのたびにfacebookAPIを叩くことになってAPIのレスポンスを得られなくなるので CacheService を使ってキャッシュさせているところですね。

とセルに書いてあげることで、いいね数が返ってくる様になります。

とても便利なのでぜひお試しを。

loopback-testingを利用してloopbackで作成したAPIのテストを書く

loopbackでAPIのテストを書く際にloopback-testingを利用してAPIのテストを書いてみたのでその際のメモ。

まずは必要なnpmパッケージをloopbackアプリケーションに導入します。loopbackアプリのルートで以下のnpmコマンドを実行。

www.npmjs.com

$ npm install loopback-testing --save-dev
$ npm install chai --save-dev

これで準備完了。加えて npm test でテストを実行できる様に package.json 内のscriptsの定義を以下の様に書き換えます。*1

"scripts": {
"test": "NODE_ENV=\"testing\" ./node_modules/loopback-testing/node_modules/.bin/mocha -R spec --recursive"
}

上記の意図は npm test が実行された際に testing 環境としてnode_modules配下のmochaを利用してテストを実行します。

それにともなってtesting環境でloopbackアプリが実行された際のデータソース(DB接続先)を定義しておきます。Circle CI等のCI環境でもすぐに実行できる様に、memoryを指定します。

~/server/datasources.testing.js というファイルを用意して以下の様にデータの保存先をmemoryに指定します。

module.exports = {
db: {
connector: "memory",
defaultForType: "db"
}
};

これでテストが実行できる様になりました。expressの流儀と同様にプロジェクト直下の test ディレクトリに現在開発しているloopbackアプリケーション(API)のテストを書いてみます。

例えばユーザ登録(メールアドレスとPWをPOSTするとユーザ登録できる)のAPIのテストであれば、

var lt = require('loopback-testing');
var chai = require('chai');
var assert = chai.assert;
var app = require('../../server/server.js');
describe('/api/users', function() {
var newUser = {email: "tester1@remp.jp", password:"tester1remp"};
describe('ユーザ登録', function() {
lt.describe.whenCalledRemotely('POST', '/api/users', {}, function() {
it('ユーザ登録の際にメールアドレス、パスワードのパラメータは必須', function() {
var codes = this.res.body.error.details.codes;
assert.include(codes.password, 'presence');
assert.include(codes.email, 'presence');
assert.include(codes.email, 'format.null');
});
});
lt.describe.whenCalledRemotely('POST', '/api/users', newUser, function() {
it('メールアドレス, パスワードを与えるとユーザ作成できる', function() {
assert.equal(this.res.statusCode, 200);
});
});
});
});

といった具合に記述することができます。

ほぼコードを読んだままなのですが、 lt.describe.whenCalledRemotely の記述で指定のエントリポイント下へ指定のメソッド及びパラメータでアクセスがあった場合のテストを書くことができます。

また、アクセスするユーザにロールや状態をもたせた状態のテストも同様に記述ができ、例えばログインを行ったユーザによるAPIへのアクセスを想定したテストは

  var user = {
id: 2,
email: "tester2@remp.jp",
username: "tester2",
password: "tester2remp"
};
// (snip)
describe('ユーザによるプレイリスト操作', function() {
lt.describe.whenCalledRemotely('GET', '/api/users/2/playlists', function() {
it('未ログインユーザはユーザのプレイリストは取得できない', function() {
assert.equal(this.res.statusCode, 401);
});
});
lt.describe.whenCalledByUser(user, 'GET', '/api/users/2/playlists', function() {
it('ログインしたユーザ自身のプレイリストは取得できる', function() {
assert.equal(this.res.statusCode, 200);
});
});
});

の様に lt.describe.whenCalledByUser という記述で実現することができます。他にも各種ロールを割り当てた上での記述が行える様になっています。

こういった形でテストを用意した上で npm test で実行してみると...

といった具合にmochaによるテストが実行できています。

loopbackで作成したAPIであれば、loopback-testingを用いることでアクセスするユーザの各種ロールを想定したテストが記述できて便利ですというお話でした。

まとめ

  • loopbackアプリケーションでのテストを行うために loopback-testing を導入しました
  • npm test でテストを実行できる様にpackage.jsonの一部を修正しました
  • whenCalledRemotely, whenCalledByUser 等 loopback-testingを利用することで用意に各種ロールを想定したテストが書けました

あわせて読みたい

*1:loopbackのscafold(slcコマンド)で作成された場合は仮のpretestの定義が書いてあります

loopbackで作成されたAPIのアクセスコントロールを設定する

の様なモデルのリレーションを定義し、APIも自動的に作成され /rempusers/:id/libraries といった形でアクセスできる様に
なったのですが、ログインして得られるアクセストークンを付与しても現状だと401応答が帰って来ます。

$ http http://localhost:5000/api/RempUsers/55486573fecad3d7215ead80/libraries?access_token=*****
HTTP/1.1 401 Unauthorized
Access-Control-Allow-Credentials: true
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
Date: Sun, 10 May 2015 01:52:10 GMT
ETag: W/"DNoQruYc4EoovuVyGTv+hg=="
Transfer-Encoding: chunked
Vary: Origin, Accept-Encoding
X-Powered-By: Express
{
"error": {
"code": "AUTHORIZATION_REQUIRED",
"message": "Authorization Required",
"name": "Error",
"status": 401,
"statusCode": 401
}
}

これはloopbackで既定されているUserモデルを継承したモデルにはユーザ自身の情報のみが制御できる様なアクセスコントロールが設定されているため、
そのモデルとリレーションするモデルをAPI経由で呼びだそうとすると制限がかけられています。*1

この問題を解消するためのアクセスコントロールを設定します。

loopbackでアクセスコントロールを設定するためのscafoldは slc loopback:acl というコマンドで実現できます。

今回対象となるAPIのエントリポイントはモデルのメソッド的にはgetに対応するためmethod nameとしては __get__libraries を指定します。

$ slc loopback:acl
? Select the model to apply the ACL entry to: RempUser
? Select the ACL scope: A single method
? Enter the method name: __get__libraries
? Select the role: The user owning the object
? Select the permission to apply: Explicitly grant access

具体的にモデル間のリレーションを組んだ時にどの様なメソッドが自動生成したモデルに備わっているかはドキュメントを参照するとわかりやすいです。

アクセスコントロールを設定した後に再度アクセスしてみると、

$ http http://localhost:5000/api/RempUsers/55486573fecad3d7215ead80/libraries?access_token=****
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Connection: keep-alive
Content-Length: 329
Content-Type: application/json; charset=utf-8
Date: Sun, 10 May 2015 07:27:01 GMT
ETag: W/"149-11634253"
Vary: Origin, Accept-Encoding
X-Powered-By: Express
[]

今度は問題なく取得できています。

なんとなくloopbackの世界が少しだけ見えてきました。

参照

*1:表現が難しい....

loopbackでモデルのrelationを定義する

loopbackでモデルを作成するときslcコマンドで作成できるのだけど、
モデル間のリレーションを同様にscafoldするやり方のメモです。

ここでは1対多となるモデルのリレーションの定義をslcコマンドで行ってみます。
例としてRempUserというユーザが複数のプレイリストを持つケースを想定します。

ユーザのモデルは既に作成されているものとして、プレイリストを管理するモデルを復習がてら作成します。

$ slc loopback:model
? Enter the model name: Playlist
? Select the data-source to attach Playlist to: db (mongodb)
? Select model's base class: PersistedModel
? Expose Playlist via the REST API? Yes
? Custom plural form (used to build REST URL):
Let's add some Playlist properties now.
Enter an empty property name when done.
? Property name: title
invoke   loopback:property
? Property type: string
? Required? Yes
Let's add another Playlist property.
Enter an empty property name when done.
? Property name: published
invoke   loopback:property
? Property type: boolean
? Required? Yes
Let's add another Playlist property.
Enter an empty property name when done.
? Property name:

次に先ほど作成したプレイリストのモデルとユーザモデルの間のリレーションを定義します。

これもscafoldできて slc loopback:relation というコマンドで実現できます。

$ slc loopback:relation
? Select the model to create the relationship from: RempUser
? Relation type: has many
? Choose a model to create a relationship with: playlist
? Enter the property name for the relation: playlists
? Optionally enter a custom foreign key:
? Require a through model? No
$ slc loopback:relation
? Select the model to create the relationship from: playlist
? Relation type: belongs to
? Choose a model to create a relationship with: RempUser
? Enter the property name for the relation: RempUser
? Optionally enter a custom foreign key:

このコマンドで具体的に行われるのは common/models/*.json で保管されている各モデルの定義が記載されているJSONrelations という
要素に定義が追加されます。

実際に該当のJSONファイルを見てみると、例えばユーザモデルであれば、

{
"name": "RempUser",
"base": "User",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {},
"validations": [],
"relations": {
"playlists": {
"type": "hasMany",
"model": "Playlist",
"foreignKey": ""
}
},
"acls": [],
"methods": []
}

といった具合にプレイリストモデルとのリレーションの定義が追加されていることがわかります。

また、loopbackの特徴であるモデル定義がそのままAPIとして反映されているので、loopbackのAPI Explorerを介して該当モデルの
エントリポイントを確認してみると、

といった形でCRUDできるAPIが作られています。便利。

ただ、今回の例の場合、新しく作成されている /RempUsers/:id/playlists といったエントリポイントにアクセスをしても HTTP/1.1 401 Unauthorized となってしまいます。

これは、loopbackで設けられているAPIに対するアクセスコントロールによるものなのですが、この辺りを解決するやり方はまた次回。

参考

loopbackでAPIにアクセスした際のACLの適用状況を確認する

loopbackで作成したAPIには、ユーザのロールに応じてアクセスコントロールを指定することができます。

例えば、

  • adminユーザのみアクセス可
  • このロールのユーザのみアクセス可
  • 認証済のユーザであればアクセス可

といった様なアクセスコントロールをslcコマンドでscaffoldすることができます。(やっていることはmodelの定義をしているJSONにアクセス権限の設定を付与している)

この設定を簡単にチェックするためにアプリケーションログとして標準出力するにはloopbackアプリケーション指定時に以下の環境変数を指定することで実現できます。

$ DEBUG=loopback:security:acl slc run

といった形でloopbackアプリを起動するとloobackで作成したAPIにアクセスした際にそのAPIへ適用されているアクセスコントロールの適用状況を確認することができます。

例えば RempUser というモデルがあり、/api/RempUsers/{id} というエントリポイントに対してユーザ情報を取得するためGETリクエストを発行した場合、発行と同時にアクセスコントロールの適用状況がログとして標準出力に出力されます。

$ http http://localhost:5000/api/RempUsers/1?access_token=pIIxAUP6qn2OtXntEGWO6KxAU71qDSS14A1qZamwTTk2xZEOppdtUVRM3agrdoQ8

といった形でリクエストを発行すると、以下の様なログが出力されます。

loopback:security:acl The following ACLs were searched:
loopback:security:acl ---ACL---
loopback:security:acl model RempUser
loopback:security:acl property findById
loopback:security:acl principalType ROLE
loopback:security:acl principalId $owner
loopback:security:acl accessType *
loopback:security:acl permission ALLOW
loopback:security:acl with score: 8016
loopback:security:acl ---ACL---
loopback:security:acl model RempUser
loopback:security:acl property *
loopback:security:acl principalType ROLE
loopback:security:acl principalId $everyone
loopback:security:acl accessType *
loopback:security:acl permission DENY
loopback:security:acl with score: 7495
loopback:security:acl ---Resolved---

この出力を確認することでloopbackが該当のエントリポイントに対してどういった判断が行われてアクセス可/不可の判定を行ったか確認することができます。

loopbackでMongoDBを利用する

loopbackでアプリケーションを作成した直後はデータストレージにmemoryが設定されているため、そのままだとアプリケーションが再起動するたびにmodelの内容が初期化されてしまうため、保管できる様にMongoDB*1を利用できる様にします。

作成したアプリケーションルートでnpmコマンドを叩きます。

$ npm install loopback-connector-mongodb --save

www.npmjs.com

MongoDBに接続するためのコネクタがpackage.jsonに追加されて必要なnpmモジュールがインストールされたのを確認した後、server/datasource.json にある
データベースへの接続設定を更新します。

{
"db": {
"name": "db",
"connector": "mongodb",
"host": "127.0.0.1",
"database": "hogehoge_development",
"username": "",
"password": "",
"port": 27017
}
}

必要な設定はこれだけになります。

先日作成したユーザ登録のAPIを呼び出してみます。

☁  http POST http://0.0.0.0:3000/api/users password=hogehoge email=hideack@remp.jp
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Connection: keep-alive
Content-Length: 59
Content-Type: application/json; charset=utf-8
Date: Mon, 04 May 2015 06:30:46 GMT
ETag: W/"3b-84c0720e"
Vary: Origin, Accept-Encoding
X-Powered-By: Express
{
"email": "hideack@remp.jp",
"id": "554712159967a7b3efce0f0c"
}

MongoDBで永続化されているかを確認してみます。

素朴に mongo コマンドでMongoDBに接続して確認します。

> show collections
User
system.indexes
> db.User.find()
{ "_id" : ObjectId("554712159967a7b3efce0f0c"), "password" : "$2a$10$AzdK8q7nUIHxcoiW5y17Lusb4eag7VOjwQI.e5ukjJRWKMWXSaP6a", "email" : "hideack@remp.jp" }
>

loopbackで作成したアプリケーションで操作されたmodelの内容がMongoDBで永続化される様になりました。

併せて読みたい

過去のloopbackに関する記事

*1:REMPもSTOBOもストレージはMongoDBです

Node Foremanで複数のプロセスを同時に起動する

Rubyで開発している時に開発環境で複数のプロセスをまとめて起動させたいときにforeman
利用することが多いですがNode.jsの実装でNode Foremanがあります。

www.npmjs.com

npmコマンドでNode Foremanをインストールします。

$ npm install -g foreman

コマンド自体は nf となります。

$ nf
_____
|   __|___ ___ ___ _____ ___ ___
|   __| . |  _| -_|     |   |   |
|__|  |___|_| |___|_|_|_|_^_|_|_|
Usage: nf [options] [command]
Commands:
start [options]        Start the jobs in the Procfile
run [options]          Run a one off process using the ENV variables
export [options]       Export to an upstart job independent of foreman
Options:
-h, --help             output usage information
-V, --version          output the version number
-j, --procfile <FILE>  load procfile FILE
-e, --env      <FILE>  use FILE to load environment
-p, --port     <PORT>  start indexing ports at number PORT

では、実際に複数のプロセスをNode foremanで起動してみます。

Procfile自体はRubyのforemanと同じなので準備します。ひとまず開発用ということで Procfile.development というファイル名で以下の様な内容を準備します。

サンプルとして先日作成したloopbackアプリ + MongoDBを動かしてみます。

web: node .
mongo: mongod --dbpath=./db

上記の様なProcfileを用意したらNode Foremanを起動します。

$ nf start -j Procfile.development

上記のコマンドでForemanを起動すると、複数プロセス(loopbackアプリとMongoDB)が起動します。

Node.jsのアプリでforemanを使いたいとき、npmの範囲でカバーできるので便利ですね。

loopbackでアプリケーションを作成してユーザ登録APIを作るまで

StrongLoopが開発したloopbackは、Node.jsで作られたフレームワーク(所謂mBaaSのオープンソース実装)で以下の様な特徴があります。

  • RESTなAPIをモデルと対応させて素早く作れる (モデルを作るとCRUDするAPIが出来上がる)
  • モデルはコネクタを介して様々なDBで永続化できる
  • API自体は application/jsonAPIとして操作でき、各種クライアント向けのSDKを備えている

といった特徴があります。

利用実績としては、GoDaddyでpublic reseller APIに利用されている様です。

SPAなアプリケーションを2011年からREMPSTOBO
そしてRendrを利用してCastoを作ってきましたが、もしかしたらloopbackを使ってAPI開発をよりスムーズに
解決できるのではないか。という期待を抱きつつ試しに触ってみました。

ひとまずゴールとしては、

loopbackでアプリケーションを作成し、APIを介してユーザを作るところまで

とします。

準備

とにもかくにも strongloop コマンドをインストール。*1

$ npm install -g strongloop

これで slc コマンドが使える様になってscaffoldできます。

アプリケーション作成

実際にアプリケーションを作成してみます。(謎のキャラクターが表示されます)

☁  slc loopback remp-api
_-----_
|       |    .--------------------------.
|--(o)--|    |  Let's create a LoopBack |
`---------´   |       application!       |
( _´U`_ )    '--------------------------'
/___A___\
|  ~  |
__'.___.'__
´   `  |° ´ Y `
? What's the name of your application? remp-api
? Enter name of the directory to contain the project: remp-api
create remp-api/
info change the working directory to remp-api
Generating .yo-rc.json
I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
create .editorconfig
create .jshintignore
create .jshintrc
create README.md
(snip)
Next steps:
Change directory to your app
$ cd remp-api
Create a model in your app
$ slc loopback:model
Optional: Enable StrongOps monitoring
$ slc strongops
Run the app
$ slc run .

ユーザーモデルを作成

続いてユーザーを管理するためのモデルを作成してみます。

loopbackではいくつかのbase classが用意されていてその中にUserというクラスが存在するので今回はこれをこのまま利用します。

基本的なユーザ管理をする場合であればbase classのままでよいのですが、何か新たにプロパティ足したい場合は追加をすることもできます。今回はスキップ。

☁  slc loopback:model
? Enter the model name: user
? Select the data-source to attach user to: db (memory)
? Select model's base class: User
? Expose user via the REST API? Yes
? Custom plural form (used to build REST URL):
Let's add some user properties now.
Enter an empty property name when done.
? Property name:
☁  

上の操作で以下の様な要素を持ったユーザ管理のモデルが作成できます。

要素 -
realm (string, optional)
username (string, optional)
credentials (object, optional)
challenges (object, optional)
email (string)
emailVerified (boolean, optional)
verificationToken (string, optional)
status (string, optional)
created (string, optional)
lastUpdated (string, optional)
id (number, optional)

APIを呼び出してみる

では、モデルを作成 = API作成 ができたので実際にHTTPクライアントからAPIを呼び出してみます。

loopbackアプリケーションを起動します。

☁  node .
Browse your REST API at http://0.0.0.0:3000/explorer
Web server listening at: http://0.0.0.0:3000/

おもむろにloopbackアプリケーションを呼び出します。

先ほど作成したUserモデルに対応するAPIのエントリポイントは /api/users に対応しますので、そこへメールアドレスとパスワードをPOSTします。

☁  http -v POST http://0.0.0.0:3000/api/users password=hogehoge email=hideack@remp.jp
POST /api/users HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Content-Length: 52
Content-Type: application/json; charset=utf-8
Host: 0.0.0.0:3000
User-Agent: HTTPie/0.8.0
{
"email": "hideack@remp.jp",
"password": "hogehoge"
}
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Connection: keep-alive
Content-Length: 34
Content-Type: application/json; charset=utf-8
Date: Sat, 02 May 2015 05:27:48 GMT
ETag: W/"22-3085cb67"
Vary: Origin, Accept-Encoding
X-Powered-By: Express
{
"email": "hideack@remp.jp",
"id": 2
}

ステータスコード200が帰って来てユーザを作成することができました。

ログインしてみる

では、先ほど作成したユーザでログインしてみます。ユーザ作成の際に利用したメールアドレスとパスワードを要素としてPOSTします。

ログイン用のエントリポイントは /api/users/login なので、ここにユーザ登録の際に設定したメールアドレスとパスワードを渡します。

☁  http -v POST http://0.0.0.0:3000/api/users/login email=hideack@remp.jp password=hogehoge
POST /api/users/login HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Content-Length: 52
Content-Type: application/json; charset=utf-8
Host: 0.0.0.0:3000
User-Agent: HTTPie/0.8.0
{
"email": "hideack@remp.jp",
"password": "hogehoge"
}
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Connection: keep-alive
Content-Length: 135
Content-Type: application/json; charset=utf-8
Date: Sat, 02 May 2015 05:30:16 GMT
ETag: W/"87-4fc8ab24"
Vary: Origin, Accept-Encoding
X-Powered-By: Express
{
"created": "2015-05-02T05:30:16.742Z",
"id": "r3YFqmceF1INk5FlstmZgO7p2y42TyLYPlzSchPIDIDBlAbuOHQurS5j5gOSH82h",
"ttl": 1209600,
"userId": 2
}

ステータスコード200が帰って来て、API操作用のトークンが戻ってきました。なお、パスワードが誤ると、

HTTP/1.1 401 Unauthorized
{
"error": {
"code": "LOGIN_FAILED",
"message": "login failed",
"name": "Error",
"stack": "Error: login fail...",
"status": 401,
"statusCode": 401
}
}

となって期待通りです。

ログイン時のトークンを利用してユーザ情報を取る

続けて先ほどログイン時に取得したトークンを利用してユーザの情報を取得してみます。

現状だとUserモデルしか存在しないのでできることが少ないですがログインしているユーザ自身の情報を取ってみます。

/api/users/2?access_token=(ログイン時に得たtoken) に対してGETします。

☁  ~  http http://0.0.0.0:3000/api/users/2\?access_token\=r3YFqmceF1INk5FlstmZgO7p2y42TyLYPlzSchPIDIDBlAbuOHQurS5j5gOSH82h
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Connection: keep-alive
Content-Length: 34
Content-Type: application/json; charset=utf-8
Date: Sat, 02 May 2015 05:45:01 GMT
ETag: W/"22-3085cb67"
Vary: Origin, Accept-Encoding
X-Powered-By: Express
{
"email": "hideack@remp.jp",
"id": 2
}

scafoldする際に特にプロパティを追加していないのでidとemailのみ返ります。

API Explorer

ここまでコマンドラインのHTTPクライアントでAPIを操作してみましたが、実はscafoldした時点でStrong Loop API ExplorerというWebアプリが同時に起動しています。

http://0.0.0.0:3000/explorer

へブラウザでアクセスすると以下の様な画面を閲覧できて実際にAPI操作も行うことができます。

まとめ

loopbackを利用して、アプリケーションの作成とユーザを管理するモデルの作成(それと同時にユーザ操作をするAPIの作成)を行ってみました。

気づかれたかもしれませんが、上までの操作だとモデルを保管する先のストレージを何も設定していない状態なのでアプリケーションの再起動で全て消えます...。

データベースの接続はまた次の機会に。

*1:内部的にYeomanを使っているのでYeomanを既に使っていたら npm install -g generator-loopback

RunscopeでAPIの応答を監視する

Runscopeとは

Runscopeは2013年にローンチしされたAPI監視サービスです。

www.runscope.com

メリットとしては、"本番環境で提供しているAPIのステータス監視及び応答内容監視ができる" があります。

単純な死活監視ではなく、APIが返答するJSONXML, HTTPステータスなどの応答内容の監視まで行うことで仮に提供中のAPIから更に外部のAPIと連携しているなどしていた場合、外部のAPIの異常を検知できずにサービスが稼働を続けるということを防ぐことができます。

30日間, 25万リクエストまでであれば無償で試すことができます。

設定

ログイン直後の上部メニューの "Radar Tests" → "Create Test" を指定し、テストグループを作成した後、作成されたテストで "Edit Test" をクリックします。

そうすると下記の様なUIが表示されるため、設定自体はものすごくシンプルでリクエスト対象のURLを指定します。

API呼び出し時に認証がかかる場合は、BASIC認証及び、OAuthのキーも設定することができます。

"Assertions"のタブで期待する応答を指定します。チェックできる項目は以下の内容です。

  • JSON Body
  • XML Body
  • Response Header
  • Text Body
  • Status Code
  • Response Time (ms)
  • Response Size (bytes)

それぞれの内容について期待値を指定しそれを満たしているか否かというチェックが行えます。

例えば、あるAPIを呼び出された時に....

といった所謂APIで監視したくなる要素についてチェックができる様になっています。

この様に各テストを追加していくと各URLのエントリポイントの状態がダッシュボード上で一覧することができます。

テストは毎分〜1日1回の間で実行間隔を設定できる様になっており、また実行結果はSlackに通知させることも可能です。


Runscopeを利用すると死活監視とAPIの応答内容監視も行うことができてサービス内(あるいは会社内等)で複数API外部から利用されたた際にどの様な状態を返しているか という点を主体において監視する際に役立ちそうな印象でした。

また、API内部で更に第三者が運営する別のAPIを呼び出す等の連携が行われている場合、その部分の監視も併せて行えていることになるため、副次的なメリットも大きいかと思いました。