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