CORS (Cross-Origin Resource Sharing) の基本と設定方法

Web開発では、異なるオリジン間での通信を安全に行うために **CORS (Cross-Origin Resource Sharing)** を利用します。この記事では、CORSの基本から、Node.js（Express）を使った実装例、さらに設定の確認方法までを解説します。

---

## **CORS とは？**

CORS は、ブラウザが異なるオリジン間でリソースを共有する際に発生するセキュリティ制限を緩和する仕組みです。たとえば、`http://example.com` でホストされているウェブページが、`http://api.example.com` にリクエストを送る場合、CORS の設定が必要になります。

### **オリジンとは？**
オリジンは以下の3つの要素で構成されます：
- **スキーム (プロトコル):** `http` または `https`
- **ホスト名:** 例: `example.com`
- **ポート番号:** 例: `:80`

これらのいずれかが異なる場合、オリジンが異なるとみなされます。

例：
- `http://example.com` と `http://api.example.com` は異なるオリジン
- `http://example.com:80` と `http://example.com` は同じオリジン

---

## **CORS の基本設定**

CORSの設定はサーバー側で行います。以下では、Node.js と Express を使って、CORSを簡単に設定する方法を説明します。

### **1. 必要なパッケージをインストールする**

CORS設定を簡単に行うため、公式の `cors` パッケージを使用します。

```bash
npm install cors
```

### **2. サーバーのセットアップ**
以下は、特定のオリジンからのリクエストを許可する例です。

```javascript
const express = require('express');
const cors = require('cors');

const app = express();

// CORS の設定
app.use(cors({
  origin: 'https://example.com', // 許可するオリジン
  methods: ['GET', 'POST'],      // 許可するHTTPメソッド
  credentials: true             // 認証情報を含むリクエストを許可
}));

// API エンドポイント
app.get('/api/data', (req, res) => {
  res.json({ message: 'CORS is working!' });
});

// サーバー起動
app.listen(3000, () => {
  console.log('Server running on port 3000');
});
```

### **3. オリジンを柔軟に設定する**
特定のオリジンのみを許可したい場合や、複数のオリジンを扱う場合の例です。

#### **複数オリジンを許可**
```javascript
const allowedOrigins = ['https://example.com', 'https://another-domain.com'];

app.use(cors({
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
  credentials: true
}));
```

---

## **プリフライトリクエストの対応**

特定の条件下では、ブラウザが本リクエストの前に "プリフライトリクエスト" を送信します。これは、`OPTIONS` メソッドを使ったリクエストで、サーバーが特定の条件を満たすか確認します。

サーバーがこのリクエストに正しく応答するように設定します。

```javascript
app.options('*', cors()); // すべてのエンドポイントでプリフライトリクエストに対応
```

---

## **クライアントからのリクエスト例**

CORS設定が有効になったサーバーに対して、ブラウザ側からリクエストを送信します。

```javascript
fetch('https://example.com/api/data', {
  method: 'GET',
  credentials: 'include' // クッキーや認証情報を含める場合
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));
```

- **`credentials: 'include'`** を指定する場合、サーバー側で `Access-Control-Allow-Credentials: true` を設定する必要があります。

---

## **確認方法**

### **ブラウザでの確認**
1. **開発者ツールを開く**
   - `F12` または右クリック → 「検証」から起動。
2. **ネットワークタブを確認**
   - リクエストヘッダーとレスポンスヘッダーに次のCORSヘッダーが含まれているか確認します。
     - `Access-Control-Allow-Origin`
     - `Access-Control-Allow-Methods`

### **curl コマンドで確認**

```bash
curl -X OPTIONS 'https://example.com/api/data' -I
```

- レスポンスに `Access-Control-*` ヘッダーが含まれていれば、CORS設定が有効です。

---

## **トラブルシューティング**

CORSエラーが発生した場合、以下を確認します。

1. **`Access-Control-Allow-Origin` が正しいか？**
   - ワイルドカード (`*`) を使用している場合、`credentials: true` と併用できません。

2. **プリフライトリクエストに対応しているか？**
   - `OPTIONS` リクエストにサーバーが適切に応答しているか確認します。

3. **ブラウザキャッシュをクリア**
   - 古いキャッシュが原因でエラーが発生することがあります。

---

## **まとめ**

CORSの設定は、一見複雑に思えるかもしれませんが、`cors` パッケージを使うことで簡単に実装できます。適切な設定を行い、安全で効率的なAPI通信を実現しましょう。

ぜひこの記事を参考に、CORSの理解を深めてください！