LoginSignup
3
5

FastAPIにおけるCORSのテスト方法

Posted at

概要

  • FastAPIで設定したCORSの自動テスト方法

CORSについて

オリジン間リソース共有 (Cross-Origin Resource Sharing, CORS) は、追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組み

FastAPIにおけるCORS設定方法

  • FastAPI アプリケーションでは CORSMiddleware を使用して、CORSに関する設定を実施
  • 詳細

CORSMiddlewareで設定可能な引数

引数 内容 デフォルト
allow_origins オリジン間リクエストを許可するオリジンのリスト
allow_origin_regex オリジン間リクエストを許可するオリジンの正規表現文字列
allow_methods オリジン間リクエストで許可するHTTPメソッドのリスト ['GET']
allow_headers オリジン間リクエストでサポートするHTTPリクエストヘッダーのリスト
CORSリクエストでは、 Accept 、 Accept-Language 、 Content-Language 、 Content-Type ヘッダーが常に許可されている
[]
allow_credentials オリジン間リクエストでCookieをサポートする必要があることを示します False
expose_headers ブラウザからアクセスできるようにするレスポンスヘッダーを示します []
max_age ブラウザがCORSレスポンスをキャッシュする最大時間を秒単位で設定します 600
main.py
"""FastAPIのエントリーポイント."""
from typing import Dict

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()
"""FastAPIのインスタンス"""

# 本来なら環境変数から設定できるようにしておくといい
origins = ["http://allowed.origin.com"]

# CORSのミドルウェアを設定
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/")
async def root() -> Dict[str, str]:
    """ルートパス.

    Returns:
        messeageを返却
    """
    return {"message": "Hello World"}

CORSの設定に対する自動テスト方法

  • CORSプリフライトリクエストを使用してCORSの自動テストを実施
    • Origin ヘッダーと Access-Control-Request-Method ヘッダーを持つ OPTIONS リクエスト
    • ミドルウェアはリクエストを横取りし、適切なCORSヘッダーと共に情報提供のために 200 または 400 のレスポンスを返す
  • 詳細
  • テスト方法
    • CORSプリフライトリクエストを設定
      • Originヘッダーにテストしたいオリジンを設定
      • Access-Control-Request-MethodにテストしたいHTTPメソッドを設定
    • OPTIONSリクエストを実施
    • HTTPステータスコードを確認
      • 200ならアクセス可能
      • 400ならアクセス不可能
    • レスポンスのヘッダーを確認
      • ステータスコードが200の場合
        • access-control-allow-originに送信したオリジンが設定されている
      • ステータスコードが400の場合
        • access-control-allow-originが設定されていないこと
test_cors.py
"""CORSのテスト."""

from fastapi import status
from fastapi.testclient import TestClient
from pytest import fixture

# FastAPIのインスタンスをimport
from main import app


@fixture
def client():
    """テスト用のクライアント."""
    return TestClient(app)

def test_allowed_cors(client):
    """CORSに設定されているパスがアクセス可能なことをテスト."""
    url = "http://allowed.origin.com"
    headers = {
        "Origin": url,
        "Access-Control-Request-Method": "GET"
    }

    response = client.options("/", headers=headers)
    assert status.HTTP_200_OK == response.status_code
    assert response.headers["access-control-allow-origin"] == url

def test_disallowed_cors(client):
    """CORSに設定されてないパスがアクセス不可能なことをテスト."""
    url = "http://disallowed.origin.com"
    headers = {
        "Origin": url,
        "Access-Control-Request-Method": "GET"
    }

    response = client.options("/", headers=headers)
    assert status.HTTP_400_BAD_REQUEST == response.status_code
    assert "access-control-allow-origin" not in response.headers

参考

3
5
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
3
5