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

[JAWS-UG CLI] API Gateway: #4 RestAPIの作成(LambdaMicroservice)

More than 3 years have passed since last update.
  1. API Gateway

前提条件

API Gatewayへの権限

API Gatewayに対してフル権限があること。

AWS CLI

以下のバージョンで動作確認済

  • AWS CLI 1.11.8
コマンド
aws --version

結果(例):

  aws-cli/1.11.34 Python/2.7.10 Darwin/15.6.0 botocore/1.4.91

バージョンが古い場合は最新版に更新しましょう。

コマンド
sudo -H pip install -U awscli

0. 準備

0.1. リージョンの決定

変数の設定
export AWS_DEFAULT_REGION='ap-northeast-1'

0.2. プロファイルの確認

プロファイルが想定のものになっていることを確認します。

変数の確認
aws configure list

結果(例):

        Name                    Value             Type    Location
        ----                    -----             ----    --------
     profile       lambdaFull-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.3. Lambda関数のARN取得

変数の設定
LAMBDA_FUNC_NAME='microservice_http_endpoint-20170102'
変数の設定
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='LambdaMicroservice'

同名のREST APIが存在しないことを確認します。

コマンド
aws apigateway get-rest-apis \
        --query "items[?name == \`${APIGW_API_NAME}\`]"

結果(例):

  []

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": "LambdaMicroservice",
    "description": "This is my API for demonstration purposes",
    "createdDate": 1448002904
  }

2.2. APIの確認

コマンド
aws apigateway get-rest-apis \
        --query "items[?name == \`${APIGW_API_NAME}\`]"

結果(例):

  {
    "id": "xxxxxxxxxx",
    "name": "LambdaMicroservice",
    "description": "This is my API for demonstration purposes",
    "createdDate": 1448002904
  }
変数の設定
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": "LambdaMicroservice",
    "description": "This is my API for demonstration purposes",
    "createdDate": 1448002904
  }

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": "ctcxxf",
          "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": "fpdged",
          "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='microservice-http-endpoint-python'
変数の確認
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": "/microservice-http-endpoint-python",
    "pathPart": "microservice-http-endpoint-python",
    "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": "/microservice-http-endpoint-python",
    "pathPart": "microservice-http-endpoint-python",
    "id": "xxxxxx",
    "parentId": "xxxxxxxxxx"
  }

4. Lambda関数の指定

変数の確認
cat << ETX

        AWS_DEFAULT_REGION: ${AWS_DEFAULT_REGION}
        LAMBDA_FUNC_ARN:    ${LAMBDA_FUNC_ARN}

ETX
変数の設定
APIGW_INTEG_URI="arn:aws:apigateway:${AWS_DEFAULT_REGION}:lambda:path/2015-03-31/functions/${LAMBDA_FUNC_ARN}/invocations" \
        && echo ${APIGW_INTEG_URI}

結果(例):

  arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:microservice_http_endpoint-20170102 /invocations

5. ANYメソッドの作成

5.1. methodの作成

変数の設定
HTTP_METHOD='ANY'
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": "ANY",
    "authorizationType": "NONE"
  }
コマンド
aws apigateway get-method \
        --rest-api-id ${APIGW_API_ID} \
        --resource-id ${APIGW_RESOURCE_ID} \
        --http-method ${HTTP_METHOD}

結果(例):

  {
    "apiKeyRequired": false,
    "httpMethod": "ANY",
    "authorizationType": "NONE"
  }

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
変数の設定
APIGW_INTEG_TYPE='AWS_PROXY'
変数の設定
APIGW_INTEG_METHOD='POST'
変数の確認
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",
    "passthroughBehavior": "WHEN_NO_MATCH",
    "cacheKeyParameters": [],
    "type": "AWS_PROXY",
    "uri": "arn:aws:apigateway::lambda:path/2015-03-31/functions/arn:aws:lambda::XXXXXXXXXXXX:function:\ |LAMBDA_FUNC_NAME|\ /invocations",
    "cacheNamespace": "2t9qak"
  }
コマンド
aws apigateway get-integration \
        --rest-api-id ${APIGW_API_ID} \
        --resource-id ${APIGW_RESOURCE_ID} \
        --http-method ${HTTP_METHOD}

結果(例):

  {
    "httpMethod": "POST",
    "passthroughBehavior": "WHEN_NO_MATCH",
    "cacheKeyParameters": [],
    "uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:microservice_http_endpoint-20170102/invocations",
    "cacheNamespace": "88a637",
    "type": "AWS_PROXY"
  }

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} \
        --selection-pattern '.*'

結果(例):

  {
    "selectionPattern": ".*",
    "statusCode": "200"
  }

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}

結果(例):

  {
    "selectionPattern": ".*",
    "statusCode": "200"
  }

GETメソッドのIntegrationにリザルトコード200でのIntegration Responseが
存在することを確認します。

コマンド
aws apigateway get-integration \
        --rest-api-id ${APIGW_API_ID} \
        --resource-id ${APIGW_RESOURCE_ID} \
        --http-method ${HTTP_METHOD}

結果(例):

  {
    "integrationResponses": {
      "200": {
          "selectionPattern": ".*",
          "statusCode": "200"
      }
    },
    "passthroughBehavior": "WHEN_NO_MATCH",
    "cacheKeyParameters": [],
    "uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:microservice_http_endpoint-20161231/invocations",
    "httpMethod": "POST",
    "cacheNamespace": "2t9qak",
    "type": "AWS_PROXY"
  }

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}"
変数の確認
cat << ETX

        AWS_DEFAULT_REGION: ${AWS_DEFAULT_REGION}
        AWS_ID:             ${AWS_ID}
        APIGW_API_ID:       ${APIGW_API_ID}
        HTTP_METHOD:        ${HTTP_METHOD}
        RESOURCE_PATH:      ${RESOURCE_PATH}

ETX
変数の設定
SOURCE_ARN="arn:aws:execute-api:${AWS_DEFAULT_REGION}:${AWS_ID}:${APIGW_API_ID}/*/*${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": "{"Sid":"0230237a9b696476bde295c8bf436f99","Resource":"arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:microservice_http_endpoint-20161231","Effect":"Allow","Principal":{"Service":"apigateway.amazonaws.com"},"Action":["lambda:InvokeFunction"],"Condition":{"ArnLike":{"AWS:SourceArn":"arn:aws:execute-api:ap-northeast-1:XXXXXXXXXXXX:s2ff0lq6l9/*/*/microservice-http-endpoint-python"}}}"
  }
コマンド
aws lambda get-policy \
        --function-name ${LAMBDA_FUNC_NAME} \
      | sed 's/\\//g' | sed 's/\"{/{/' | sed 's/\"$//' \
      | jp.py "Policy.Statement[?Sid == \`${LAMBDA_STAT_ID}\`]"

結果(例)

  [
    {
      "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:microservice_http_endpoint-20170102",
      "Effect": "Allow",
      "Sid": "0230237a9b696476bde295c8bf436f99",
      "Action": "lambda:InvokeFunction",
      "Condition": {
          "ArnLike": {
              "AWS:SourceArn": "arn:aws:execute-api:ap-northeast-1:XXXXXXXXXXXX:xxxxxxxxxx/*/*/microservice-http-endpoint-python"
          }
      },
      "Principal": {
          "Service": "apigateway.amazonaws.com"
      }
    }
  ]

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}

結果:

  An error occurred (NotFoundException) when calling the GetMethodResponse operation: Invalid Response status code specified
変数の確認
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-method-response \
        --rest-api-id ${APIGW_API_ID} \
        --resource-id ${APIGW_RESOURCE_ID} \
        --http-method ${HTTP_METHOD} \
        --status-code ${HTTP_STATUS_CODE} \
        --response-models '{}'

結果(例)

  {
    "responseModels": {},
    "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": {},
    "statusCode": "200"
  }
コマンド
aws apigateway get-method \
        --rest-api-id ${APIGW_API_ID} \
        --resource-id ${APIGW_RESOURCE_ID} \
        --http-method ${HTTP_METHOD}

結果(例):

  {
    "apiKeyRequired": false,
    "httpMethod": "ANY",
    "methodIntegration": {
      "integrationResponses": {
          "200": {
              "selectionPattern": ".*",
              "statusCode": "200"
          }
      },
      "passthroughBehavior": "WHEN_NO_MATCH",
      "cacheKeyParameters": [],
      "uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:microservice-http-endpoint-python/invocations",
      "httpMethod": "POST",
      "cacheNamespace": "xxxxxx",
      "type": "AWS_PROXY"
    },
    "methodResponses": {
      "200": {
          "responseModels": {},
          "statusCode": "200"
      }
    },
    "authorizationType": "NONE"
  }

5.6. メソッドのテスト

(省略)

6. APIのデプロイ

6.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 MicroserviceEndpoint.'
変数の確認
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 MicroserviceEndpoint.",
    "id": "aody9s",
    "createdDate": 1483327540
  }
コマンド
aws apigateway get-deployments \
        --rest-api-id ${APIGW_API_ID}

結果(例):

  {
    "items": [
      {
          "createdDate": 1483327540,
          "id": "aody9s",
          "description": "Calling Lambda functions MicroserviceEndpoint."
      }
    ]
  }

6.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

6.3. APIの情報の取得

コマンド
aws apigateway get-deployment \
        --rest-api-id ${APIGW_API_ID} \
        --deployment-id ${APIGW_DEPLOY_ID}

結果(例):

  {
    "description": "Calling Lambda functions MicroserviceEndpoint.",
    "id": "aody9s",
    "createdDate": 1483327540
  }

6.4. APIのステージ名の取得

コマンド
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}

結果(例):

  test
コマンド
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": "aody9s",
    "lastUpdatedDate": 1483327540,
    "createdDate": 1483327540,
    "methodSettings": {}
  }

7 .APIのテスト

GETメソッドのテスト

変数の設定
PATH_WITH_QUERY_STRING='TableName=microservice-http'
変数の確認
cat << ETX

        APIGW_API_ID:        ${APIGW_API_ID}
        AWS_DEFAULT_REGION:  ${AWS_DEFAULT_REGION}
        APIGW_STAGE_NAME:    ${APIGW_STAGE_NAME}
        APIGW_RESOURCE_PATH: ${APIGW_RESOURCE_PATH}
        PATH_WITH_QUERY_STRING: ${PATH_WITH_QUERY_STRING}

ETX
変数の設定
APIGW_URI="https://${APIGW_API_ID}.execute-api.${AWS_DEFAULT_REGION}.amazonaws.com/${APIGW_STAGE_NAME}${APIGW_RESOURCE_PATH}?${PATH_WITH_QUERY_STRING}" \
        && echo ${APIGW_URI}

表示されたURLをブラウザで開いて、以下のJSONファイルが表示されればOKで
す。

ブラウザ表示の結果:

  {"Count": 1, "Items": [{"Description": "sample", "Name": "taro"}], "ScannedCount": 1, "ResponseMetadata": {"RetryAttempts": 0, "HTTPStatusCode": 200, "RequestId": "EQ6FPKSBTR75S2LEFQ4JPA6407VV4KQNSO5AEMVJF66Q9ASUAABG", "HTTPHeaders": {"x-amzn-requestid": "EQ6FPKSBTR75S2LEFQ4JPA6407VV4KQNSO5AEMVJF66Q9ASUAABG", "content-length": "89", "server": "Server", "connection": "keep-alive", "x-amz-crc32": "2586798783", "date": "Mon, 02 Jan 2017 03:33:26 GMT", "content-type": "application/x-amz-json-1.0"}}}

完了

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