AWSメモ > AWS API Gateway&LambdaをSwaggerで定義する †TODO: 書きかけ - 動作未確認
テーブル定義 †aws dynamodb create-table \ --profile developper \ --table-name Books \ --attribute-definitions \ AttributeName=id,AttributeType=S \ AttributeName=isbn,AttributeType=S \ AttributeName=title,AttributeType=S \ --key-schema AttributeName=id,KeyType=HASH AttributeName=isbn,KeyType=RANGE \ --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 \ --global-secondary-indexes IndexName=title-index, KeySchema=[{AttributeName=title,KeyType=RANGE}],Projection={ProjectionType=KEYS_ONLY}, ProvisionedThroughput={ReadCapacityUnits=1,WriteCapacityUnits=1} Lambda関数作成 †'use strict'; var crypto = require('crypto'); var AWS = require('aws-sdk'); var documentClient = new AWS.DynamoDB.DocumentClient(); const tableName = "Book"; const createResponse = (callback, statusCode, body) => { var res = { "statusCode": statusCode, "body": JSON.stringify(body) } callback(null, res); } exports.handler = (event, context, callback) => { var req = event.body; if (typeof(req) === "string") { req = JSON.parse(req); } var id = false; if (event.pathParameters){ id = event.pathParameters.id || false; } switch(event.httpMethod){ case "GET": if(id) { var params = { TableName : tableName, KeyConditionExpression: '#id = :id', ExpressionAttributeNames:{ '#id': 'id'}, ExpressionAttributeValues:{':id': id } }; documentClient.query(params, function(err, data) { if (err) { createResponse(callback, 500, { "msg": "Get Error!", "err": err, "params" : params }); } else { var result = data; if (data.Items) { data = data.Items[0] || {}; var childCount = data.children ? data.children.length : 0; result = { "data" : data , "message" : data.name + " has " + childCount + " children" } } createResponse(callback, 200, result); } }); return; } else { var params = { TableName : tableName }; documentClient.scan(params, function(err, data) { if (err) { createResponse(callback, 500, { "msg": "List Error!", "err": err}); } else { var result = data.Items || data; createResponse(callback, 200, result); } }); } break; case "POST": var newId = crypto.createHash('md5').update(new Date().getTime().toString()).digest('hex'); var params = { TableName : tableName, Item: { "id" : newId, "isbn" : req.isbn, "title" : req.title, "price" : parseInt(req.price, 10) } }; documentClient.put(params, function(err, data) { if (err) { console.log(err); createResponse(callback, 500, { "msg": "Create Error!", "err": err, "params": params, "req": req}); } else { createResponse(callback, 200, { "msg": "Create OK!", "id": newId }); } }); break; case "PUT": var params = { TableName : tableName, Key: { "id" : id }, ExpressionAttributeNames: { "#isbn" : "isbn", "#title" : "title", "#price" : "price" }, ExpressionAttributeValues: { ":isbn" : req.isbn, ":title" : req.title, ":price" : parseInt(req.price,10) }, UpdateExpression: "SET #isbn = :isbn, #title = :title, #price = :price" }; documentClient.update(params, function(err, data) { if (err) { createResponse(callback, 500, { "msg": "Update Error!", "err": err, "params": params }); } else { createResponse(callback, 200, { "msg": "Update OK!", "params": params}); } }); break; case "DELETE": var params = { TableName : tableName, Key: { "id" : id } }; documentClient.delete(params, function(err, data) { if (err) { createResponse(callback, 500, { "msg": "Delete Error!", "err": err, "params" : params }); } else { createResponse(callback, 200, { "msg": "Delete OK!", "params": params }); } }); break; default: console.log("Error: unsupported HTTP method (" + event.httpMethod + ")"); createResponse(callback, 501, { "msg": "Error: unsupported HTTP method (" + event.httpMethod + ")" } ); } } Lambda 関数と統合されたサンプル API の Swagger 定義 †TODO: とりあえず参考URLの内容をそのまま写経しただけ。ここから上記のLambda用に書き換えていく
{ "swagger": "2.0", "info": { "version": "2017-04-20T04:08:08Z", "title": "LambdaGate" }, "host": "xxxxxxxxxx.execute-api.us-east-1.amazonaws.com", "basePath": "/test", "schemes": [ "https" ], "paths": { "/calc": { "get": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "parameters": [ { "name": "operand2", "in": "query", "required": true, "type": "string" }, { "name": "operator", "in": "query", "required": true, "type": "string" }, { "name": "operand1", "in": "query", "required": true, "type": "string" } ], "responses": { "200": { "description": "200 response", "schema": { "$ref": "#/definitions/Result" }, "headers": { "operand_1": { "type": "string" }, "operand_2": { "type": "string" }, "operator": { "type": "string" } } } }, "x-amazon-apigateway-request-validator": "Validate query string parameters and headers", "x-amazon-apigateway-integration": { "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole", "responses": { "default": { "statusCode": "200", "responseParameters": { "method.response.header.operator": "integration.response.body.op", "method.response.header.operand_2": "integration.response.body.b", "method.response.header.operand_1": "integration.response.body.a" }, "responseTemplates": { "application/json": "#set($res = $input.path('$'))\n{\n \"result\": \"$res.a, $res.b, $res.op => $res.c\",\n \"a\" : \"$res.a\",\n \"b\" : \"$res.b\",\n \"op\" : \"$res.op\",\n \"c\" : \"$res.c\"\n}" } } }, "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations", "passthroughBehavior": "when_no_match", "httpMethod": "POST", "requestTemplates": { "application/json": "{\n \"a\": \"$input.params('operand1')\",\n \"b\": \"$input.params('operand2')\", \n \"op\": \"$input.params('operator')\" \n}" }, "type": "aws" } }, "post": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "parameters": [ { "name": "InvocationType", "in": "header", "required": false, "type": "string" }, { "in": "body", "name": "Input", "required": true, "schema": { "$ref": "#/definitions/Input" } } ], "responses": { "200": { "description": "200 response", "schema": { "$ref": "#/definitions/Result" } } }, "x-amazon-apigateway-request-validator": "Validate body", "x-amazon-apigateway-integration": { "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole", "responses": { "default": { "statusCode": "200", "responseTemplates": { "application/json": "#set($inputRoot = $input.path('$'))\n{\n \"a\" : $inputRoot.a,\n \"b\" : $inputRoot.b,\n \"op\" : $inputRoot.op,\n \"c\" : $inputRoot.c\n}" } } }, "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations", "passthroughBehavior": "when_no_templates", "httpMethod": "POST", "type": "aws" } } }, "/calc/{operand1}/{operand2}/{operator}": { "get": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "parameters": [ { "name": "operand2", "in": "path", "required": true, "type": "string" }, { "name": "operator", "in": "path", "required": true, "type": "string" }, { "name": "operand1", "in": "path", "required": true, "type": "string" } ], "responses": { "200": { "description": "200 response", "schema": { "$ref": "#/definitions/Result" } } }, "x-amazon-apigateway-integration": { "responses": { "default": { "statusCode": "200", "responseTemplates": { "application/json": "#set($inputRoot = $input.path('$'))\n{\n \"input\" : {\n \"a\" : $inputRoot.a,\n \"b\" : $inputRoot.b,\n \"op\" : \"$inputRoot.op\"\n },\n \"output\" : {\n \"c\" : $inputRoot.c\n }\n}" } } }, "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations", "passthroughBehavior": "when_no_templates", "httpMethod": "POST", "requestTemplates": { "application/json": "{\n \"a\": \"$input.params('operand1')\",\n \"b\": \"$input.params('operand2')\",\n \"op\": #if($input.params('operator')=='%2F')\"/\"#{else}\"$input.params('operator')\"#end\n \n}" }, "contentHandling": "CONVERT_TO_TEXT", "type": "aws" } } } }, "definitions": { "Input": { "type": "object", "required": [ "a", "b", "op" ], "properties": { "a": { "type": "number" }, "b": { "type": "number" }, "op": { "type": "string", "description": "binary op of ['+', 'add', '-', 'sub', '*', 'mul', '%2F', 'div']" } }, "title": "Input" }, "Output": { "type": "object", "properties": { "c": { "type": "number" } }, "title": "Output" }, "Result": { "type": "object", "properties": { "input": { "$ref": "#/definitions/Input" }, "output": { "$ref": "#/definitions/Output" } }, "title": "Result" } }, "x-amazon-apigateway-request-validators": { "Validate body": { "validateRequestParameters": false, "validateRequestBody": true }, "Validate query string parameters and headers": { "validateRequestParameters": true, "validateRequestBody": false } } } |