#前回までのあらすじ
前々回の記事でAPI Gatewayを使ってAPIのモックを作ってみました。
API Gatewayの統合リクエストの統合タイプ:Mockを使えば固定値を返すAPIモックは簡単に作れることが分かったので、今後も業務でちょこちょこ作っていこうと思います。
が、いちいちAWSコンソールから作るのが面倒なので、Slackからサクッと作れるようにしたいと思います。
#API Gatewayを作るLambda(Python)の作成
PythonからAWSをコントロールするためにBoto3
を使います。
参考にしたBoto3のドキュメント。
##Slackでのキーワード
Slackからは以下のキーワードでAPI Gatewayを作ることにします。
api_gateway [API名] [リソース名] [メソッド] [ステータスコード] [レスポンスボディ] [ステージ名]
Slackから受け取った上記のキーワードをLambdaでは以下のように取り出して変数に格納することにします。
# クエリ文字列解析
query = parse_qs(event.get('body') or '')
SETTINGS = query.get('text', [''])[0].split(' ')
API_GATEWAY_NAME = SETTINGS[1] # API名
PATH_PART = SETTINGS[2] # リソース名
HTTP_METHOD = SETTINGS[3] # メソッド
STATUS_CODE = SETTINGS[4] # ステータスコード
RESPONSE_TEMPLATES = SETTINGS[5] # レスポンスボディ
STAGE_NAME = SETTINGS[6] # ステージ名
##API Gatewayの作成
REST_API_ID = agw.create_rest_api(name = API_GATEWAY_NAME)
##ルートのリソースIDの取得とリソースの作成
# ルートのリソースIDの取得
PARENT_ID = agw.get_resources(restApiId = REST_API_ID['id'])
# リソースの作成
RESOURCE_ID = agw.create_resource(
restApiId = REST_API_ID['id'],
parentId = PARENT_ID['items'][0]['id'],
pathPart = PATH_PART
)
##メソッドリクエストの作成
agw.put_method(
restApiId = REST_API_ID['id'],
resourceId = RESOURCE_ID['id'],
httpMethod = HTTP_METHOD,
authorizationType = 'None'
)
##統合リクエストの作成
agw.put_integration(
restApiId = REST_API_ID['id'],
resourceId = RESOURCE_ID['id'],
httpMethod = HTTP_METHOD,
type = 'MOCK',
requestTemplates = {'application/json':'{"statusCode":' + STATUS_CODE + '}'}
)
##メソッドレスポンスの作成
agw.put_method_response(
restApiId = REST_API_ID['id'],
resourceId = RESOURCE_ID['id'],
httpMethod = HTTP_METHOD,
statusCode = STATUS_CODE,
responseModels = {'application/json': 'Empty'}
)
##統合レスポンスの作成
agw.put_integration_response(
restApiId = REST_API_ID['id'],
resourceId = RESOURCE_ID['id'],
httpMethod = HTTP_METHOD,
statusCode = STATUS_CODE,
responseTemplates = {'application/json': RESPONSE_TEMPLATES }
)
##作成したAPIのデプロイ
agw.create_deployment(
restApiId = REST_API_ID['id'],
stageName = STAGE_NAME
)
##呼び出しURLをSlackに返す
手を抜いてリージョンはコードに埋め込んでいるので、可変にしたい場合は変数で逃しておいてください。
RESOURCE_NAME = agw.get_resources(restApiId = REST_API_ID['id'])
URL = 'https://' + REST_API_ID['id'] + '.execute-api.ap-northeast-1.amazonaws.com/' + STAGE_NAME + '/' + PATH_PART
return {
'statusCode': 200,
'body': json.dumps({
'text': URL
})
}
##コードのまとめ
上記のコードをまとめると以下のようになります。
余計なリクエストを受けないようにSlackトークンをチェックしています。
SlackトークンはLambdaの環境変数にセットしそれをos.environ.get('SLACK_TOKEN')
で呼び出しています。
Slackのキーワードが不足している時の処理などは入れていないので、必要に応じて追加してください。
import boto3
import json
import os
from urllib.parse import parse_qs
agw = boto3.client('apigateway')
token = os.environ.get('SLACK_TOKEN')
def lambda_handler(event, context):
# クエリ文字列解析
query = parse_qs(event.get('body') or '')
# 設定値
SETTINGS = query.get('text', [''])[0].split(' ')
API_GATEWAY_NAME = SETTINGS[1] # API名
PATH_PART = SETTINGS[2] # リソース名
HTTP_METHOD = SETTINGS[3] # メソッド
STATUS_CODE = SETTINGS[4] # ステータスコード
RESPONSE_TEMPLATES = SETTINGS[5] # レスポンスボディ
STAGE_NAME = SETTINGS[6] # ステージ名
# slackトークンの確認
if query.get('token', [''])[0] != token:
return { 'statusCode': 400 }
# API Gatewayの作成
REST_API_ID = agw.create_rest_api(name = API_GATEWAY_NAME)
# ルートのリソースIDの取得
PARENT_ID = agw.get_resources(restApiId = REST_API_ID['id'])
# リソースの作成
RESOURCE_ID = agw.create_resource(
restApiId = REST_API_ID['id'],
parentId = PARENT_ID['items'][0]['id'],
pathPart = PATH_PART
)
# メソッドリクエストの作成
agw.put_method(
restApiId = REST_API_ID['id'],
resourceId = RESOURCE_ID['id'],
httpMethod = HTTP_METHOD,
authorizationType = 'None'
)
# 統合リクエストの作成
agw.put_integration(
restApiId = REST_API_ID['id'],
resourceId = RESOURCE_ID['id'],
httpMethod = HTTP_METHOD,
type = 'MOCK',
requestTemplates = {'application/json':'{"statusCode":' + STATUS_CODE + '}'}
)
# メソッドレスポンスの作成
agw.put_method_response(
restApiId = REST_API_ID['id'],
resourceId = RESOURCE_ID['id'],
httpMethod = HTTP_METHOD,
statusCode = STATUS_CODE,
responseModels = {'application/json': 'Empty'}
)
# 統合レスポンスの作成
agw.put_integration_response(
restApiId = REST_API_ID['id'],
resourceId = RESOURCE_ID['id'],
httpMethod = HTTP_METHOD,
statusCode = STATUS_CODE,
responseTemplates = {'application/json': RESPONSE_TEMPLATES }
)
# 作成したAPIのデプロイ
agw.create_deployment(
restApiId = REST_API_ID['id'],
stageName = STAGE_NAME
)
# 呼び出しURLをSlackに返す
RESOURCE_NAME = agw.get_resources(restApiId = REST_API_ID['id'])
URL = 'https://' + REST_API_ID['id'] + '.execute-api.ap-northeast-1.amazonaws.com/' + STAGE_NAME + '/' + PATH_PART
return {
'statusCode': 200,
'body': json.dumps({
'text': URL
})
}
#AWS Gatewayの作成
上記で作ったLambdaを呼び出すAPI Gatewayを以下の設定で作成します。
・ プロトコル:REST
・ メソッド:POST
・ 統合リクエスト
・ 統合タイプ:Lambda関数
・ Lambdaプロキシ統合の使用:チェックON
・ Lambda関数:作成したLambda関数を指定
#Slackの発信Webhookの作成
・ Outgoing Webhookで
・ チャンネル:botを参加させるSlackチャンネルを指定
・ 引き金となる言葉:Lambda関数を起動させるトリガー(今回は「api_gateway」と指定)
・ URL:上で作成したAPI Gatewayのステージの呼び出しURL
・ トークン:表示されているトークンをコピーして、Lambda関数の環境変数に登録
・ キー:SLACK_TOKEN(今回の場合)、値:Slackに表示されているトークン
名前のカスタマイズやアイコンはお好みで。
#まとめ
SlackからAPI Gatewayを作れるようになりました。
API Gatewayの削除などまだまだ足りない機能はありますが、上記を参考に追加してみてください。
#プチ連載
1回目 AWS API Gatewayでモックを作ってみよう
2回目 AWS API Gateway + Lambda (Python) でモックを作ってみよう
3回目 Slack + Lambda (Python) でAWS API Gatewayモックを作ってみよう(本記事)
#We're hiring!
AIチャットボットを開発しています。
ご興味ある方は Wantedlyページ からお気軽にご連絡ください!
#参考記事
Boto3 Docs Lambda
Qiita AWS Lambda (Python3) + API Gateway で Slackのbotを作ろう
Qiita [JAWS-UG CLI] API Gateway: #1 RestAPIの作成
Qiita AWS CLIのレスポンス処理は jq 使う前に --query オプションの利用を考えてみよう!
Qiita 【AWS Lambda】API Gatewayを一発で作成するスクリプトを作成してみた(Python版)
AWS CLI Command Reference apigateway