目次

概要

AWS LambdaからBox Node SDKを用いてBoxのAPIを利用するための手順

参考

box-node-lambda-sample

JWTアプリの作成

  • JWT認証アプリを作成
  • 公開鍵ペアを追加
  • 管理コンソール > カスタムアプリに登録

Lambda関数の作成

設計図 > boxで検索
box-node-lambda-sample を選択

aws_lambda_boxnodesdk_1.png

名前:box-node-lambda-sample

ロール:
1つ以上のテンプレートから新しいロールを作成

ロール名:
box-node-lambda-sample-role

ポリシーテンプレート:
空欄のまま

aws_lambda_boxnodesdk_2.png

環境変数BOX_CONFIGの値にJWTアプリのconfigファイルの内容をそのまま貼り付け

aws_lambda_boxnodesdk_3.png

関数の作成 を実行
関数が作成される

関数のテスト

テスト を選択

aws_lambda_boxnodesdk_4.png

テストイベントの作成 画面
このサンプルコードは入力を必要としないので、デフォルトで表示されたHello Worldのままでよい。
イベント名を適当に入力し、「作成」

aws_lambda_boxnodesdk_5.png

aws_lambda_boxnodesdk_6.png

関数の画面に戻るので、「テスト」を実行
実行結果を確認
ユーザー情報が表示されていれば成功
※このサンプルアプリは、自分自身(つまりJWTアプリのサービスアカウント)の情報をAPIで問い合わせ、結果を取得して終了する。

aws_lambda_boxnodesdk_7.png

戻り値の例

{
  "type": "user",
  "id": "サービスアカウントのユーザID",
  "name": "Lambda-nodesdk-test01",
  "login": "AutomationUser_(省略)@boxdevedition.com",
  "created_at": "2019-03-02T21:23:02-08:00",
  "modified_at": "2019-03-02T21:23:02-08:00",
  "language": "ja",
  "timezone": "Asia/Tokyo",
  "space_amount": 10737418240,
  "space_used": 0,
  "max_upload_size": 5368709120,
  "status": "active",
  "job_title": "",
  "phone": "",
  "address": "",
  "avatar_url": "https://boxpocsite.app.box.com/api/avatar/large/xxxxxxx"
}

ソースコードの解読 (途中)

ソースコード全体

/**
 * This sample demonstrates how to call Box APIs from a Lambda function using the Box Node SDK.
 *
 * For step-by-step instructions on how to create and authorize a Box application,
 * see https://github.com/box/samples/tree/master/box-node-lambda-sample.
 */

'use strict';

const BoxSDK = require('box-node-sdk');

// Load the config from an environment variable for security and configuration management.
const boxConfig = JSON.parse(process.env.BOX_CONFIG);

boxConfig.boxAppSettings.appAuth.keyID = boxConfig.boxAppSettings.appAuth.publicKeyID;

const sdk = new BoxSDK(boxConfig.boxAppSettings);

/**
 * Create a service account client that performs actions in the context of the specified
 * enterprise.  The app has a unique service account in each enterprise that authorizes the app.
 * The service account contains any app-specific content for that enterprise.
 * Depending on the scopes selected, it can also create and manage app users or managed users
 * in that enterprise.
 *
 * The client will automatically create and refresh the service account access token, as needed.
 */
const client = sdk.getAppAuthClient('enterprise', boxConfig.enterpriseID);

/**
 *  YOUR CODE GOES HERE!!!
 *
 *  This sample function returns details of the current user (the service account).
 */
exports.handler = (event, context, callback) => {
    console.log(`Event: ${JSON.stringify(event, null, 2)}`);

    // Get details on the current user  (the service account)
    client.users.get(client.CURRENT_USER_ID, null, (err, result) => {
        let response;

        if (err) {
            if (err.response && err.response.body) {
                response = err.response.body;
            } else {
                response = err.toString();
            }
        } else {
            response = result;
        }

        console.log(`Response: ${JSON.stringify(response, null, 2)}`);
        callback(null, response);
    });
};

解読とお勉強

'use strict';

const BoxSDK = require('box-node-sdk');

// Load the config from an environment variable for security and configuration management.
const boxConfig = JSON.parse(process.env.BOX_CONFIG);

Box Node SDKを呼び出し
設定ファイルのJsonを読み込んで、boxConfigに格納

boxConfig.boxAppSettings.appAuth.keyID = boxConfig.boxAppSettings.appAuth.publicKeyID;

公開鍵のIDを取得

const sdk = new BoxSDK(boxConfig.boxAppSettings);

BoxSDKに設定ファイル(認証情報など)を読ませて、インスタンスオブジェクトsdkを作成

const client = sdk.getAppAuthClient('enterprise', boxConfig.enterpriseID);

sdkからclientオブジェクトを作成
以降、このクライアントオブジェクトのメソッドを使ってファイル/フォルダ作成など行う

exports.handler = (event, context, callback) => {
    console.log(`Event: ${JSON.stringify(event, null, 2)}`);

    // Get details on the current user  (the service account)
    client.users.get(client.CURRENT_USER_ID, null, (err, result) => {
        let response;

        if (err) {
            if (err.response && err.response.body) {
                response = err.response.body;
            } else {
                response = err.toString();
            }
        } else {
            response = result;
        }

        console.log(`Response: ${JSON.stringify(response, null, 2)}`);
        callback(null, response);
    });
};

以下、処理ブロックごとにバラして読んでいきます。

exports.handler = (event, context, callback) => {

handler : AWS Lambda が呼び出す関数の名前

event: Lambdaはイベントによって実行される。 API Gatewayに何か着信したとき、受け取った内容(WebHookやPOSTのデータなど)がこのeventに格納されてLambda関数に渡されて、実行される。

context: よくわからない

callback:
callbackはコールバック関数を意味する。
callback関数の本体は最下行のあたりにある

callback(null, response);

で、第2引数のresponseがこのLambda関数の実行結果となる。

コールバックパラメーターを使用するためのオプション

// Get details on the current user  (the service account)
client.users.get(client.CURRENT_USER_ID, null, (err, result) => {
    let response;

自分自身のユーザ情報を取得するための関数を定義
=>があるのでアロー関数で書かれている
2行目で、実行結果を格納するための変数responseをletで定義
letなので、後から変数responseの中身を上書きすることはできない。

clientオブジェクト > users > getメソッドを実行
第1引数: client.CURRENT_USER_ID 現在のユーザIDを指定

第2引数: null よくわからない

if (err) {
    if (err.response && err.response.body) {
        response = err.response.body;
    } else {
        response = err.toString();
    }
} else {
    response = result;
}

実行結果がエラーになると、変数errに値が入る。
値が入ると評価式のif(err)条件を満たすので、ブロック{ }の中の処理が実行される

if (err.response && err.response.body) {
    response = err.response.body;
} else {
    response = err.toString();
}

APIコールの結果がエラーとなった戻り値にBodyがあるか判定
Bodyがある場合は、変数responseにBodyの中身を格納する
Bodyがない場合は、変数responsetoString()を格納する。
toStringとは、エラーを表す文字列のことらしい。

Error.prototype.toString()

toString() メソッドは、指定した Error オブジェクトを表す文字列を返します。

} else {
    response = result;
}

APIコールの結果がエラーとならなかった場合(つまり正常終了のとき)に実行されるブロック
変数responseにresultの中身を代入する。

console.log(`Response: ${JSON.stringify(response, null, 2)}`);

コンソールへのログ出力
Json形式で帰ってきた戻り値をstringifyで文字列化している
引数は3つ:

  • response: 前の処理でのAPI実行結果が格納されている変数
  • null: replacerの指定。現時点では完全に理解を超えているのでパス。将来の自分に期待。
  • 2: 整形して出力するときのインデント幅を指定(本例ではスペース2つ分)

    callback(null, response);
    

このLambda関数で実行されるコールバック関数。
第1引数のnullはよくわからない
第2引数のresponseがこのLambda関数そのものの戻り値になる。