Let's connect API Gateway to the one of Last time. This is the goal

API Gateway
The GUI is pretty intuitive so you can use it without using your head.
/ projectGET`` PUT POST`` DELETE on the resourceproject for each method
It's easy to forget that you have to press "Deploy" to deploy the API changes. This should work for the time being

A little troublesome when using API keys
dev_1 here)
It may take a few minutes for the changes to take effect, but now you should be able to call with the API key.
curl -s -X GET -H "x-api-key: your-api-key-here" https://<project-id>.execute-api.us-east-2.amazonaws.com/dev_1/projects | jq
--Check Lambda integrated proxy
--Associate the method (GET/PUT/POST/DELETE) with the lambda function [^ 1]
[^ 1]: In a case like this, actually using ANY as a method eliminates the need to associate each method with a lambda function.
By doing so, various parameters included in the HTTP request are passed to Lambda as they are.

For example, you can tell on the Lambda side whether the HTTP method is POST or GET.
When I read it like this
curl -s -X GET -H "x-api-key:your-api-key-here" https://<api-id>.execute-api.us-east-2.amazonaws.com/dev_1/projects?say=ciao -d '{"say": "hello"}'
The parameter passed to Lambda as event looks like this
event
{
  "resource": "/projects",
  "path": "/projects",
  "httpMethod": "GET",
  "headers": {
    "accept": "*/*",
    "content-type": "application/x-www-form-urlencoded",
    "Host": "<project-id>.execute-api.us-east-2.amazonaws.com",
    "User-Agent": "curl/7.64.1",
    "X-Amzn-Trace-Id": "Root=1-5fd44390-5f78ee5a289e7e3a0355bec2",
    "x-api-key": "your-api-key",
    "X-Forwarded-For": "***.**.**.**",
    "X-Forwarded-Port": "443",
    "X-Forwarded-Proto": "https"
  },
  "multiValueHeaders": {
    "accept": [
      "*/*"
    ],
    "content-type": [
      "application/x-www-form-urlencoded"
    ],
    "Host": [
      "<project-id>.execute-api.us-east-2.amazonaws.com"
    ],
    "User-Agent": [
      "curl/7.64.1"
    ],
    "X-Amzn-Trace-Id": [
      "Root=1-5fd44390-5f78ee5a289e7e3a0355bec2"
    ],
    "x-api-key": [
      "<your-api-key>"
    ],
    "X-Forwarded-For": [
      "***.**.**.**"
    ],
    "X-Forwarded-Port": [
      "443"
    ],
    "X-Forwarded-Proto": [
      "https"
    ]
  },
  "queryStringParameters": {
    "say": "ciao"
  },
  "multiValueQueryStringParameters": {
    "say": [
      "ciao"
    ]
  },
  "pathParameters": null,
  "stageVariables": null,
  "requestContext": {
    "resourceId": "<resource-id>",
    "resourcePath": "/projects",
    "httpMethod": "GET",
    "extendedRequestId": "Xa9-iG9kCYcFU8Q=",
    "requestTime": "12/Dec/2020:04:14:08 +0000",
    "path": "/dev_1/projects",
    "accountId": "<account-id>",
    "protocol": "HTTP/1.1",
    "stage": "dev_1",
    "domainPrefix": "<project-id>",
    "requestTimeEpoch": 1607746448145,
    "requestId": "06499aaf-9168-49d7-b4da-2a0a3ad5d4ad",
    "identity": {
      "cognitoIdentityPoolId": null,
      "cognitoIdentityId": null,
      "apiKey": "<your-api-key>",
      "principalOrgId": null,
      "cognitoAuthenticationType": null,
      "userArn": null,
      "apiKeyId": "<api-key-id>",
      "userAgent": "curl/7.64.1",
      "accountId": null,
      "caller": null,
      "sourceIp": "***.**.**.**",
      "accessKey": null,
      "cognitoAuthenticationProvider": null,
      "user": null
    }, 
    "domainName": "<project-id>.execute-api.us-east-2.amazonaws.com",
    "apiId": "<api-id>"
  },
  "body": "{\"say\": \"hello\"}",
  "isBase64Encoded": false
}
The data body from the client can be accessed byevent ['body'], so change the CRUD code on the Lambda side a little from previous to make it look like this
require 'json'
require 'aws-sdk-dynamodb'
def add_project(table, body)
  table.put_item({ item: body })  
end
def delete_project(table, body)
  params = { table_name: table, key: { 'project-id': body['project-id'] } }
  begin
    table.delete_item(params)
  rescue Aws::DynamoDB::Errors::ServiceError => error
    puts error.message
  end
end
def update_project(table, body)
  params = {
    table_name: table,
    key: { 'project-id': body['project-id'] },
    attribute_updates: {
      name: {
        value: body['name'],
        action: "PUT"
      }
    }
  }
  table.update_item(params)  
end
def list_project(table)
  scan_output = table.scan({ limit: 50, select: "ALL_ATTRIBUTES" })
  scan_output.items.each do |item|
    keys = item.keys
    keys.each do |k|
      puts "#{k}: #{item[k]}"
    end
  end
end
def lambda_handler(event:, context:)
  
  http_method = event['httpMethod'] #Add this
  body = JSON.parse(event['body'])  #Add this
  
  dynamodb = Aws::DynamoDB::Resource.new(region: 'us-east-2')
  table = dynamodb.table('project')
  
  case http_method
    when 'GET'    then list_project(table)
    when 'PUT'    then update_project(table, body)
    when 'POST'   then add_project(table, body)
    when 'DELETE' then delete_project(table, body)
    else 0
  end
  { statusCode: 200, body: JSON.generate(list_project(table)) }
end
For example, if you make a request like this, you will see the HTTP method and perform CRUD processing. By the way, jq is recommended because it is easy to see.
curl -s -X POST -d '{ "project-id":101, "name":"Cycling", "is-default":false }' -H "x-api-key: <your-api-key-here>" https://<project-id>.execute-api.us-east-2.amazonaws.com/dev_1/projects | jq
Um, it worked
Recommended Posts