前提条件
API Gatewayへの権限
API Gatewayに対してフル権限があること。
AWS CLI
以下のバージョンで動作確認済
- AWS CLI 1.9.8
aws --version
aws-cli/1.9.8 Python/2.7.5 Darwin/13.4.0 botocore/1.3.0
- 準備
=======
0.1. 変数の確認
プロファイルが想定のものになっていることを確認します。
aws configure list
Name Value Type Location
---- ----- ---- --------
profile administrator-prjz-mbp13 env AWS_DEFAULT_PROFILE
access_key ****************XXXX shared-credentials-file
secret_key ****************XXXX shared-credentials-file
region ap-northeast-1 env AWS_DEFAULT_REGION
プロファイルが想定のものになっていることを確認します。
0.2. リージョンの取得
AWS_REGION='ap-northeast-1'
0.3. Lambda関数のARN取得
LAMBDA_FUNC_NAME='GetHelloWithName'
LAMBDA_FUNC_ARN=$( \
aws lambda get-function \
--function-name ${LAMBDA_FUNC_NAME} \
--query 'Configuration.FunctionArn' \
--output text \
) \
&& echo ${LAMBDA_FUNC_ARN}
- 事前作業
===========
API名の指定
APIGW_API_NAME='MyDemoAPI'
同名のREST APIが存在しないことを確認します。
aws apigateway get-rest-api \
--rest-api-id ${APIGW_API_NAME}
A client error (NotFoundException) occurred when calling the GetRestApi operation: Invalid REST API identifier specified
2. APIの作成
2.1. APIの作成
APIを作成するときは、説明も必ず入れるようにしましょう。
APIGW_API_DESC='This is my API for demonstration purposes'
cat << ETX
APIGW_API_NAME: ${APIGW_API_NAME}
APIGW_API_DESC: "${APIGW_API_DESC}"
ETX
aws apigateway create-rest-api \
--name ${APIGW_API_NAME} \
--description "${APIGW_API_DESC}"
{
"id": "xxxxxxxxxx",
"name": "MyDemoAPI",
"description": "This is my API for demonstration purposes",
"createdDate": 1448002904
}
2.2. APIの確認
aws apigateway get-rest-apis
{
"items": [
{
"description": "This is my API for demonstration purposes",
"createdDate": 1445947998,
"id": "xxxxxxxxxx",
"name": "MyDemoAPI"
}
]
}
APIGW_API_ID=$( \
aws apigateway get-rest-apis \
--query "items[?name == \`${APIGW_API_NAME}\`].id" \
--output text \
) \
&& echo ${APIGW_API_ID}
xxxxxxxxxx
aws apigateway get-rest-api \
--rest-api-id ${APIGW_API_ID}
{
"id": "xxxxxxxxxx",
"name": "MyDemoAPI",
"description": "This is my API for demonstration purposes",
"createdDate": 1445947998
}
2.3. アカウントの確認
aws apigateway get-account
{
"throttleSettings": {
"rateLimit": 500.0,
"burstLimit": 1000
}
}
2.4. モデルの確認
aws apigateway get-models \
--rest-api-id ${APIGW_API_ID}
{
"items": [
{
"description": "This is a default empty schema model",
"schema": "{\n \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n \"title\" : \"Empty Schema\",\n \"type\" : \"object\"\n}",
"contentType": "application/json",
"id": "xxxxxx",
"name": "Empty"
},
{
"description": "This is a default error schema model",
"schema": "{\n \"$schema\" : \"http://json-schema.org/draft-04/schema#\",\n \"title\" : \"Error Schema\",\n \"type\" : \"object\",\n \"properties\" : {\n \"message\" : { \"type\" : \"string\" }\n }\n}",
"contentType": "application/json",
"id": "xxxxxx",
"name": "Error"
}
]
}
3. リソースの作成
3.1. 現在のリソースの確認
aws apigateway get-resources \
--rest-api-id ${APIGW_API_ID}
{
"items": [
{
"path": "/",
"id": "xxxxxxxxxx"
}
]
}
3.2. 現在のリソースのリソースID取得
APIGW_RESOURCE_PATH="/"
APIGW_RESOURCE_ID=$( \
aws apigateway get-resources \
--rest-api-id ${APIGW_API_ID} \
--query "items[?path == \`${APIGW_RESOURCE_PATH}\`].id" \
--output text \
) \
&& echo ${APIGW_RESOURCE_ID}
xxxxxxxxxx
aws apigateway get-resource \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID}
{
"path": "/",
"id": "xxxxxxxxxx"
}
3.3. 新しいリソースの作成
APIGW_PARENT_ID="${APIGW_RESOURCE_ID}"
APIGW_PATH_PART='mydemoresource'
cat << ETX
APIGW_API_ID: ${APIGW_API_ID}
APIGW_PARENT_ID: ${APIGW_PARENT_ID}
APIGW_PATH_PART: ${APIGW_PATH_PART}
ETX
aws apigateway create-resource \
--rest-api-id ${APIGW_API_ID} \
--parent-id ${APIGW_PARENT_ID} \
--path-part ${APIGW_PATH_PART}
{
"path": "/mydemoresource",
"pathPart": "mydemoresource",
"id": "xxxxxx",
"parentId": "xxxxxxxxxx"
}
3.4. 新しいリソースのリソースID取得
APIGW_RESOURCE_PATH="${APIGW_RESOURCE_PATH}${APIGW_PATH_PART}" \
&& echo ${APIGW_RESOURCE_PATH}
APIGW_RESOURCE_ID=$( \
aws apigateway get-resources \
--rest-api-id ${APIGW_API_ID} \
--query "items[?path == \`${APIGW_RESOURCE_PATH}\`].id" \
--output text \
) \
&& echo ${APIGW_RESOURCE_ID}
xxxxxx
3.5. 新しいリソースの内容確認
aws apigateway get-resource \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID}
{
"path": "/mydemoresource",
"pathPart": "mydemoresource",
"id": "xxxxxx",
"parentId": "xxxxxxxxxx"
}
4. Lambda関数の指定
APIGW_INTEG_TYPE='AWS'
APIGW_INTEG_URI="arn:aws:apigateway:${AWS_REGION}:lambda:path/2015-03-31/functions/${LAMBDA_FUNC_ARN}/invocations" \
&& echo ${APIGW_INTEG_URI}
arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName
APIGW_INTEG_METHOD='POST'
5. GETメソッドの作成
5.1. methodの作成
HTTP_METHOD='GET'
AUTH_TYPE='NONE'
cat << ETX
APIGW_API_ID: ${APIGW_API_ID}
APIGW_RESOURCE_ID: ${APIGW_RESOURCE_ID}
HTTP_METHOD: ${HTTP_METHOD}
AUTH_TYPE: ${AUTH_TYPE}
ETX
aws apigateway put-method \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--authorization-type ${AUTH_TYPE}
{
"apiKeyRequired": false,
"httpMethod": "GET",
"authorizationType": "NONE"
}
aws apigateway get-method \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD}
5.2. integrationの作成
aws apigateway get-integration \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD}
A client error (NotFoundException) occurred when calling the GetIntegration operation: No integration defined for method
cat << ETX
APIGW_API_ID: ${APIGW_API_ID}
APIGW_RESOURCE_ID: ${APIGW_RESOURCE_ID}
HTTP_METHOD: ${HTTP_METHOD}
APIGW_INTEG_TYPE: ${APIGW_INTEG_TYPE}
APIGW_INTEG_METHOD: ${APIGW_INTEG_METHOD}
APIGW_INTEG_URI: ${APIGW_INTEG_URI}
ETX
aws apigateway put-integration \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--type ${APIGW_INTEG_TYPE} \
--integration-http-method ${APIGW_INTEG_METHOD} \
--uri ${APIGW_INTEG_URI}
{
"httpMethod": "GET",
"type": "AWS",
"uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName/invocations",
"cacheNamespace": "xxxxxx"
}
aws apigateway get-integration \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD}
{
"httpMethod": "POST",
"cacheKeyParameters": [],
"type": "AWS",
"uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName/invocations",
"cacheNamespace": "5toub6"
}
5.3. Integration Responseの作成
GETメソッドのリザルトコード200でのIntegration Responseが存在作成しないことを確認します。
HTTP_STATUS_CODE='200'
aws apigateway get-integration-response \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--status-code ${HTTP_STATUS_CODE}
A client error (NotFoundException) occurred when calling the GetMethodResponse operation: Invalid Response status code specified
GETメソッドのリザルトコード200でのIntegration Responseを作成します。
cat << ETX
APIGW_API_ID: ${APIGW_API_ID}
APIGW_RESOURCE_ID: ${APIGW_RESOURCE_ID}
HTTP_METHOD: ${HTTP_METHOD}
HTTP_STATUS_CODE: ${HTTP_STATUS_CODE}
ETX
aws apigateway put-integration-response \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--status-code ${HTTP_STATUS_CODE} \
--response-templates '{"application/json":""}'
{
"statusCode": "200",
"responseTemplates": {
"application/json": null
}
}
GETメソッドのリザルトコード200でのIntegration Responseを確認します。
aws apigateway get-integration-response \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--status-code ${HTTP_STATUS_CODE}
{
"statusCode": "200",
"responseTemplates": {
"application/json": null
}
}
GETメソッドのIntegrationにリザルトコード200でのIntegration Responseが存在することを確認します。
aws apigateway get-integration \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD}
{
"httpMethod": "POST",
"integrationResponses": {
"200": {
"responseTemplates": {
"application/json": null
},
"statusCode": "200"
}
},
"cacheKeyParameters": [],
"type": "AWS",
"uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName/invocations",
"cacheNamespace": "xxxxxx"
}
5.4. lambda関数の実行権限付与
GETメソッドのリザルトコード200でのIntegration Responseに、Lambda関数を実行する権限を付与します。
Statement IDを乱数32桁で生成します。
(もっとスマートな方法があれば教えてください...)
LAMBDA_STAT_ID=$(od -vAn -N16 -tx < /dev/urandom |sed 's/ //g')
LAMBDA_ACTION='lambda:InvokeFunction'
AWS_PRINCIPAL='apigateway.amazonaws.com'
RESOURCE_PATH="${APIGW_RESOURCE_PATH}"
SOURCE_ARN="arn:aws:execute-api:${AWS_REGION}:${AWS_ID}:${APIGW_API_ID}/*/${HTTP_METHOD}${RESOURCE_PATH}" \
&& echo ${SOURCE_ARN}
cat << ETX
LAMBDA_FUNC_NAME: ${LAMBDA_FUNC_NAME}
LAMBDA_STAT_ID: ${LAMBDA_STAT_ID}
LAMBDA_ACTION: ${LAMBDA_ACTION}
AWS_PRINCIPAL: ${AWS_PRINCIPAL}
SOURCE_ARN: ${SOURCE_ARN}
ETX
aws lambda add-permission \
--function-name ${LAMBDA_FUNC_NAME} \
--statement-id ${LAMBDA_STAT_ID} \
--action ${LAMBDA_ACTION} \
--principal ${AWS_PRINCIPAL} \
--source-arn ${SOURCE_ARN}
{
"Statement": "{\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:ap-northeast-1::xxxxxxxxxx/*/GET/mydemoresource\"}},\"Action\":[\"lambda:InvokeFunction\"],\"Resource\":\"arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Sid\":\"da0d644756f42dd8ccf455176c560b8c\"}"
}
aws lambda get-policy \
--function-name ${LAMBDA_FUNC_NAME} |\
sed 's/\\//g' | sed 's/\"{/{/' | sed 's/\"$//' |\
jq --arg sid ${LAMBDA_STAT_ID} '.Policy.Statement[]|select(.Sid == $sid)'
{
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:execute-api:ap-northeast-1::xxxxxxxxxx/*/GET/mydemoresource"
}
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Sid": "da0d644756f42dd8ccf455176c560b8c"
}
5.5. Method Responseの作成
aws apigateway get-method-response \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--status-code ${HTTP_STATUS_CODE}
A client error (NotFoundException) occurred when calling the GetIntegrationResponse operation: Invalid Response status code specified
aws apigateway put-method-response \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--status-code ${HTTP_STATUS_CODE} \
--response-models '{"application/json": "Empty"}'
{
"responseModels": {
"application/json": "Empty"
},
"statusCode": "200"
}
aws apigateway get-method-response \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--status-code ${HTTP_STATUS_CODE}
{
"responseModels": {
"application/json": "Empty"
},
"statusCode": "200"
}
aws apigateway get-method \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD}
{
"apiKeyRequired": false,
"httpMethod": "GET",
"methodIntegration": {
"integrationResponses": {
"200": {
"responseTemplates": {
"application/json": null
},
"statusCode": "200"
}
},
"cacheKeyParameters": [],
"uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName/invocations",
"httpMethod": "POST",
"cacheNamespace": "xxxxxx",
"type": "AWS"
},
"methodResponses": {
"200": {
"responseModels": {
"application/json": "Empty"
},
"statusCode": "200"
}
},
"authorizationType": "NONE"
}
5.6. GETメソッドのテスト
PATH_WITH_QUERY_STRING=''
cat << ETX
APIGW_API_ID: ${APIGW_API_ID}
APIGW_RESOURCE_ID: ${APIGW_RESOURCE_ID}
HTTP_METHOD: ${HTTP_METHOD}
PATH_WITH_QUERY_STRING: "${PATH_WITH_QUERY_STRING}"
ETX
aws apigateway test-invoke-method \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--path-with-query-string "${PATH_WITH_QUERY_STRING}"
{
"status": 200,
"body": "{\"Hello\":\"No-Name\"}",
"log": "Execution log for request test-request\nSun Nov 22 05:19:22 UTC 2015 : Starting execution for request: test-invoke-request\nSun Nov 22 05:19:22 UTC 2015 : API Key: test-invoke-api-key\nSun Nov 22 05:19:22 UTC 2015 : Method request path: {}\nSun Nov 22 05:19:22 UTC 2015 : Method request query string: {}\nSun Nov 22 05:19:22 UTC 2015 : Method request headers: {}\nSun Nov 22 05:19:22 UTC 2015 : Method request body before transformations: null\nSun Nov 22 05:19:22 UTC 2015 : Endpoint request URI: https://lambda.ap-northeast-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName/invocations\nSun Nov 22 05:19:22 UTC 2015 : Endpoint request headers: {Authorization=************************************************************************************************************************************************************************************************************************************619f32, X-Amz-Date=20151122T051922Z, X-Amz-Source-Arn=arn:aws:execute-api:ap-northeast-1:XXXXXXXXXXXX:xxxxxxxxxx/null/GET/mydemoresource, Accept=application/json, User-Agent=AmazonAPIGateway_xxxxxxxxxx, Host=lambda.ap-northeast-1.amazonaws.com}\nSun Nov 22 05:19:22 UTC 2015 : Endpoint request body after transformations: \nSun Nov 22 05:19:22 UTC 2015 : Endpoint response body before transformations: {\"Hello\":\"No-Name\"}\nSun Nov 22 05:19:22 UTC 2015 : Endpoint response headers: {x-amzn-Remapped-Content-Length=0, x-amzn-RequestId=96d204f3-90d8-11e5-8336-4109c0d3fc68, Connection=keep-alive, Content-Length=19, Date=Sun, 22 Nov 2015 05:19:21 GMT, Content-Type=application/json}\nSun Nov 22 05:19:22 UTC 2015 : Method response body after transformations: {\"Hello\":\"No-Name\"}\nSun Nov 22 05:19:22 UTC 2015 : Method response headers: {Content-Type=application/json}\nSun Nov 22 05:19:22 UTC 2015 : Successfully completed execution\n",
"latency": 79,
"headers": {
"Content-Type": "application/json"
}
}
6. POSTメソッドの作成
6.1. methodの作成
HTTP_METHOD='POST'
AUTH_TYPE='NONE'
cat << ETX
APIGW_API_ID: ${APIGW_API_ID}
APIGW_RESOURCE_ID: ${APIGW_RESOURCE_ID}
HTTP_METHOD: ${HTTP_METHOD}
AUTH_TYPE: ${AUTH_TYPE}
ETX
aws apigateway put-method \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--authorization-type ${AUTH_TYPE}
{
"apiKeyRequired": false,
"httpMethod": "POST",
"authorizationType": "NONE"
}
aws apigateway get-method \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD}
{
"apiKeyRequired": false,
"httpMethod": "POST",
"authorizationType": "NONE"
}
6.2. integrationの作成
aws apigateway get-integration \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD}
A client error (NotFoundException) occurred when calling the GetIntegration operation: No integration defined for method
cat << ETX
APIGW_API_ID: ${APIGW_API_ID}
APIGW_RESOURCE_ID: ${APIGW_RESOURCE_ID}
HTTP_METHOD: ${HTTP_METHOD}
APIGW_INTEG_TYPE: ${APIGW_INTEG_TYPE}
APIGW_INTEG_METHOD: ${APIGW_INTEG_METHOD}
APIGW_INTEG_URI: ${APIGW_INTEG_URI}
ETX
aws apigateway put-integration \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--type ${APIGW_INTEG_TYPE} \
--integration-http-method ${APIGW_INTEG_METHOD} \
--uri ${APIGW_INTEG_URI}
{
"httpMethod": "POST",
"type": "AWS",
"uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName/invocations",
"cacheNamespace": "xxxxxx"
}
aws apigateway get-integration \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD}
{
"httpMethod": "POST",
"cacheKeyParameters": [],
"type": "AWS",
"uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName/invocations",
"cacheNamespace": "xxxxxx"
}
6.3. Integration Responseの作成
POSTメソッドのリザルトコード200でのIntegration Responseが存在作成しないことを確認します。
HTTP_STATUS_CODE='200'
aws apigateway get-integration-response \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--status-code ${HTTP_STATUS_CODE}
A client error (NotFoundException) occurred when calling the GetMethodResponse operation: Invalid Response status code specified
POSTメソッドのリザルトコード200でのIntegration Responseを作成します。
cat << ETX
APIGW_API_ID: ${APIGW_API_ID}
APIGW_RESOURCE_ID: ${APIGW_RESOURCE_ID}
HTTP_METHOD: ${HTTP_METHOD}
HTTP_STATUS_CODE: ${HTTP_STATUS_CODE}
ETX
aws apigateway put-integration-response \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--status-code ${HTTP_STATUS_CODE} \
--response-templates '{"application/json":""}'
{
"statusCode": "200",
"responseTemplates": {
"application/json": null
}
}
POSTメソッドのリザルトコード200でのIntegration Responseを確認します。
aws apigateway get-integration-response \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--status-code ${HTTP_STATUS_CODE}
{
"statusCode": "200",
"responseTemplates": {
"application/json": null
}
}
aws apigateway get-integration \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD}
{
"httpMethod": "POST",
"integrationResponses": {
"200": {
"responseTemplates": {
"application/json": null
},
"statusCode": "200"
}
},
"cacheKeyParameters": [],
"type": "AWS",
"uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName/invocations",
"cacheNamespace": "xxxxxx"
}
6.4. Lambda関数の実行権限付与
POSTメソッドのリザルトコード200でのIntegration Responseに、Lambda関数を実行する権限を付与します。
Statement IDを乱数32桁で生成します。
LAMBDA_STAT_ID=$(od -vAn -N16 -tx < /dev/urandom |sed 's/ //g')
LAMBDA_ACTION='lambda:InvokeFunction'
AWS_PRINCIPAL='apigateway.amazonaws.com'
RESOURCE_PATH="${APIGW_RESOURCE_PATH}"
SOURCE_ARN="arn:aws:execute-api:${AWS_REGION}:${AWS_ID}:${APIGW_API_ID}/*/${HTTP_METHOD}${RESOURCE_PATH}" \
&& echo ${SOURCE_ARN}
cat << ETX
LAMBDA_FUNC_NAME: ${LAMBDA_FUNC_NAME}
LAMBDA_STAT_ID: ${LAMBDA_STAT_ID}
LAMBDA_ACTION: ${LAMBDA_ACTION}
AWS_PRINCIPAL: ${AWS_PRINCIPAL}
SOURCE_ARN: ${SOURCE_ARN}
ETX
aws lambda add-permission \
--function-name ${LAMBDA_FUNC_NAME} \
--statement-id ${LAMBDA_STAT_ID} \
--action ${LAMBDA_ACTION} \
--principal ${AWS_PRINCIPAL} \
--source-arn ${SOURCE_ARN}
{
"Statement": "{\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:execute-api:ap-northeast-1::1afbnp37t7/*/POST/mydemoresource\"}},\"Action\":[\"lambda:InvokeFunction\"],\"Resource\":\"arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"apigateway.amazonaws.com\"},\"Sid\":\"2555f27b3ed0ee871d38925d7e052e96\"}"
}
aws lambda get-policy \
--function-name ${LAMBDA_FUNC_NAME} |\
sed 's/\\//g' | sed 's/\"{/{/' | sed 's/\"$//' |\
jq --arg sid ${LAMBDA_STAT_ID} '.Policy.Statement[]|select(.Sid == $sid)'
{
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:execute-api:ap-northeast-1::1afbnp37t7/*/POST/mydemoresource"
}
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Sid": "2555f27b3ed0ee871d38925d7e052e96"
}
6.5. Method Responseの作成
aws apigateway get-method-response \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--status-code ${HTTP_STATUS_CODE}
A client error (NotFoundException) occurred when calling the GetIntegrationResponse operation: Invalid Response status code specified
aws apigateway put-method-response \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--status-code ${HTTP_STATUS_CODE} \
--response-models '{"application/json": "Empty"}'
{
"responseModels": {
"application/json": "Empty"
},
"statusCode": "200"
}
aws apigateway get-method-response \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--status-code ${HTTP_STATUS_CODE}
{
"responseModels": {
"application/json": "Empty"
},
"statusCode": "200"
}
aws apigateway get-method \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD}
{
"apiKeyRequired": false,
"httpMethod": "POST",
"methodIntegration": {
"integrationResponses": {
"200": {
"responseTemplates": {
"application/json": null
},
"statusCode": "200"
}
},
"cacheKeyParameters": [],
"uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:GetHelloWithName/invocations",
"httpMethod": "POST",
"cacheNamespace": "xxxxxx",
"type": "AWS"
},
"methodResponses": {
"200": {
"responseModels": {
"application/json": "Empty"
},
"statusCode": "200"
}
},
"authorizationType": "NONE"
}
6.6. POSTメソッドのテスト (bodyなし)
cat << ETX
APIGW_API_ID: ${APIGW_API_ID}
APIGW_RESOURCE_ID: ${APIGW_RESOURCE_ID}
HTTP_METHOD: ${HTTP_METHOD}
ETX
aws apigateway test-invoke-method \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--path-with-query-string '' \
--query 'body' |\
sed 's/\\//g' | sed 's/^\"//g' | sed 's/\"$//' |\
jq .
{
"Hello": "No-Name"
}
6.6. POSTメソッドのテスト (bodyあり)
cat << ETX
APIGW_API_ID: ${APIGW_API_ID}
APIGW_RESOURCE_ID: ${APIGW_RESOURCE_ID}
HTTP_METHOD: ${HTTP_METHOD}
ETX
aws apigateway test-invoke-method \
--rest-api-id ${APIGW_API_ID} \
--resource-id ${APIGW_RESOURCE_ID} \
--http-method ${HTTP_METHOD} \
--path-with-query-string '' \
--body '{"name": "User"}' \
--query 'body' |\
sed 's/\\//g' | sed 's/^\"//g' | sed 's/\"$//' |\
jq .
{
"Hello": "User"
}
7. APIのデプロイ
7.1. APIのデプロイ
aws apigateway get-deployments \
--rest-api-id ${APIGW_API_ID}
{
"items": []
}
APIGW_STAGE_NAME='test'
APIGW_STAGE_DESC='This is a test.'
APIGW_DEPLOY_DESC='Calling Lambda functions walkthrough.'
cat << ETX
APIGW_API_ID: ${APIGW_API_ID}
APIGW_STAGE_NAME: ${APIGW_STAGE_NAME}
APIGW_STAGE_DESC: "${APIGW_STAGE_DESC}"
APIGW_DEPLOY_DESC: "${APIGW_DEPLOY_DESC}"
ETX
aws apigateway create-deployment \
--rest-api-id ${APIGW_API_ID} \
--stage-name ${APIGW_STAGE_NAME} \
--stage-description "${APIGW_STAGE_DESC}" \
--description "${APIGW_DEPLOY_DESC}"
{
"description": "Calling Lambda functions walkthrough.",
"id": "n5ston",
"createdDate": 1448115971
}
aws apigateway get-deployments \
--rest-api-id ${APIGW_API_ID}
{
"items": [
{
"createdDate": 1448115971,
"id": "xxxxxx",
"description": "Calling Lambda functions walkthrough."
}
]
}
7.2. API IDの取得
APIGW_DEPLOY_ID=$( \
aws apigateway get-deployments \
--rest-api-id ${APIGW_API_ID} \
--query "items[?description == \`${APIGW_DEPLOY_DESC}\`].id" \
--output text \
) \
&& echo ${APIGW_DEPLOY_ID}
xxxxxx
7.3. APIの情報の取得
aws apigateway get-deployment \
--rest-api-id ${APIGW_API_ID} \
--deployment-id ${APIGW_DEPLOY_ID}
{
"description": "Calling Lambda functions walkthrough.",
"id": "xxxxxx",
"createdDate": 1448115971
}
7.4. APIのステージ名の取得
aws apigateway get-stages \
--rest-api-id ${APIGW_API_ID}
{
"item": [
{
"description": "This is a test.",
"stageName": "test",
"cacheClusterEnabled": false,
"cacheClusterStatus": "NOT_AVAILABLE",
"deploymentId": "xxxxxx",
"lastUpdatedDate": 1448115971,
"createdDate": 1448115971,
"methodSettings": {}
}
]
}
APIGW_STAGE_NAME=$( \
aws apigateway get-stages \
--rest-api-id ${APIGW_API_ID} \
--query "item[?description == \`${APIGW_STAGE_DESC}\`].stageName" \
--output text \
) \
&& echo ${APIGW_STAGE_NAME}
{
"item": [
{
"description": "This is a test.",
"stageName": "test",
"cacheClusterEnabled": false,
"cacheClusterStatus": "NOT_AVAILABLE",
"deploymentId": "xxxxxx",
"lastUpdatedDate": 1448115971,
"createdDate": 1448115971,
"methodSettings": {}
}
]
}
aws apigateway get-stage \
--rest-api-id ${APIGW_API_ID} \
--stage-name ${APIGW_STAGE_NAME}
{
"stageName": "test",
"description": "This is a test.",
"cacheClusterEnabled": false,
"cacheClusterStatus": "NOT_AVAILABLE",
"deploymentId": "xxxxxx",
"lastUpdatedDate": 1448115971,
"createdDate": 1448115971,
"methodSettings": {}
}
8 .APIのテスト
8.1. GETメソッドのテスト (ブラウザ)
APIGW_URI="https://${APIGW_API_ID}.execute-api.${AWS_REGION}.amazonaws.com/${APIGW_STAGE_NAME}${APIGW_RESOURCE_PATH}" \
&& echo ${APIGW_URI}
表示されたURLをブラウザで開いて、以下のJSONファイルが表示されればOKです。
{"Hello":"No-Name"}
8.2. POSTメソッドのテスト (curlコマンド)
curl \
-H "Content-Type: application/json" \
-X POST -d "{\"name\": \"User\"}" \
${APIGW_URI}
{"Hello":"User"}