kintoneと異なるドメインのサイト(HTMLページ)からkintone APIを直接実行してもエラーが発生して実行できません。
(function() {
$.ajax({
type: 'GET',
url: 'https://subdomain.cybozu.com/k/v1/records.json?app=アプリID',
success: function(data) {
console.log(data);
}
});
})();
上のコードを含んだHTMLページをlocalhost上で表示すると、以下のエラーがブラウザのコンソールに出力されます。
ブラウザにはクロスドメインでの通信を拒否する仕組みがあり、それを回避するためにはJSONPとかCORSといった方法があるのですが、kintoneはどちらも利用できないため、サーバーを用意してそこからAPIを実行する必要があります。
ブラウザ <-> サーバー <-(API)-> kintone
Amazon API GatewayにはCORSの仕組みがあるので、API Gatewayを使ってブラウザからのAPI実行を実現してみたいと思います。
構成はこんな感じ。
ブラウザ <-> API Gateway <-> Lambda <-(API)-> kintone
Lambdaからkintoneの呼び出し
こちらを参考に作ります。
今回は以下のコードでkintoneのレコードを取得してみたいと思います。
var aws = require('aws-sdk');
var request = require('request');
/* kintone用のパラメータ(変更が必要) */
var DOMAIN = 'subdomain.cybozu.com'; //kintone環境のドメイン
var APP_ID = 1; //アプリID
var LOGIN_NAME = 'Administrator';
var PASSWORD = 'secret';
/* 変更は不要 */
var BASE_URL = "https://" + DOMAIN + '/k/v1/';
var AUTH_VALUE = new Buffer(LOGIN_NAME + ':' + PASSWORD).toString('base64');
var headers = {'X-Cybozu-Authorization': AUTH_VALUE};
exports.handler = function(event, context) {
var body_getrecords = {
app: APP_ID
}
//販売実績アプリからレコードを取得する際のヘッダー
var options_getrecords = {
url: BASE_URL + 'records.json',
method: 'GET',
headers: headers,
'Content-Type': 'application/json',
json: body_getrecords
}
//レコードを取得
request(options_getrecords, function (error, response, body) {
if (!error && response.statusCode == 200) {
//取得した結果から販売実績を取得し、レコードの数だけ合算する
var records = body.records;
console.log(records);
context.done(null, records);
}
})
};
API GatewayからLambdaの呼び出し
クラメソさんのブログが分かりやすかったのでこちらを参照。(「2.Amazon API Gateway画面へ」の辺り)
リソース名は適当(今回はkintonerecordsとした)、メソッドはGETにします。
Integration typeに「Lambda Function」を選び、先程作ったファンクションを選びます。
Testを実行して、結果が返る事を確認します。(日本語化けてる・・・)
デプロイして発行されたエンドポイントにアクセスすると、レコードが取得できます。
(Chromeだと文字化けしまくってるけど、Firefoxだと問題無かった)
CORSの設定
さぁ、HTMLから実行しよう!と思いたいところだけど、このままだとAPI Gatewayのクロスオリジンのエラーになるので、API GatewayにCORSの設定をしてあげる必要がある。
詳細はこちらに書いてある。
実際の手順はこちらの方が分かりやすい。
※手元の環境では、「メソッドのCORS設定」で「Integration Response」の「Header Mappings」の設定で、「Access-Control-Allow-Origin」に対して「'*'」を設定する必要があった
[Create Method]でメソッドを追加する際、GETやPOSTだけで無く、OPTIONSも追加しましょう。
Integration typeはMock IntegrationでOK。
この状態でHTMLからエンドポイントを実行すると、kintoneのレコードが取得されている事が分かる。
(見づらいのでconsole.logをconsole.tableにしてる)
余談
このままだとURL叩くだけでレコードが見えちゃうので、API Gateway側でAPIキー認証を設定しておくと良いかもしれない。
Amazon API GatewayでAPIキー認証を設定する
と思って試したけど、JavaScriptからうまくAPIキーがヘッダーに乗ってくれず成功していない・・・。
JavaScript SDKを使ってもうまくいかずで原因調査中。
当初うまくいかなかったのは、preflightリクエスト(OPTIONSメソッド)が403 Forbiddenになっていた事が原因っぽい。
OPTIONSメソッドのAPI Key Requiredをfalseにする事で解決。
APIキーを送信する場合のコードはこんな感じ。
(function() {
$.ajax({
type: 'GET',
url: 'https://subdomain.cybozu.com/k/v1/records.json?app=アプリID',
headers: {
'x-api-key': 'APIキー'
},
success: function(data) {
console.log(data);
}
});
})();
参考までにヘッダー情報も。(余計なヘッダーも追加されている可能性はある・・・)
OPTIONSメソッド
(POSTメソッドを実行した際は、Access-Control-Request-Method:POSTとなる)