要約:60秒で解決する方法
このエラーを解消するには、バックエンドサーバーに対してフロントエンドを信頼するように設定する必要があります。これは、APIレスポンスに Access-Control-Allow-Origin ヘッダーを追加することで行います。開発環境では、ワイルドカードを使用してすべてを許可できます:
Access-Control-Allow-Origin: *
本番環境では、より具体的に指定する必要があります。* を https://app.yourdomain.com などの実際のドメインに置き換えてください。重要なのは、この修正はフロントエンドのコードではなく、サーバーまたはAPIゲートウェイで行う必要があるという点です。
なぜブラウザはブロックするのか?
ブラウザは、**同一生成元ポリシー(Same-Origin Policy: SOP)**と呼ばれるセキュリティメカニズムを使用しています。これにより、悪意のあるウェブサイトがプライベートなAPIに対してリクエストを送信することを防いでいます。localhost:3000 にあるReactアプリが api.domain.com からデータを取得しようとすると、ブラウザはドメインが一致しないことを検知します。そして即座に、サーバーからの「許可証」を探します。
サーバーが Access-Control-Allow-Origin ヘッダーを通じてその許可を返さない場合、ブラウザはリクエストを遮断します。その際、コンソールにはおなじみの赤いテキストが表示されます:
Access to fetch at 'http://api.domain.com' from origin 'http://localhost:3000' has been blocked by CORS policy.
バックエンドでCORSを修正する方法
1. Node.js (Express)
cors ミドルウェアは、Expressアプリにおける標準的な解決策です。面倒な処理をすべて代行してくれます。
// インストール: npm install cors
const express = require('express');
const cors = require('cors');
const app = express();
// オプションA: すべて許可(クイックテストに最適)
app.use(cors());
// オプションB: セキュアな設定(本番環境に推奨)
const corsOptions = {
origin: 'https://my-cool-app.com',
optionsSuccessStatus: 200
};
app.use(cors(corsOptions));
2. Python (Flask)
Flask開発者は flask-cors 拡張機能を使用すべきです。すべてのルートに手動でヘッダーを注入するよりもはるかにスマートです。
# インストール: pip install flask-cors
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
# アプリ全体のすべてのルートでCORSを有効にする
CORS(app)
@app.route("/api/data")
def get_data():
return {"status": "success", "data": "CORS is working!"}
3. Nginxの設定
アプリケーションのコードを触ることができない場合もあります。その場合は、リバースプロキシのレベルでCORSを処理します。これは、トラフィックの多いAPIではより効率的な場合が多いです。
location /api/ {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://myapp.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type';
add_header 'Access-Control-Max-Age' 1728000;
return 204;
}
add_header 'Access-Control-Allow-Origin' 'https://myapp.com' always;
proxy_pass http://backend_cluster;
}
4. Spring Boot (Java)
Java開発者は @CrossOrigin アノテーションを使用できます。これは単一のメソッド、またはコントローラークラス全体に適用できます。
@RestController
@RequestMapping("/v1")
public class ApiController {
@CrossOrigin(origins = "http://localhost:3000")
@GetMapping("/users")
public List<User> getUsers() {
return userService.findAll();
}
}
修正を確認する方法
ページを更新して直っていることを祈るだけでは不十分です。以下の2つの方法で確実に確認してください:
- ネットワークタブ: F12キーを押してネットワークタブを開きます。APIリクエストをクリックし、レスポンスヘッダーの下に
Access-Control-Allow-Originがあることを確認します。もしなければ、サーバーの設定が反映されていません。 - ターミナル: cURLを使用してクロスオリジンリクエストをシミュレートします。次のコマンドを実行してください:
curl -I -H "Origin: http://localhost:3000" http://api.domain.com/data
出力の中に access-control-allow-origin: http://localhost:3000 という行があるか確認します。
よくある失敗の原因
CORSは非常に厄介なことで知られています。依然としてエラーが出る場合は、以下の3つのよくある原因を確認してください:
- プロトコルの不一致:
http://domain.comとhttps://domain.comは異なるオリジンです。フロントエンドがHTTPSでAPIがHTTPの場合、ブラウザはブロックします。 - 末尾のスラッシュ: 一部のサーバーでは、
http://localhost:3000と(スラッシュありの)http://localhost:3000/を異なるオリジンとして扱います。統一するようにしてください。 - 資格情報とワイルドカード: Cookieや
Authorizationヘッダーを送信する場合、オリジンに*を使用することはできません。正確なドメインを指定し、Access-Control-Allow-Credentials: trueを設定する必要があります。
これらのリクエストに対してIP範囲をホワイトリストに登録したり、ファイアウォールを設定したりする場合、正確さが重要になります。私はCIDR範囲を素早く確認するために、ToolCraftの Subnet Calculator を使用しています。これにより、インフラを誤ってパブリックインターネットに公開することなく、APIゲートウェイが内部サービスからアクセス可能な状態を維持できます。
チートシート:主要なCORSヘッダー
ヘッダー
役割
`Access-Control-Allow-Origin`
APIとの通信を許可する対象を定義します。
`Access-Control-Allow-Methods`
許可されるHTTPメソッド(GET、DELETEなど)をリストします。
`Access-Control-Max-Age`
CORSの許可をブラウザがキャッシュする秒数(例:86400)を指定します。

