Ext JS の SimManager を利用してモック REST API サーバーを実装する方法をメモっとく。Sencha Fiddle でモック API サーバーを実装するときに便利なのだ。とくに今回はシンプルな API サーバーではなく複雑な REST API サーバーを実装してみる。
SimManager
Ext.ux.ajax.SimManager はシミュレートされた Ajax レスポンスを管理するシングルトンクラスだ。Ext.data.Connection のメソッドをフックして実現しているので、Ext.Ajax のような派生クラスの Ajax レスポンスもシミュレートされたものになる。
SimManager の init
メソッドが呼び出されるか、register
メソッドで最初の Ext.ux.ajax.Simlet が登録されたときに前述のフックが挿入される。
Simlet は Ajax リクエストに応答してレスポンスを生成するシミューレートされたサーバー (Simulated Server) の基本クラスになる。派生クラスとして Ext.ux.ajax.DataSimlet、Ext.ux.ajax.XmlSimlet、Ext.ux.ajax.JsonSimlet、Ext.ux.ajax.PivotSimlet がある。おそらく JsonSimlet の使用頻度が高くなるはずだ。
Ext.ux.ajax.SimXhr は XMLHttpRequest オブジェクトをシミュレートする。SimXhr の中には Simlet が含まれていて、その Simlet がレスポンスを生成しているのだ。
静的 API サーバー
SimManager で静的な値を返す API サーバーを定義するには、type
に JsonSimlet のエイリアスを設定し、url
に URL を設定する。そして data
にはレスポンスとして返したいデータを指定する。
Ext.ux.ajax.SimManager.register([{
type: 'json',
url: '/users',
data: [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
{ id: 4, name: 'Dave' }
]
}]);
次のように Ext.Ajax でリクエストを送信することで静的 API サーバーの動作を検証できる。
Ext.Ajax.request({
url: '/users',
success: function (response) {
console.dir(Ext.decode(response.responseText));
}
});
実行結果は上記のスクリーンショットを参照してほしい。
動的 API サーバー
SimManager で動的な値を返す API サーバーを定義するには、type
に JsonSimlet のエイリアスを設定し、url
に URL を設定する。そして data
にはレスポンスとして返したいデータを生成する関数を指定する。
Ext.ux.ajax.SimManager.register([{
type: 'json',
url: '/users',
data: function (ctx) {
var users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
{ id: 4, name: 'Dave' }
];
return users.filter(user => user.name.includes(ctx.params.query));
}
}]);
関数の ctx
パラメーターにはコンテキストを表すオブジェクトが渡される。オブジェクトには下記のプロパティが含まれる。
プロパティ | 型 | 内容 |
---|---|---|
method | 文字列 | HTTP メソッド |
params | オブジェクト | クエリパラメーター |
url | 文字列 | クエリパラメーターを含む URL |
xhr | オブジェクト | モック XHR オブジェクト |
次のように Ext.Ajax でリクエストを送信することで動的 API サーバーの動作を検証できる。
Ext.Ajax.request({
url: '/users?query=li',
success: function (response) {
console.dir(Ext.decode(response.responseText));
}
});
実行結果は上記のスクリーンショットを参照してほしい。
REST API サーバー
REST API サーバーを定義するには、GET・POST・PUT・DELETE などの HTTP メソッドに対応した Simlet を使用しなければならない。標準では用意されていないので JsonSimlet を継承する RestSimlet を定義しよう。
doGet
メソッドと doPost
メソッドは JsonSimlet で定義されているので、doPut
メソッドと doDelete
メソッドを追加で定義する。それぞれ JsonSimlet で定義されている doPost
メソッドと同じ定義にしている。
Ext.define('RestSimlet', {
extend: 'Ext.ux.ajax.JsonSimlet',
alias: 'simlet.rest',
doPut: function (ctx) {
return this.doGet(ctx);
},
doDelete: function (ctx) {
return this.doGet(ctx);
}
});
そして SimManager で REST API サーバーを定義しよう。type
に RestSimlet のエイリアスを設定し、url
に URL を設定する。そして data
にはレスポンスとして返したいデータを生成する関数を指定する。リクエストの HTTP メソッドによって処理を分岐させたり、レスポンスの HTTP ステータスコードを指定することもできる。モック REST API サーバーとしては十分な機能が実装できるはずだ。
Ext.ux.ajax.SimManager.register([{
type: 'rest',
url: '/users',
data: function (ctx) {
switch (ctx.method.toUpperCase()) {
case 'GET':
this.status = 200;
this.statusText = 'OK';
return [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
{ id: 4, name: 'Dave' }
];
case 'POST':
this.status = 201;
this.statusText = 'Created';
return { id: 5, name: 'Eve' };
case 'DELETE':
this.status = 204;
this.statusText = 'No Content';
return;
}
}
}]);
次のように Ext.Ajax でリクエストを送信することで REST API サーバーの動作を検証できる。
Ext.Ajax.request({
method: 'GET',
url: '/users',
success: function (response) {
console.log('GET /users');
console.log(response.status + ' ' + response.statusText);
console.dir(Ext.decode(response.responseText));
}
});
Ext.Ajax.request({
method: 'POST',
url: '/users',
success: function (response) {
console.log('POST /users');
console.log(response.status + ' ' + response.statusText);
console.dir(Ext.decode(response.responseText));
}
});
Ext.Ajax.request({
method: 'DELETE',
url: '/users',
success: function (response) {
console.log('DELETE /users');
console.log(response.status + ' ' + response.statusText);
console.dir(Ext.decode(response.responseText));
}
});
実行結果は上記のスクリーンショットを参照してほしい。
名前付きパラメーターに対応した REST API サーバー
REST API サーバーを定義してみるとリソースの ID などパスに含まれる値によって処理を変更したいことがある。URL の指定には正規表現を利用できるので、それを活用してパスに含まれる値を ctx.params
にマージするように RestSimlet を修正してみよう。
doGet
メソッドをオーバーライドすることで実現する。今回は仕様として提案されている RegExp Named Capture Groups を使用してみる。
Ext.define('RestSimlet', {
extend: 'Ext.ux.ajax.JsonSimlet',
alias: 'simlet.rest',
doGet: function (ctx) {
ctx.params = Ext.merge(ctx.params, this.getNamedParams(ctx));
return this.callParent(arguments);
},
doPut: function (ctx) {
return this.doGet(ctx);
},
doDelete: function (ctx) {
return this.doGet(ctx);
},
privates: {
getNamedParams: function (ctx) {
var url = ctx.url.split(/\?|#/)[0],
pattern = ctx.xhr.simlet.url;
return url.match(pattern).groups;
}
}
});
この RestSimlet を使用して REST API サーバーを定義しよう。type
に RestSimlet のエイリアスを設定し、url
に正規表現で URL を設定する。名前付きキャプチャが含まれる正規表現を指定するのがポイントだ。そして data
にはレスポンスとして返したいデータを生成する関数を指定する。ctx.params.id
に id
という名前でキャプチャされた値が入ってくる。
Ext.ux.ajax.SimManager.register([{
type: 'rest',
url: RegExp('^/users(/(?<id>\\d+))?$'),
data: function (ctx) {
switch (ctx.method.toUpperCase()) {
case 'GET':
switch (Number(ctx.params.id)) {
case 1:
this.status = 200;
this.statusText = 'OK';
return { id: 1, name: 'Alice' };
case 2:
this.status = 200;
this.statusText = 'OK';
return { id: 2, name: 'Bob' };
default:
this.status = 404;
this.statusText = 'Not Found';
return;
}
}
}
}]);
次のように Ext.Ajax でリクエストを送信することで REST API サーバーの動作を検証できる。
Ext.Ajax.request({
method: 'GET',
url: '/users/1',
success: function (response) {
console.log('GET /users/1');
console.log(response.status + ' ' + response.statusText);
console.dir(Ext.decode(response.responseText));
}
});
Ext.Ajax.request({
method: 'GET',
url: '/users/2',
success: function (response) {
console.log('GET /users/2');
console.log(response.status + ' ' + response.statusText);
console.dir(Ext.decode(response.responseText));
}
});
Ext.Ajax.request({
method: 'GET',
url: '/users/3',
failure: function (response) {
console.log('GET /users/3');
console.log(response.status + ' ' + response.statusText);
console.dir(Ext.decode(response.responseText));
}
});
実行結果は上記のスクリーンショットを参照してほしい。
REST API サーバーを含むサンプルアプリケーション
紹介した方法を使用してサンプルアプリケーションを実装してみたので参考にしてほしい。
今回は。SimManager を利用してモック REST API サーバーを実装してみた。Sencha Fiddle でのサンプル実装にぜひ活用していただきたい。
参考文献
http://examples.sencha.com/extjs/6.2.0/examples/classic/ticket-app/
https://docs.sencha.com/extjs/6.2.0/classic/Ext.ux.ajax.SimManager.html
https://docs.sencha.com/extjs/6.2.0/classic/Ext.ux.ajax.Simlet.html
https://docs.sencha.com/extjs/6.2.0/classic/Ext.ux.ajax.SimXhr.html
https://github.com/tc39/proposal-regexp-named-groups