はじめに
AWSのDeveloper試験を受験しようと手を動かしながら勉強中だが、以下リンク先でNodeJS 16.xでないと動かないプログラムがサンプルとして置かれている。
https://aws.amazon.com/jp/getting-started/hands-on/build-serverless-web-app-lambda-apigateway-s3-dynamodb-cognito/module-3/
しかし、ap-northeast-1で選択できるNodeJSはすでに18.x以降のものしかなかった。
とりあえずもろもろサンプルから置き換えて実装し、ひとまず動くところまで確認できたので残しておく。
さっそくブツを
// 書き換えポイント このimport群
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const randomBytes = require('crypto').randomBytes;
import { PutCommand, DynamoDBDocument } from '@aws-sdk/lib-dynamodb';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
const ddb = DynamoDBDocument.from(new DynamoDBClient({ region: "ap-northeast-1" }));
const fleet = [
{
Name: 'Angel',
Color: 'White',
Gender: 'Female',
},
{
Name: 'Gil',
Color: 'White',
Gender: 'Male',
},
{
Name: 'Rocinante',
Color: 'Yellow',
Gender: 'Female',
},
];
// 書き換えポイント このhandlerの定義の仕方
export const handler = (event, context, callback) => {
if (!event.requestContext.authorizer) {
errorResponse('Authorization not configured', context.awsRequestId, callback);
return;
}
const rideId = toUrlString(randomBytes(16));
console.log('Received event (', rideId, '): ', event);
// Because we're using a Cognito User Pools authorizer, all of the claims
// included in the authentication token are provided in the request context.
// This includes the username as well as other attributes.
const username = event.requestContext.authorizer.claims['cognito:username'];
// The body field of the event in a proxy integration is a raw string.
// In order to extract meaningful values, we need to first parse this string
// into an object. A more robust implementation might inspect the Content-Type
// header first and use a different parsing strategy based on that value.
const requestBody = JSON.parse(event.body);
const pickupLocation = requestBody.PickupLocation;
const unicorn = findUnicorn(pickupLocation);
recordRide(rideId, username, unicorn).then(_ => {
callback(null, {
statusCode: 201,
body: JSON.stringify({
RideId: rideId,
Unicorn: unicorn,
Eta: '30 seconds',
Rider: username,
}),
headers: {
'Access-Control-Allow-Origin': '*',
},
});
}).catch((err) => {
console.error(err);
// If there is an error during processing, catch it and return
// from the Lambda function successfully. Specify a 500 HTTP status
// code and provide an error message in the body. This will provide a
// more meaningful error response to the end client.
errorResponse(err.message, context.awsRequestId, callback)
});;
};
// This is where you would implement logic to find the optimal unicorn for
// this ride (possibly invoking another Lambda function as a microservice.)
// For simplicity, we'll just pick a unicorn at random.
function findUnicorn(pickupLocation) {
console.log('Finding unicorn for ', pickupLocation.Latitude, ', ', pickupLocation.Longitude);
return fleet[Math.floor(Math.random() * fleet.length)];
}
// 書き換えポイント このFunction
async function recordRide(rideId, username, unicorn) {
const command = new PutCommand({
TableName: 'Rides',
Item: {
RideId: rideId,
User: username,
Unicorn: unicorn,
RequestTime: new Date().toISOString(),
},
});
const response = await ddb.send(command)
return response;
}
function toUrlString(buffer) {
return buffer.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
function errorResponse(errorMessage, awsRequestId, callback) {
callback(null, {
statusCode: 500,
body: JSON.stringify({
Error: errorMessage,
Reference: awsRequestId,
}),
headers: {
'Access-Control-Allow-Origin': '*',
},
});
}
終わりに
自分がどう実装したか忘れる自信しかなかったのでQiitaに備忘録として残しておくことを目的としているが、同じように迷った誰かの助けになったらそれはそれで嬉しいです。