記事の概要
非公開のGoogleスプレッドシートの情報を取得する関数をLambdaで作成
API Gatewayで呼び出すところまでの手順を記録
- 利用サービス
- Google Cloud APIs
- AWS Lambda
- AWS API Gateway
前提
- javascriptで何かしらの開発した経験がある
- Google Cloud Platformアカウントを所持している
- AWSアカウントを所持している
作業手順目次
- Google Cloud APIs
- プロジェクトの作成
- Google Sheets API ライブラリの有効化
- 認証情報の追加
- 鍵の作成
- Lambda
- 関数の作成
- node_modulesのLayers登録
- 環境変数の登録(Googleの認証情報)
- API Gateway
- APIの作成
- リソースの作成
- メソッドの作成
- APIのデプロイ
- 制限の設定
- APIの呼び出し
- サンプルコード
Google Cloud APIs
Google Cloud Platform
Googleが提供しているクラウドコンピューティングサービス
Google Cloud APIsの利用にはこのアカウントが必要
Google Cloud APIs
Googleが提供するサービスのデータを操作することができるAPIを
インターネットを通じて実行できるサービス
プロジェクトの作成
- Google Cloud Platformで新しいプロジェクトを作成
ライブラリの有効化
プロジェクトで利用するAPIを有効化する
- APIとサービス > ライブラリ
-
Google Sheets API
を選択 - 有効にする
認証情報の追加
1. APIとサービス > 認証情報
- 認証情報を作成 > サービスアカウント
- アカウント名の入力 > 完了
鍵の作成
Lambdaで利用するための認証鍵の作成
- サービスアカウントの詳細 > キー > 鍵の作成
- キータイプ JSON > 作成
- jsonがダウンロードできる(あとで内容をLambdaに登録する)
AWS Lambda
AWS(Amazon Web Services)
Amazon.comにより提供されているクラウドコンピューティングサービス
Lambda
サーバーレスで開発したプログラムを実行できるようにするサービス
関数の作成
- [関数名] sample-test(任意の名前でOK)
- [作成方法] 一から作成
- [ランタイム] Node.js 14.x
- [アーキテクチャ] x86_64
新規作成直後のコード
exports.handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
node_modulesのLayers登録
AWS Lambda Layers
複数のLambda関数で外部ライブラリなどを共有できる仕組み
Lambdaでは、ファイル量が多いとブラウザ操作が制限されるため
node_modulesを含めたコードソースをZIPで登録した場合
ブラウザ上で関数の編集や閲覧ができなくなる
この状態は関数作成時に不便なため
使っているnode_modulesをAWS Lambda Layers
に登録することで回避する
登録したレイヤーは関数の「レイヤー」に追加して利用できる
また、他の関数作成時にも同じレイヤーを利用することができる
- レイヤーの一覧 > 作成
- node_modules(以下package.jsonをローカルで展開し)をzipにしてアップロード
- レイヤーの追加
package.json
{
"dependencies": {
"googleapis": "^92.0.0"
}
}
環境変数の登録
- 関数の詳細 > 設定 > 環境変数
- 環境変数の編集 で 「環境変数の追加」を押す
- aキー名 と 値 を入力 し保存
GoogleAPIからデータを取得して返すコードの作成
// レイヤー_登録したnode_modulesにgoogleapisを含めている前提
const { google } = require('googleapis');
const sheets = google.sheets('v4');
// 登録した環境変数の取得
const SERVICE_ACCOUNT_KEY = JSON.parse(process.env.SERVICE_ACCOUNT_KEY);
// 外部ドメインからAPIを叩くのでクロスドメインの許可
const HEADERS = {
"Access-Control-Allow-Headers" : "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
};
async function execAPI(spreadsheetId, range) {
// 利用するAPIは Google spreadsheetsの情報を取得するspreadsheets
const auth = await google.auth.getClient({
credentials: SERVICE_ACCOUNT_KEY,
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
});
const apiOptions = {
auth,
spreadsheetId,
range,
};
return sheets.spreadsheets.values.get(apiOptions);
}
exports.handler = async (event) => {
// event?.pathParameters でAWS API Gatewayで作成したパスパラメータを取得
const spreadsheetId = event?.pathParameters?.spreadsheetId;
const range = event?.pathParameters?.range ? decodeURI(event?.pathParameters?.range) : 'シート1';
let response = {};
let responseBody = {}
await execAPI(spreadsheetId, range).then((t) => {
responseBody = t;
})
// getメソッドとして返す場合のオブジェクト形式
response = {
"statusCode": 200,
"body": JSON.stringify(responseBody),
"headers": HEADERS,
};
return response;
};
AWS API Gateway
Lambdaで作成した関数を呼び出せるREST APIの作成を行う
AWS API Gateway
簡単にAPIの作成、配布、保守、監視、保護が行えるマネージドサービス
- APIの作成
- リソースの作成
- API Gateway CORSを有効にする
- メソッドの作成
- APIのデプロイ
- 制限の設定
APIの作成
- APIの作成
- REST APIを構築
- API > 作成
- [プロトコル] REST
- [新しいAPIの作成] 新しいAPI
- [API名] 半角英数字
- [エンドポイント] リージョン
リソースの作成
- リソースの作成
- /test
- /{spreadsheetId}
- /{range}
- API Gateway CORSを有効にする
- /{spreadsheetId}
- /test
メソッドの作成
- メソッドの作成 > GET
- Lambda関数を実行します
APIのデプロイ
作ったAPIを公開する
- プロシキの統合
- クロスドメインで実行できるようにするため
- アクション > APIのデプロイ
- レートの変更
- 必要に応じて安全なレートに変更する
- レート 10、バースト 5 は1ヶ月呼び出され続けても一万円ほどでおさまる想定の値
制限の設定
セキュリティを考慮して呼び出し処理に制限をかける
- APIキーがなければ呼び出せない
- APIキーを使っていても設定したプラン以上の呼び出しは行えない
手順
- APIキーの追加
- 使用量プランの作成
- APIステージの追加
- APIキーを使用プランに追加
- APIキーに使用料プランの設定
APIの呼び出し
サンプルコード
<html>
<header>
<script>
function getLocalApi() {
const sheetId = document.getElementById('sheetId').value;
const range = document.getElementById('range').value || 'シート1';
const request = new XMLHttpRequest()
request.open('GET', `https://[ドメイン]/[ステージ名]/test/${sheetId}/${range}`)
request.setRequestHeader('Content-Type', 'application/json');
request.setRequestHeader('x-api-key', '[APIキー]');
request.responseType = 'json'
request.send();
request.onerror = function(e){
console.log(e);
alert('データが取得できませんでした');
};
request.onload = () => {
if (request.status === 200) {
console.log(request.response);
alert('データが取得できました');
}
};
}
</script>
</header>
<body>
<input type="text" id="sheetId" name="sheetId" size="20" value="" placeholder="sheetId" required>
<input type="text" id="range" name="range" size="20" value="" placeholder="range" required>
<hr style="margin-top: 20px;">
<button type="button" onclick="getLocalApi()">
サービスアカウントからデータ取得
</button>
</body>
</html>
コードに必要な ドメイン / ステージ名 / APIキー は以下の画面から取得
実行テスト
- スプレッドシートを作成
- Googleサービスアカウントユーザーを編集者に追加
- スプレッドシートのシートIDで実行して取得完了!
まとめ
外部サービスからGoogleのデータを取得できないか模索したところ
AWSについて教えてもらい、この機会に資料にまとめた。
クロスブラウザが可能な外部サービスであれば色んな面白いことができそう。
次回はこれを利用して作成したFigmaプラグインについてまとめる。
参考
GoogleAPI
GoogleAPIをフロントで呼び出す時のサンプルコード
GoogleSheetsAPIのGETエンドポイントサンプルコード
使ってないけどリダイレクトでAuth認証するための方法
APIGateway
Lambda プロキシ統合の使用って何??
APIGatewayでクロスオリジンのためのOption関数を設定する話
APIGatewayでパスパラメータを設定する方法
APIGatewayのAPIキー設定する方法
Lambda
Lambda関数のレスポンスの形式を正しく渡さないとクロスオリジン解決できないよって話の参考
Lambda関数のレスポンスの形式を正しく渡さないとAPIGatewayから怒られる話
Lambdaで環境変数を使う方法
Lambdaでnode_modulesもzipにしてアップロードしないといけなかった話