はじめに
AWS の Application Load Balancer(ALB)で HTTPS 終端を行い、バックエンド(FastAPI/Uvicorn)へは HTTP でリクエストを流す構成において、CORS エラーが発生する事例がありました。
原因は HTTPS→HTTP へリダイレクトされる際に必要な Access-Control-*
ヘッダーが欠落すること にありました。この記事では、その原因と解決手順をまとめます。
問題の再現例
-
ブラウザがプリフライト(OPTIONS)リクエストを発行
OPTIONS https://request.example.com Origin: https://client.example.com
-
ALB(HTTPS→HTTP 終端) → Uvicorn(HTTP:80)へ転送
-
FastAPI がリダイレクトを返却
HTTP/1.1 307 Temporary Redirect Location: http://request.example.com/
-
ブラウザが HTTP 側へ再プリフライト
-
ALB の HTTP→HTTPS リダイレクトルール(301)で HTTPS に戻る
-
一度も CORS ヘッダーが付与されず ブラウザが以下を出力して失敗
No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
原因の詳細
-
ALB が HTTPS 終端 → バックエンドへは HTTP で転送
この際、起動時の設定を行なっておらず、X-Forwarded-Proto: https
が付与されていない -
Uvicorn はデフォルトで「127.0.0.1 からのプロキシのみ信頼」
→ ALB からのX-Forwarded-Proto
を無視 →request.url.scheme
がhttp
のまま - ブラウザは一度 HTTP エンドポイントへ飛び、CORS ミドルウェアを経由しないまま再リダイレクト
- 結果的に CORS ヘッダーが一切付与されず リクエストがブロック
解決方法
1. Uvicorn 起動時にプロキシを全許可する
Dockerfile や起動スクリプトで、以下オプションを追加します。
uvicorn app.main:app --reload --proxy-headers --forwarded-allow-ips="*"
-
--proxy-headers
:X-Forwarded ヘッダーを処理 -
--forwarded-allow-ips="*"
:任意のプロキシ IP を信頼
2. コード上で ProxyHeadersMiddleware を追加
CLI オプションが使えない場合は、main.py
に以下を挿入します。
from starlette.middleware.proxy_headers import ProxyHeadersMiddleware
app = FastAPI()
app.add_middleware(ProxyHeadersMiddleware, trusted_hosts="*")
まとめ
- 真の原因:HTTPS→HTTP リダイレクト時に CORS ヘッダーが付かずブロック
-
対策:Uvicorn に
--proxy-headers
と--forwarded-allow-ips="*"
を追加する
以上の手順で、ALB 経由の CORS エラーは解消できます。ぜひお試しください!