📘
CORSとPreflightリクエスト
はじめに
フロントエンドとバックエンド間でAPI通信を行う際、ブラウザのセキュリティ制限によりCORS(Cross-Origin Resource Sharing:クロスオリジンリソース共有)エラーが発生することがあります。本記事では、CORSの仕組みやPreflightリクエストの動作について解説し、エラーが発生した場合の解決方法を紹介します。
この記事の対象読者
この記事は、以下のようなエンジニアや開発者を対象としています。
- フロントエンドとバックエンドを連携させたAPI通信を行う際に、CORSエラーに直面した方
- ReactやVueなどのSPAからAPIを呼び出す開発をしている方
- バックエンドにFlaskやExpressを使用しており、CORSの設定に不慣れな方
- Preflightリクエストが原因のエラーに対する理解を深めたい方
CORSは、初学者から経験者まで頻繁に悩むポイントなので、正しく理解し、トラブルシューティングできるようになることを目指しています。
CORS(クロスオリジンリソース共有)とは?
CORSは、ブラウザが異なるオリジン(例:http://localhost:3000からhttp://127.0.0.1:5000)へのリクエストを送る場合に、セキュリティ上の理由でリクエストを制限する仕組みです。CORSは、サーバーが許可する場合に限り、クライアントからのリクエストを受け入れます。
Preflightリクエストとは?
Preflightリクエストは、ブラウザが本体のリクエストを送信する前に、サーバーがそのリクエストを受け入れるかどうかを確認するためのOPTIONSリクエストです
- Preflightリクエストの特徴
- HTTPメソッドがOPTIONS
- 本体のリクエストに先行して送信される
- サーバーがCORSの許可を示す必要がある
Preflightリクエストが発生する条件
- リクエストにカスタムヘッダー(例:Authorization)が含まれている場合
- HTTPメソッドがPOST, PUT, DELETEなど、単純なリクエスト以外の場合
- リクエストヘッダーにContent-Type: application/jsonが含まれている場合
CORSエラーの発生原因と解決方法
- FlaskでのCORS設定
PythonのFlaskでAPIを実装する場合、CORSの設定が不十分だとPreflightリクエストが失敗します。flask-corsを使うことで、簡単にCORSを許可できます。
flask-corsのインストール
pip install flask-cors
FlaskアプリにCORSを設定する
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # すべてのオリジンを許可
@app.route('/login', methods=['POST'])
def login():
return {"message": "Login successful"}
- 特定のオリジンを許可する方法
すべてのオリジンを許可するのではなく、特定のオリジンだけを許可したい場合は、次のように設定します。
CORS(app, resources={r"/*": {"origins": "http://localhost:3000"}})
- 必要なCORSヘッダーの例
Preflightリクエストが成功し、本体リクエストが実行されるためには、次のようなヘッダーが必要です。
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
- Preflightと本体リクエストの確認方法
- ブラウザのDevTools(F12)を開き、Networkタブでリクエストを確認します。
- OPTIONSリクエストが200 OKを返していれば、Preflightは正常に動作しています。
- 本体リクエスト(例:POST /login)がブロックされずに実行されているか確認します。
- ReactからのAPIリクエスト例
以下は、ReactからFlask APIにPOSTリクエストを送る際のサンプルコードです。
import axios from 'axios';
const API_URL = 'http://127.0.0.1:5000';
export const login = async (username: string, password: string) => {
const response = await axios.post(`${API_URL}/login`, { username, password });
return response.data.token;
};
- まとめ
CORSとPreflightリクエストは、Webアプリケーションのセキュリティを強化するための重要な仕組みです。適切に設定することで、異なるオリジン間のAPI通信をスムーズに行うことができます。
- Preflightリクエストで200 OKが返っても、本体リクエストが失敗する場合は、CORS設定の見直しが必要
- フロントエンドとバックエンドの整合性を確認し、必要なヘッダーを適切に設定することで、CORSエラーを回避が可能
Discussion