4
0

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.

Ext JS の SimManager を利用してモック REST API サーバーを実装する

Posted at

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.DataSimletExt.ux.ajax.XmlSimletExt.ux.ajax.JsonSimletExt.ux.ajax.PivotSimlet がある。おそらく JsonSimlet の使用頻度が高くなるはずだ。

Ext.ux.ajax.SimXhr は XMLHttpRequest オブジェクトをシミュレートする。SimXhr の中には Simlet が含まれていて、その Simlet がレスポンスを生成しているのだ。

静的 API サーバー

static-api-server.png

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 サーバー

dynamic-api-server.png

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-server.png

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-server-with-named-parameters.png

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.idid という名前でキャプチャされた値が入ってくる。

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 サーバーを含むサンプルアプリケーション

crud-sample-with-rest-api-server.png

紹介した方法を使用してサンプルアプリケーションを実装してみたので参考にしてほしい。


今回は。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

4
0
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
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?