1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWSの「サーバーレスのウェブアプリケーションを構築する」の「サーバーレスバックエンドを構築する」をNodeJS 18.x以降で対応する

Posted at

はじめに

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に備忘録として残しておくことを目的としているが、同じように迷った誰かの助けになったらそれはそれで嬉しいです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?