API Gateway カスタムドメインのAPIマッピングの動作を確認する

- 2025/6/1時点の情報
- AWS 公式ドキュメントで日本語化されていないページはChromeの翻訳にて引用

## この記事でわかること
前提：「１つのREST APIの複数ステージ」を「１つのカスタムドメイン」にマッピングをするとき
- その方法とアクセスURLの使い分け（評価の方法）
- デフォルトエンドポイントタイプ無効化時の挙動




## 具体的なシチュエーションと結論
:::note
あくまで結論は一例です
:::
シチュエーション：
１つのREST API の `prod` `dev` のステージに対して１つのカスタムドメインとマッピングするには、どのような設定を行い、どのようなURLで呼び分けるのか？

結論：
APIマッピングのベースパスにそれぞれ `prod` `dev` など分かりやすいパスを設定する。
ベースパスをもとにマッピングされいてるAPIのステージへルーティングされる。

<br>
シチュエーション：
デフォルトエンドポイントタイプを「非アクティブ」にし、`prod`ステージのみに対してデプロイしたときは`dev`ステージではどのような挙動になるのか？


結論：
デプロイしたステージに関係なく、デフォルトエンドポイントを「非アクティブ」設定を行ったAPI内のステージは、デフォルトエンドポイントでの呼び出しが不可となる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/3e7ae627-fdbc-4aea-b5a0-e0a97f0c79fa.png)


## 参考情報（この後のセクションで実際の検証）
**REST API のカスタム ドメイン名に API ステージをマッピングする**

https://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-mappings.html

参考①
>APIマッピングを使用して、APIステージをカスタムドメイン名に接続します。これにより、トラフィックはカスタムドメイン名を通じてAPIに送信されます。

参考②
>APIマッピングでは、API、ステージ、そしてオプションでマッピングに使用するパスを指定します。例えば、productionAPIのステージを にマッピングできます`https://api.example.com/orders`

参考③
>複数階層の API マッピングがある場合、API Gateway は 最も長く一致するパスを持つマッピング にリクエストをルーティングします。どの API を呼び出すか決定する際、API Gateway が参照するのは API マッピングで設定されたパスだけ であり、API 本体のルート定義は判定に含まれません。


**ベースパスマッピングの取得**

https://docs.aws.amazon.com/apigateway/latest/api/API_GetBasePathMapping.html

参考④
>ベースパス
APIの呼び出し元がURLの一部としてドメイン名の後に指定する必要があるベースパス名です。この値は、単一のAPI内のすべてのマッピングにおいて一意である必要があります。呼び出し元がドメイン名の後にベースパス名を指定しないようにするには、「(none)」を指定します。

**API Gateway のパブリック REST API のカスタム ドメイン名**

https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html

参考⑤
>カスタムドメイン名を使用すると、API のホスト名を設定し、ベースパス（例：myservice）を選択して代替 URL を API にマッピングできます。例えば、よりユーザーフレンドリーな API ベース URL は次のようになります。
`https://api.example.com/myservice`

参考⑥
>APIのデフォルトエンドポイントを無効にすることができます。クライアントは引き続きデフォルトエンドポイントに接続できますが、403 Forbiddenステータスコードを受け取ります。


## 検証
### 事前情報
実際の値は異なるが記事上では以下と定義する。
- カスタムドメイン名：`customdomain.com`
- デフォルトエンドポイント：`default.execute-api.ap-northeast-1.amazonaws.com`

その他
- API Gateway
    - API名：domain-test-api
    - プロトコル：REST API
    - API エンドポイントタイプ：リージョン（東京）

### ０．カスタムドメイン設定前の動作確認
カスタムドメイン設定無し、デフォルトエンドポイント「アクティブ」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/1caf930a-0bd7-412f-b0fb-d17f8342a8e9.png)

リソース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/91a965f2-b7cc-4c2c-b5b3-a3c8d38053bf.png)

ステージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/00d70092-901d-4db1-ad27-15b610722c6b.png)

【 dev ステージのデプロイ状態とレスポンス】
サマリー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/2d546f4c-9df5-454f-9375-b09f0815235a.png)

レスポンス確認
`https://default.execute-api.ap-northeast-1.amazonaws.com/dev/goodbye`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/a28b871b-9e83-46d6-a808-fc25f250e545.png)

`https://default.execute-api.ap-northeast-1.amazonaws.com/dev/hello`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/322d2334-65e9-44db-b7c8-8e89ae25b21b.png)


【 prod ステージのデプロイ状態とレスポンス】
サマリー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/d6b56dcc-56cb-41aa-aaba-b78da2101340.png)
レスポンス確認
`https://default.execute-api.ap-northeast-1.amazonaws.com/prod/goodbye`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/c89a24ae-1ab9-4a7f-b98c-c81742997fec.png)
`https://default.execute-api.ap-northeast-1.amazonaws.com/prod/hello`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/22dc29b1-9084-4bef-9e22-37bd639460dc.png)



### 1．カスタムドメインの設定
ベースパスの指定は任意であるが、分かりやすいようにステージ名と対応付けるよう設定

ステージ：dev → ベースパス：dev
ステージ：prod → ベースパス：prod

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/3e5a2423-3b2b-4df2-ae20-b3e03667c302.png)

### ２．カスタムドメインでのアクセス確認
「 カスタムドメイン / ベースパス / リソースパス 」でアクセスを検証
- ベースパスに基づき対応するステージのAPIへルーティングされることを確認
- API Gateway が参照するのは API マッピングで設定されたパスだけ であり、
API 本体のルート定義は判定に含まれないことを確認

【 ベースパス`dev`指定】
`https://customdomain.com/dev/goodbye`
→ dev ステージ の goodbye

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/b744f703-85f8-40fc-9077-d49f95eb0397.png)

`https://customdomain.com/dev/hello`
→ dev ステージの hello

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/99f50769-5d70-414b-be20-a56f8be157f4.png)

【ベースパス`prod`指定】
`https://customdomain.com/prod/goodbye`
→ prod ステージの goodbye

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/88f34c5b-59c4-433b-a936-9eebd8016ae1.png)

`https://customdomain.com/prod/hello`
→ prod ステージの hello

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/c3830686-353c-4854-9a22-02468305284c.png)

### ３．デフォルトエンドポイントでもアクセスできることを確認
デフォルトエンドポイント「アクティブ」のままのため、手順２のカスタムドメインに加えてデフォルトエンドポイント経由でもアクセスできることを確認
※hello リソースは割愛

【`dev`ステージ】
`https://default.execute-api.ap-northeast-1.amazonaws.com/dev/goodbye`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/a28b871b-9e83-46d6-a808-fc25f250e545.png)

【`prod`ステージ】
`https://default.execute-api.ap-northeast-1.amazonaws.com/prod/goodbye`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/c89a24ae-1ab9-4a7f-b98c-c81742997fec.png)

### ４．デフォルトエンドポイントを「非アクティブ」に設定
APIの設定から非アクティブに変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/77d6af85-fad3-470f-be57-932984706488.png)

非アクティブになっていることを確認
※設定反映には再デプロイが必要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/7f6351c0-47bc-44a6-b459-d8a50b6d17d6.png)

APIの再デプロイを行う
今回は`prod`ステージに対してデプロイ
→ この後、`prod`ステージに対してデプロイしたが`dev`ステージにも影響があるのか確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/f3f882e6-40e3-4d33-8213-889794208aae.png)

デプロイを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/2252f068-b3d2-4593-9540-34b8411f4e0e.png)

APIマッピングからも確認
→ この時点で`dev`ステージも無効になっている（察し...）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/86c74af8-5875-44d1-8a33-dea3c18f6109.png)

### ５．再度 カスタムドメインとデフォルトエンドポイントでのアクセス確認
カスタムドメインでのアクセス確認
※２．カスタムドメインでのアクセス確認 と結果が同じであったため割愛
→ カスタムドメインでのアクセスには影響なし

デフォルトエンドポイントでのアクセス
【 `dev` ステージ】
`https://default.execute-api.ap-northeast-1.amazonaws.com/dev/goodbye`
`https://default.execute-api.ap-northeast-1.amazonaws.com/dev/hello`

【 `prod` ステージ】
`https://default.execute-api.ap-northeast-1.amazonaws.com/prod/goodbye`
`https://default.execute-api.ap-northeast-1.amazonaws.com/prod/hello`

いずれも以下の通り正常アクセスできない`Forbidden`を確認
※APIの設定のため、デプロイ対象のステージに依存することなく `dev` ステージでもデフォルトエンドポイントは無効化されることが確認できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/4bfb32d5-c6fe-4561-b581-36d50f7a3bbd.png)

### ６．`dev` ステージをAPIマッピングから削除する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/a9f2088c-8ac5-46d6-b218-d27f734db120.png)

### ７．アクセス確認
APIマッピング：`prod`ステージのみ、デフォルトエンドポイント：非アクティブ の状態でそれぞれのアクセス結果を確認する。

【 `dev` ステージ】
`https://default.execute-api.ap-northeast-1.amazonaws.com/dev/goodbye`
`https://default.execute-api.ap-northeast-1.amazonaws.com/dev/hello`
`https://customdomain.com/dev/goodbye`
`https://customdomain.com/dev/hello`

デフォルトエンドポイント、カスタムドメイン、いずれも以下の通り`Forbidden`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3879433/66298479-9496-497f-a460-97bfd3e5b58f.png)

【 `prod` ステージ】
`https://default.execute-api.ap-northeast-1.amazonaws.com/dev/goodbye`
`https://default.execute-api.ap-northeast-1.amazonaws.com/dev/hello`
→ デフォルトエンドポイント「非アクティブ」のため `Forbidden`

`https://customdomain.com/dev/goodbye`
→ Goodbye prod from Lambda!

`https://customdomain.com/dev/hello`
→ Hello prod from Lambda!

カスタムドメインで正常アクセスを確認


【その他】
`https://customdomain.com/hello`
→ 該当するベースパスが無いため`Forbidden`

## まとめ
参考情報の通り以下の点が確認できた。
- （参考①~⑥）APIマッピングによってベースパスに基づき対象のAPIへルーティングする
-  （参考③）API を呼び出すか決定する際、API Gateway が参照するのは API マッピングで設定されたパスだけ であり、API 本体のルート定義は判定に含まれない
- （参考⑥）APIのデフォルトエンドポイントを無効にすると403 Forbiddenステータスコードを受け取る

**カスタムドメインの動き**
`https://customdomain.com/「dev」/hello`
「dev」がAPIマッピング（ベースパス）として、どのAPIを呼ぶかを決定する。
`hello`以降が渡されてAPI内のリソースパスに基づき動作する。

今回は未検証であるが、以下の通りロンゲストマッチでリクエストをルーティングする。

https://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-mappings.html


**デフォルトエンドポイントの非アクティブ（無効化）**
- 設定を反映させるためにはAPIの再デプロイが必要
- その際デプロイ先のステージ以外のAPIに存在する全ステージが非アクティブとなる

以上！