Help us understand the problem. What is going on with this article?

[JAWS-UG CLI] API Gateway: #1 RestAPIの作成

More than 3 years have passed since last update.

前提条件

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. 準備

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}

1. 事前作業

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"}

完了

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