Amazon API Gateway REST API のパスパラメーターでスラッシュを含む値を指定できるか試してみた(できなかった)

2023.04.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 Delivery部の若槻です。

今回は、Amazon API Gateway REST API で、パスパラメーターにスラッシュ(/)を含む値を指定できるのか確認する必要があったため、実際に試してみました。

試してみた

実装

AWS CDK で API Gateway REST API を作成し、book_id パスパラメーターを持つ books リソースを追加します。

lib/cdk-sample-app.ts

import { Construct } from 'constructs';
import {
  aws_lambda_nodejs,
  aws_apigateway,
  Stack,
  StackProps,
} from 'aws-cdk-lib';

export class CdkSampleStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    const hogeFunc = new aws_lambda_nodejs.NodejsFunction(this, 'hogeFunc');

    const api = new aws_apigateway.RestApi(this, 'books-api');

    const books = api.root.addResource('books', {});

    const book = books.addResource('{book_id}');

    book.addMethod('GET', new aws_apigateway.LambdaIntegration(hogeFunc));
  }
}

books リソースのGETメソッドのインテグレーションとして、リクエストのイベントのbook_idパスパラメーターの値をパースして、レスポンスボディで返すだけの関数を作成します。簡単のためバリデーションなどは付けていません。

lib/cdk-sample-app.hogeFunc.ts

interface Event {
  pathParameters?: {
    book_id: string;
  };
}

export const handler = async (
  event: Event
): Promise<{ statusCode: number; body?: string }> => {
  console.log(JSON.stringify(event, undefined, 2));

  const path = event.pathParameters;

  const book_id = path?.book_id;

  return {
    statusCode: 200,
    body: JSON.stringify({ book_id }),
  };
};

動作確認

API Gateway のマネジメントコンソールからメソッドテストを利用して動作確認をしてみます。

スラッシュなしの場合

まず、スラッシュの含まれていないbook01という値を指定すると、正常にパスパラメーターの値が取得できました。

Lambda 関数のイベントログでも、ちゃんとパスパラメーターの値が取得できていることが確認できます。

スラッシュありの場合

次に、今回試したかったスラッシュが含まれている/path/to/book01という値を指定してみると、パスパラメーターの値が正常に取得できませんでした。

イベントログを見ると、パスパラメーターの値がnullとなっており、REST API で上手くパース出来ていないようです。

考えられる対処方法

いくつか対処方法はあると思いますが、今回は以下の方法を試してみました。

パスパラメーターに指定する値をエンコードする

REST API へのリクエスト時にスラッシュなどの特殊文字を他の値にエンコードするようにしてみます。

エンコード方法は色々あると思いますが、今回は JavaScript の encodeURIComponent() および decodeURIComponent() 関数を利用してみます。encodeURIComponent は、URI に含まれる特定の文字を UTF-8 文字エンコーディングで表されたエスケープシーケンスに置き換えを行います。

Lambda 側でパスパラメーターから取得したbook_idパスの値をdecodeURIComponent()でデコードするようにします。

lib/cdk-sample-app.hogeFunc.ts

export const handler = async (
  event: Event
): Promise<{ statusCode: number; body?: string }> => {
  console.log(JSON.stringify(event, undefined, 2));

  const path = event.pathParameters;

  const book_id = decodeURIComponent(path?.book_id!);

  return {
    statusCode: 200,
    body: JSON.stringify({ book_id }),
  };
};

そして、REST API のマネジメントコンソールからメソッドテストを利用して動作確認をしてみます。

encodeURIComponent()でエンコード値を作成します。

> encodeURIComponent('/path/to/book01')
'%2Fpath%2Fto%2Fbook01'

エンコード値をパスパラメーターに指定してリクエストを送信すると、エンコード前の値をレスポンスで取得できました。

おわりに

Amazon API Gateway REST API のパスパラメーターでスラッシュを含む値を指定できるか試してみました。

結論としてはできなかったため、リクエスト送信時に値をエンコードするなどの対処方法を取る必要がありました。

以上