Node.js、Express.jsにおけるCORSの理解と設定方法

CORS(Cross-Origin Resource Sharing)は、ウェブページが他のドメインのリソースを要求できるようにするウェブセキュリティ標準です。

ウェブブラウザはデフォルトで Same-Origin Policy を遵守しているため、現在のウェブページと異なる出所からのリソース要求は制限されます。

このため、ウェブページが他のドメインの API を要求する場合には、CORS 設定が必要となります。

Node.js での CORS 設定

Node.js で CORS 設定を行うためには、'cors'ライブラリを使用することができます。まず最初に、このライブラリをインストールする必要があります。

Setting Cors

npm install cors

最も基本的な CORS 設定

すべてのドメインからのリクエストを許可するように設定します。

ただし、すべてのドメインからのリクエストを許可すると、問題が発生する可能性があるため、詳細な設定を行う必要があります。

問題とは、異なるドメインからリソースを要求する場合を指します。

use cors

const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors());

CORS 初級設定

もっと詳細な設定を行いたい場合は、'cors' 関数にオプションオブジェクトを渡すことができます。

'origin' プロパティには許可したいドメインを指定できます。また、'credentials' プロパティを 'true' に設定すると、そのドメインからのリクエストがクッキーなどの認証情報を含むように許可されます。

このように設定すると、ブラウザがサーバーにリクエストを送信する際に 'Access-Control-Allow-Origin' と 'Access-Control-Allow-Credentials' ヘッダーが追加され、CORS ポリシーが遵守されます。

以上が Node.js で CORS を設定する方法についての説明でした。この機能を活用することで、安全に他のドメインのリソースを要求して利用することができます。

basic cors setting

app.use(
  cors({
    origin: 'http://localhost:3300',
    credentials: true,
  }),
);

CORS 詳細設定

  1. origin: クライアントサイトの URL を指定します。この場合、http://localhost:3300 からのリクエストのみ許可されます。
  2. methods: 許可する HTTP メソッドを指定します。この場合、GET と POST メソッドを使用するリクエストのみ許可されます。
  3. allowedHeaders: サーバーが受け入れるリクエストヘッダーを指定します。この場合、リクエストヘッダーに Content-Type と Authorization が含まれている必要があります。例を見る
  4. credentials: レスポンスヘッダーに Access-Control-Allow-Credentials を追加します。この場合、リクエストはクッキーや認証情報を含めることができます。例を見る
  5. maxAge: プリフライトリクエストの結果をキャッシュする時間を秒単位で指定します。この場合、プリフライトリクエストの結果は 600 秒間キャッシュされます。詳細を確認する

detail cors setting

const express = require('express');
const cors = require('cors');
const app = express();

app.use(
  cors({
    origin: 'http://localhost:3300',
    methods: ['GET', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization'],
    credentials: true,
    maxAge: 600,
  }),
);

allowedHeaders

try 文の内部に、ヘッダーの設定を確認できます。

allowedHeaders

async function sendData() {
  try {
    const response = await fetch('http://localhost:3300/sample', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: 'token sample',
      },
      body: JSON.stringify({
        title: 'title',
        description: 'description',
      }),
    })

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }

    const data = await response.json()
    console.log(data)
  } catch (error) {
    console.error('Error:', error)
  }
}

sendData()

credentials

credentials: 'include'로 설정하면、クライアントはリクエストにクッキーを含めることができます。

逆に、'omit'に設定すると、クライアントはリクエストにクッキーを含めません。

サーバーで credentials: true を設定したからといって、必ずしも認証情報を含める必要はありません。逆に credentials が false の場合、認証情報を含めることはできません。

credentials

fetch('http://localhost:3300/sample', {
  method: 'GET',
  credentials: 'include',
})

fetch('http://localhost:3300/sample', {
  method: 'GET',
  credentials: 'omit',
})

maxAge

maxAge を使用すると、同じリクエストに対してサーバーに不要なリクエストを防ぐための時間を指定します。

つまり、プリフライトリクエストは実際のリクエストを送信する前に送信されるリクエストで、サーバーがそのリクエストを処理できるかどうかを確認し、HTTP OPTIONS メソッドを使用します。

maxAge はキャッシュ時間を意味し、上記の例では 600 を入力したので、10 分間リクエストの結果を持っているので、10 分間は同じリクエストを送信できなくなります。

これにより、同じリクエストに対してサーバーに不要なプリフライトリクエストの数を減らすことができます。

ただし、maxAge を使用していても、クライアントはキャッシュを無視してプリフライトリクエストを引き続き送信することができます。