ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

Serverless Frameworkのaws-nodejs-typescriptでCORSが設定されたAPIを用意する

スポンサードリンク

ドキュメント読んだら色々わかるんですが、 aws-nodejs-typescript のテンプレートでどうやって設定すればよいのかわからなかったのでメモ。

APIのfunctions設定で、CORSの設定をonにしたい関数だけ下記設定をします。

aws-nodejs-typescript のテンプレートでは、 src/functions/ 以下にAPIごとにディレクトリが作成できるので、 src/functions/hello/index.ts で関数の設定が編集できます。

import schema from './schema';
import { handlerPath } from '@libs/handler-resolver';

export default {
  handler: `${handlerPath(__dirname)}/handler.main`,
  events: [
    {
      http: {
        method: 'post',
        path: 'hello',
        request: {
          schemas: {
            'application/json': schema,
          },
        cors: true
        },
      },
    },
  ],
};

cors: true にしたらおk

次は、関数自体をいじります。

import type { ValidatedEventAPIGatewayProxyEvent } from '@libs/api-gateway';
import { formatJSONResponse } from '@libs/api-gateway';
import { middyfy } from '@libs/lambda';

import schema from './schema';

const hello: ValidatedEventAPIGatewayProxyEvent<typeof schema> = async (event) => {
  return formatJSONResponse({
    message: `Hello ${event.body.name}, welcome to the exciting Serverless world!`,
    event,
  });
};

export const main = middyfy(hello);

返却するレスポンスを作ってくれる formatJSONResponse をいじります。こいつの実装に飛んでみると

import type { APIGatewayProxyEvent, APIGatewayProxyResult, Handler } from "aws-lambda"
import type { FromSchema } from "json-schema-to-ts";

type ValidatedAPIGatewayProxyEvent<S> = Omit<APIGatewayProxyEvent, 'body'> & { body: FromSchema<S> }
export type ValidatedEventAPIGatewayProxyEvent<S> = Handler<ValidatedAPIGatewayProxyEvent<S>, APIGatewayProxyResult>

export const formatJSONResponse = (response: Record<string, unknown>) => {
  return {
    statusCode: 200,
    body: JSON.stringify(response)
  }
}

こうなっておりました。Lambda統合プロキシが設定されているので、Lambda側で返してあげるように修正します。

import type { APIGatewayProxyEvent, APIGatewayProxyResult, Handler } from "aws-lambda"
import type { FromSchema } from "json-schema-to-ts";

type ValidatedAPIGatewayProxyEvent<S> = Omit<APIGatewayProxyEvent, 'body'> & { body: FromSchema<S> }
export type ValidatedEventAPIGatewayProxyEvent<S> = Handler<ValidatedAPIGatewayProxyEvent<S>, APIGatewayProxyResult>

export const formatJSONResponse = (response: Record<string, unknown>) => {
  return {
    statusCode: 200,
    body: JSON.stringify(response),
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Credentials': true,
    },
  }
}

こんな感じ(引数でheadersを渡せるようにしても良いと思う)

これで設定はおkです。実際運用する場合は、 Access-Control-Allow-Origin をちゃんと設定するとかしないと行けないと思います。