cors の使い方

Node.js CORS middleware

v2.8.6/週MITWeb API
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

cors の使い方 — Node.js CORS ミドルウェア完全ガイド

一言でいうと

cors は、Express/Connect アプリケーションに CORS(Cross-Origin Resource Sharing)レスポンスヘッダーを付与する Node.js ミドルウェアです。ブラウザが異なるオリジンからの API レスポンスを読み取れるかどうかを制御します。

どんな時に使う?

  • フロントエンドとバックエンドが別ドメイン/ポートで動いている時 — React(localhost:3000)から Express API(localhost:8080)を呼ぶ開発環境など
  • 公開 API を提供する時 — 外部サイトの JavaScript から自社 API を利用可能にしたい場合
  • 特定のオリジンだけにアクセスを許可したい時 — 自社のフロントエンドドメインのみ API レスポンスの読み取りを許可する場合

重要: CORS はブラウザが実施するセキュリティ機構です。cors パッケージはレスポンスヘッダーを設定するだけで、リクエスト自体をブロックするわけではありません。curl や Postman などの非ブラウザクライアントは CORS を無視します。

インストール

# npm
npm install cors

# yarn
yarn add cors

# pnpm
pnpm add cors

TypeScript の型定義も合わせてインストールします:

npm install --save-dev @types/cors

基本的な使い方

最もシンプルなパターンは、すべてのオリジンからのアクセスを許可する方法です。

import express from 'express';
import cors from 'cors';

const app = express();

// すべてのルートで CORS を有効化(Access-Control-Allow-Origin: *)
app.use(cors());

app.get('/api/products/:id', (req, res) => {
  res.json({ msg: 'This is CORS-enabled for all origins!' });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

よく使う API・設定パターン

1. 特定のオリジンのみ許可する

import express from 'express';
import cors from 'cors';

const app = express();

const corsOptions: cors.CorsOptions = {
  origin: 'https://example.com',
  optionsSuccessStatus: 200, // IE11 や一部のスマートTVは 204 で問題が起きる
};

app.use(cors(corsOptions));
// → Access-Control-Allow-Origin: https://example.com
// → Vary: Origin

app.get('/api/data', (req, res) => {
  res.json({ data: 'restricted' });
});

app.listen(3000);

2. 複数のオリジンを許可する(配列指定)

import cors from 'cors';

const corsOptions: cors.CorsOptions = {
  origin: [
    'https://app.example.com',
    'https://admin.example.com',
    /\.example\.com$/, // example.com のサブドメインすべてにマッチ
  ],
};

app.use(cors(corsOptions));

3. 動的にオリジンを判定する(DB 連携など)

import cors from 'cors';

const corsOptions: cors.CorsOptions = {
  origin: (origin, callback) => {
    // origin は undefined になることがある(同一オリジンリクエストや非ブラウザ)
    if (!origin) {
      return callback(null, true);
    }

    // 例: DB やキャッシュから許可リストを取得
    const allowedOrigins = ['https://app.example.com', 'https://partner.example.com'];

    if (allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
};

app.use(cors(corsOptions));

4. Cookie/認証情報を含むリクエストを許可する

import cors from 'cors';

const corsOptions: cors.CorsOptions = {
  origin: 'https://app.example.com', // credentials 使用時は * 不可
  credentials: true, // Access-Control-Allow-Credentials: true
};

app.use(cors(corsOptions));
// フロントエンド側: fetch(url, { credentials: 'include' })

5. 特定ルートのみ CORS を有効化 / プリフライト対応

import express from 'express';
import cors from 'cors';

const app = express();

// 全ルートの OPTIONS プリフライトに対応
app.options('*', cors());

// 特定ルートのみ CORS を有効化
app.get('/api/public', cors(), (req, res) => {
  res.json({ msg: 'Public endpoint' });
});

// リクエストごとに動的に CORS 設定を切り替え
const dynamicCors: cors.CorsOptionsDelegate = (req, callback) => {
  let options: cors.CorsOptions;

  if (req.path.startsWith('/auth/')) {
    options = { origin: 'https://app.example.com', credentials: true };
  } else {
    options = { origin: '*' };
  }

  callback(null, options);
};

app.use(cors(dynamicCors));

app.listen(3000);

設定オプション一覧

オプションデフォルト説明
originboolean | string | RegExp | Array | Function'*'許可するオリジン
methodsstring | string[]'GET,HEAD,PUT,PATCH,POST,DELETE'許可する HTTP メソッド
allowedHeadersstring | string[]リクエストの Access-Control-Request-Headers を反映許可するリクエストヘッダー
exposedHeadersstring | string[]なしブラウザに公開するレスポンスヘッダー
credentialsbooleanfalseAccess-Control-Allow-Credentials を設定
maxAgenumberなしプリフライト結果のキャッシュ秒数
preflightContinuebooleanfalseプリフライトレスポンスを次のハンドラに渡す
optionsSuccessStatusnumber204OPTIONS リクエスト成功時のステータスコード

類似パッケージとの比較

パッケージ特徴週間DL数備考
corsExpress/Connect 向け定番ミドルウェア約1,800万最も広く使われている
@fastify/corsFastify 専用 CORS プラグイン約50万Fastify を使うならこちら
@koa/corsKoa 専用 CORS ミドルウェア約20万Koa を使うならこちら
helmetセキュリティヘッダー全般を設定約200万CORS 専用ではないが併用されることが多い

※ DL 数は目安です。フレームワークに合ったパッケージを選びましょう。

注意点・Tips

1. credentials: trueorigin: '*' は併用できない

ブラウザの仕様上、Access-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: * の組み合わせはエラーになります。Cookie を使う場合は必ず具体的なオリジンを指定してください。

// ❌ NG: ブラウザがエラーを出す
{ origin: '*', credentials: true }

// ✅ OK: 具体的なオリジンを指定
{ origin: 'https://app.example.com', credentials: true }

2. origin 関数の第一引数は undefined になりうる

同一オリジンからのリクエストや、curl などの非ブラウザクライアントからのリクエストでは originundefined になります。関数内で必ずハンドリングしてください。

origin: (origin, callback) => {
  // origin が undefined の場合の処理を忘れずに
  if (!origin || allowedOrigins.includes(origin)) {
    callback(null, true);
  } else {
    callback(new Error('Not allowed by CORS'));
  }
}

3. app.use(cors()) ならプリフライトは自動対応

アプリケーションレベルで app.use(cors()) を使っている場合、すべてのルートの OPTIONS リクエストが自動的に処理されます。個別ルートに cors() を適用している場合は、app.options() を明示的に追加する必要があります。

4. CORS はセキュリティの「壁」ではない

CORS はブラウザ側の仕組みです。サーバーサイドの認証・認可の代わりにはなりません。API キーや JWT トークンによる認証は別途実装してください。

5. プリフライトのキャッシュで不要なリクエストを減らす

maxAge を設定すると、ブラウザがプリフライトの結果をキャッシュし、毎回の OPTIONS リクエストを省略できます。

const corsOptions: cors.CorsOptions = {
  origin: 'https://app.example.com',
  maxAge: 86400, // 24時間キャッシュ
};

まとめ

cors は Express/Connect アプリケーションに CORS ヘッダーを設定するためのデファクトスタンダードなミドルウェアです。app.use(cors()) の一行で全オリジン許可から、動的オリジン判定や認証情報付きリクエストまで柔軟に対応できます。ただし、CORS はブラウザ側の仕組みに過ぎないため、サーバーサイドの認証・認可と組み合わせて正しくセキュリティを設計することが重要です。