35
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Organization

外部サイトから直接kintone APIを実行したい

kintoneと異なるドメインのサイト(HTMLページ)からkintone APIを直接実行してもエラーが発生して実行できません。

kintone_test.html
(function() {
    $.ajax({
        type: 'GET',
        url: 'https://subdomain.cybozu.com/k/v1/records.json?app=アプリID',
        success: function(data) {
            console.log(data);
        }
    });
})();

上のコードを含んだHTMLページをlocalhost上で表示すると、以下のエラーがブラウザのコンソールに出力されます。
origin.png

ブラウザにはクロスドメインでの通信を拒否する仕組みがあり、それを回避するためにはJSONPとかCORSといった方法があるのですが、kintoneはどちらも利用できないため、サーバーを用意してそこからAPIを実行する必要があります。

ブラウザ <-> サーバー <-(API)-> kintone

Amazon API GatewayにはCORSの仕組みがあるので、API Gatewayを使ってブラウザからのAPI実行を実現してみたいと思います。
構成はこんな感じ。

ブラウザ <-> API Gateway <-> Lambda <-(API)-> kintone

Lambdaからkintoneの呼び出し

こちらを参考に作ります。

今回は以下のコードでkintoneのレコードを取得してみたいと思います。

index.js
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を実行して、結果が返る事を確認します。(日本語化けてる・・・)
FireShot Screen Capture #113 - 'API Gateway' - ap-northeast-1_console_aws_amazon_com_apigateway_home_region=ap-northeast-1#_apis_8rvhf5thtg_resources_nmabpk_methods_GET.png

デプロイして発行されたエンドポイントにアクセスすると、レコードが取得できます。
(Chromeだと文字化けしまくってるけど、Firefoxだと問題無かった)
FireShot Screen Capture #114 - '' - 8rvhf5thtg_execute-api_ap-northeast-1_amazonaws_com_prod_kintonerecords.png

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。

こんな感じになるはず。
FireShot Screen Capture #115 - 'API Gateway' - ap-northeast-1_console_aws_amazon_com_apigateway_home_region=ap-northeast-1#_apis_8rvhf5thtg_resources_nmabpk_methods_GET.png
FireShot Screen Capture #116 - 'API Gateway' - ap-northeast-1_console_aws_amazon_com_apigateway_home_region=ap-northeast-1#_apis_8rvhf5thtg_resources_nmabpk_methods_GET.png

この状態でHTMLからエンドポイントを実行すると、kintoneのレコードが取得されている事が分かる。
(見づらいのでconsole.logをconsole.tableにしてる)
console.png

余談

このままだとURL叩くだけでレコードが見えちゃうので、API Gateway側でAPIキー認証を設定しておくと良いかもしれない。
Amazon API GatewayでAPIキー認証を設定する

と思って試したけど、JavaScriptからうまくAPIキーがヘッダーに乗ってくれず成功していない・・・。
JavaScript SDKを使ってもうまくいかずで原因調査中。

当初うまくいかなかったのは、preflightリクエスト(OPTIONSメソッド)が403 Forbiddenになっていた事が原因っぽい。
OPTIONSメソッドのAPI Key Requiredをfalseにする事で解決。
FireShot Screen Capture #117 - 'API Gateway' - ap-northeast-1_console_aws_amazon_com_apigateway_home_region=ap-northeast-1#_apis_8rvhf5thtg_resources_nmabpk_methods_OPTIONS.png

APIキーを送信する場合のコードはこんな感じ。

kintone_test.html
(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メソッド
options.png
(POSTメソッドを実行した際は、Access-Control-Request-Method:POSTとなる)

GET
GET.png

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
35
Help us understand the problem. What are the problem?