個人的備忘録：AWS ホスティング API × CloudFront でハマる CORS 問題を整理し、記事としてアウトプットしてみた

## はじめに

Web 開発をしていると、ある日突然「CORS エラー」が発生し、「Access-Control-Allow-Origin が設定されていません」といったエラーメッセージに遭遇することがあります。

:::note note
**フロントエンドとバックエンドを分けて開発していると特に起こりやすく、解決しないと API へのリクエストが通らないため、非常に困る問題です。**
:::

この記事では、CORS とは何か、なぜ必要なのか、具体的な例とともに分かりやすく解説します。

## 書こうと思ったきっかけ

最近、フロントエンド（React や Vue.js など）とバックエンド（Node.js や Python など）を分離したアーキテクチャが一般的になってきました。

:::note warn
***その際に、多くの開発者が CORS の壁にぶつかります（私も今、ぶつかっています）。***
:::

特に、AWS でホスティングした API や、CDN（CloudFront）を経由したリクエストで CORS の問題が発生しがちです。

私自身も、S3 にホストした React フロントエンドと、ALB（Application Load Balancer）経由のバックエンド API を組み合わせた際に、CORS の設定を正しくしないと API リクエストがブロックされる経験をしました。

**この経験から、CORS の基本と設定方法を整理し、多くの開発者がスムーズに解決できるようにしたいと思いました。**

## CORS（Cross-Origin Resource Sharing）とは？

CORS（クロスオリジンリソース共有）とは、異なるオリジン（ドメイン、プロトコル、ポートが異なるサーバー）間でリソースを共有するための仕組みです。

Web ブラウザには、**同一オリジンポリシー（Same-Origin Policy, SOP）** という制約があります。

:::note alert
**このポリシーにより、異なるオリジンのサーバーへのリクエストはデフォルトでブロックされます。**
:::

しかし、CORS を適切に設定することで、安全に異なるオリジンのリソースへアクセスできるようになります。

## 一般的な読み方

CORS の一般的な読み方は、
- **「コルス」**（英語の発音に近い）

多くの開発者が「コルス」と発音することが多いです。

https://qiita.com/c6tower/items/6acb64aef5966b1c999a

https://developer.mozilla.org/ja/docs/Glossary/CORS

## なぜ CORS が必要なのか？

ブラウザはセキュリティのために「同一オリジンポリシー」を採用しており、異なるオリジンへのリクエストを制限しています。

例えば、`https://frontend.example.com` にホストされたフロントエンドアプリが、`https://api.example.com` の API にリクエストを送ると、CORS の設定がない限りブロックされます。

:::note info
***これは、悪意のあるスクリプトが勝手に他のサイトのデータを取得したり、不正なリクエストを送信することを防ぐための仕組みです。***
:::

しかし、正規のアプリケーション開発においては、異なるオリジンの API を使うことが一般的なため、CORS の設定を適切に行うことで、この制限を解除する必要があります。

## オリジンとは？

オリジン（Origin）とは、 **「プロトコル + ドメイン + ポート」** の 3 つの要素で構成される識別情報です。

例えば、以下の 3 つの URL はすべて **異なるオリジン** となります。

| URL | オリジン |
|---|---|
| `https://example.com` | `https://example.com` |
| `http://example.com` | `http://example.com` （プロトコルが異なる）|
| `https://api.example.com` | `https://api.example.com` （サブドメインが異なる）|
| `https://example.com:3000` | `https://example.com:3000` （ポートが異なる）|

異なるオリジンにリクエストを送る際には、CORS の設定が必要になります。

## 簡単な CORS の例

### **1. CORS エラーが発生するケース**

```js
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('CORS Error:', error));
```

上記のコードを `https://frontend.example.com` で実行すると、バックエンドが CORS を許可していない場合、ブラウザは以下のエラーを出します。

```
Access to fetch at 'https://api.example.com/data' from origin 'https://frontend.example.com' has been blocked by CORS policy.
```

### **2. サーバー側で CORS を許可する方法**

バックエンドで CORS を許可することで、この問題を解決できます。

#### **Flask（Python）**
```python
from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)  # すべてのオリジンを許可

@app.route('/data')
def data():
    return {"message": "Hello from API"}
```

#### **Express（Node.js）**
```js
const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors({ origin: "https://frontend.example.com" }));  // 特定のオリジンを許可
```

サーバー側で `Access-Control-Allow-Origin` を適切に設定すれば、フロントエンドからのリクエストが正常に通るようになります。

## まとめ  
- CORS（Cross-Origin Resource Sharing）は、異なるオリジン間での通信を制御する仕組み。  
- 同一オリジンポリシーにより、異なるオリジンへのリクエストはデフォルトでブロックされる。  
- API サーバー側で CORS の設定を行うことで、異なるオリジンからのリクエストを許可できる。  
- AWS では ALB ではなく、EC2 や ECS のアプリケーション側で CORS を設定する必要がある。  

CORS の仕組みを理解し、適切に設定することで、フロントエンドとバックエンドをスムーズに連携させることができます！