Fetch と CORS

概要: このチュートリアルでは、CORS (Cross-Origin Resource Sharing) について、また、あるオリジンがデータを取得できるようにWebサーバーを設定する方法について説明します。

オリジンとは

オリジンとは、次の3つの要素のユニークな組み合わせを指します。

  • プロトコル (スキーム): URLで指定されたプロトコル(HTTPHTTPSFTPSなど)
  • ドメイン (ホスト): ドメイン名またはIPアドレス(javascripttutorial.net127.0.0.1 など)
  • ポート: Webサーバーとの通信に使用されるポート番号。ポートを指定しない場合、プロトコルのデフォルトポートが使用されます。例: HTTPS の場合はポート 443HTTP の場合はポート 80

例えば、https://javascripttutorial.dokyumento.jp/api/ は、以下のオリジンです。

  • HTTPS がプロトコル。
  • www.javascriptttorial.net がドメイン名。
  • 443HTTPS プロトコルのデフォルトポート。

https://api.javascripttutorial.net/ は、ドメイン名 api.javascripttutorial.netwww.javascripttutorial.net と異なるため、別のオリジンです。

オリジンは、WebブラウザがCORSとして知られるセキュリティポリシーを適用するために重要です。

CORSとは

CORS (Cross-Origin Resource Sharing) は、Webブラウザのセキュリティ機能で、あるオリジンから別のオリジンへの不正なリクエストを防ぎます。

ブラウザは、サイトが自身のオリジンに対してHTTPリクエストを行うことを許可します。しかし、そのサイトが異なるオリジン (クロスオリジン) をリクエストしようとすると、クロスサイトスクリプティング (XSS) 攻撃のようなセキュリティリスクから保護するために、ブラウザはデフォルトでこのアクションをブロックします。

CORSがどのように機能するかをよりよく理解するために、例を見てみましょう。

簡単なWebサーバーの設定

Node.jsで簡単なExpress Webサーバーを設定します。

ステップ1. プロジェクトファイルを保存するための新しいディレクトリを作成します

mkdir webserver
cd webserverCode language: JavaScript (javascript)

ステップ2. ターミナルで npm init コマンドを実行してプロジェクトを初期化します

npm init --yesCode language: JavaScript (javascript)

このコマンドは、プロジェクトディレクトリにpackage.jsonファイルを作成します。

ステップ3. express パッケージをインストールします

npm install expressCode language: JavaScript (javascript)

ステップ4. type : "module" を追加して package.json を設定します

"type": "module"Code language: JavaScript (javascript)

これにより、Node.js プロジェクトでES6 モジュールを使用できるようになります。

また、script セクションも変更します

"scripts": {
    "start": "node index.js"
}Code language: JavaScript (javascript)

scripts セクションを変更することで、ターミナルで npm start コマンドを実行して index.js ファイルを実行できるようになります。

ステップ5. 次のコードで index.js という名前の新しいファイルを作成します

import express from 'express';
const app = express();

app.get('/', (req, res) => {
  res.send('Hello, World!');
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});Code language: JavaScript (javascript)

index.js ファイルでは、http://localhost:3000/ というルートへの GET リクエストを受け付け、'Hello, World!' というメッセージを返す Express Web サーバーを作成します。

ステップ6. ターミナルで次のコマンドを実行してWebサーバーを起動します

npm start

ステップ7. Webブラウザで http://localhost:3000/ を開くと、JSONレスポンスが表示されます

{
  "message": "Hello, World!"
}Code language: JavaScript (javascript)

JavaScriptアプリの作成

fetch() メソッドを使用して、APIエンドポイント http://localhost:3000/ を呼び出す簡単なJavaScriptアプリを作成します。

ステップ1. JavaScriptアプリファイルを保存するための新しいディレクトリを作成します

mkdir app
cd app

ステップ2. index.html ファイルを作成します

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Fetch API - CORS</title>
    </head>

    <body>
        <button id="btn">Fetch</button>
        <p id="message"></p>
        <script src="app.js"></script>
    </body>

</html>Code language: HTML, XML (xml)

index.html ファイルには、同じディレクトリ内の app.js が含まれています。

ステップ3. プロジェクトディレクトリに app.js ファイルを作成します

const btn = document.getElementById('btn');
const messageElem = document.getElementById('message');

btn.addEventListener('click', async () => {
  // reset the message
  messageElem.innerHTML = '';
  try {
    // call the API
    const response = await fetch('http://localhost:3000/');
    const data = await response.json();

    // update the message
    messageElem.innerHTML = data.message;
  } catch (err) {
    messageElem.innerHTML = err.message;
  }
});Code language: JavaScript (javascript)

ステップ4. index.html を開き (VS codeでライブサーバー拡張機能を使用)、Fetchボタンをクリックすると、メッセージが表示されます。

Failed to fetchCode language: JavaScript (javascript)

コンソールウィンドウを開くと、次のエラーメッセージが表示されます

Access to fetch at 'http://localhost:3000/' from origin 'http://127.0.0.1:5501' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.Code language: JavaScript (javascript)

理由は、オリジン http://127.0.0.1:5501 からオリジン http://localhost:3000/ のサーバーにHTTPリクエストを行っており、ブラウザがそれをブロックするためです。

WebサーバーでCORSを有効にする

ステップ1. ターミナルを開き、Node.js プロジェクトに cors パッケージをインストールします

npm install corsCode language: JavaScript (javascript)

ステップ2. すべてのオリジンからのCORSを有効にするように index.js ファイルを変更します

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

const app = express();

app.use(cors());

app.get('/', (req, res) => {
  res.send({ message: 'Hello, World!' });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});Code language: JavaScript (javascript)

仕組み。

まず、cors パッケージから cors 関数をインポートします。

import cors from 'cors';Code language: JavaScript (javascript)

次に、cors() 関数を呼び出し、その戻り値を app.use() メソッドに渡します

app.use(cors());Code language: JavaScript (javascript)

このコード行は、Express Webサーバーに、すべてのオリジンからAPIエンドポイントを呼び出すことを許可するHTTP応答のヘッダーに次のエントリを追加するように指示します。

Access-Control-Allow-Origin: *Code language: JavaScript (javascript)

アスタリスク (*) は、任意のオリジンを意味します。

ステップ3. Webサーバーを停止 (Ctrl-Cを押す) してから再び起動して、再起動します

npm start

ステップ4. JavaScriptアプリでFetchボタンをクリックします。Webブラウザに Hello, World! メッセージが表示されます。

Hello, World!Code language: JavaScript (javascript)

HTTP応答のヘッダーを調べると、次のエントリが表示されます。

Access-Control-Allow-Origin: *Code language: JavaScript (javascript)

cors() 関数に http://127.0.0.1:5501 などの特定のオリジンを追加することで、Webサーバーを特定のオリジンからのCORSを許可するように設定できることに注意してください。

// ...

app.use(
  cors({
    origin: 'http://127.0.0.1:5501',
  })
);
//  ...Code language: JavaScript (javascript)

ブラウザによって送信されるオリジンに末尾のスラッシュ (/) が含まれない場合があるため、オリジンに末尾のスラッシュ (/) は含まれないことに注意してください。

この場合、Webサーバーは、HTTP応答のヘッダーに次のエントリを追加します

Access-Control-Allow-Origin: http://127.0.0.1:5501/Code language: JavaScript (javascript)

プロジェクトのソースコードをダウンロード

ここをクリックしてプロジェクトのソースコードをダウンロードしてください

zipファイルを解凍すると、次の2つのディレクトリが表示されます

  • webserver
  • app

Webサーバーを起動するには、次の手順を実行する必要があります

まず、webserver ディレクトリに移動します

cd webserver

次に、npm install コマンドを実行して依存関係をインストールします

npm install

3番目に、Webサーバーを起動します

npm start

概要

  • オリジンは、ドメイン、プロトコル、およびポートの3つの要素の組み合わせによって定義されます。
  • CORS (Cross-Origin Resource Sharing) は、Webブラウザに組み込まれたセキュリティ機能で、デフォルトでは、あるオリジンが異なるオリジンへのリクエストを行うことを防ぎます。
  • すべてのオリジンからのリクエストを許可するには、HTTP応答にヘッダー Access-Control-Allow-Origin: * を含めるようにWebサーバーを設定します。
このチュートリアルは役に立ちましたか?