Node.jsにおいて、次のようなエラーメッセージがブラウザのコンソールに出て来ることがある。
このエラーはCORS(Cross-Origin Resouce Sharing)の設定をすると出なくなる。
このエラーはクライアントがhttp://192.168.2.100:80(htmlファイル)から、サーバー側のhttp://192.168.2.100:3000(Node.jsのjsファイル)にアクセスしようとすると、CORSの設定がないためにエラーになる。
クロスオリジン要求をブロックしました: 同一生成元ポリシーにより、http://192.168.2.100:3000/socket.io/?EIO=4&transport=polling&t=Oa-dgsr にあるリモートリソースの読み込みは拒否されます (理由: CORS ヘッダー ‘Access-Control-Allow-Origin’ が足りない)。ステータスコード: 200
このエラーが出るhtml,jsを次に示す。
client.html
<!DOCTYPE html>
<html lang="ja">
<head>
<title>Socket.io サンプルコード(1)~超簡易チャットアプリ~</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.1/socket.io.js"></script>
</head>
<body>
<h1>Socket.io サンプルコード(1)~超簡易チャットアプリ~</h1>
<input type="text" id="messageInput">
<button onclick="sendMessage()">送信</button>
<ul id="messageList"></ul>
<script>
//この処理でサーバーと通信をしているな。
const socket = io('http://192.168.2.100:3000');
// サーバーからのメッセージを受信
socket.on('message', (data) => {
// HTML内のID=messageList」を持つ要素を取得する。
const messageList = document.getElementById('messageList');
// 新しいli要素を作成する。li要素はメッセージをリストアイテムとして表示するために使用される。
const li = document.createElement('li');
// li要素のテキストコンテンツを受信したメッセージ(data)に設定する。
li.textContent = data;
// li要素をmessageList要素に追加する。これにより、受信したメッセージがリスト内に表示される。
messageList.appendChild(li);
});
// メッセージを送信
function sendMessage() {
// HTML内のID=messageInput」を持つ要素を取得する。
const messageInput = document.getElementById('messageInput');
// テキスト入力欄の値を変数messageに代入する。
const message = messageInput.value;
// テキスト入力欄の値を空文字にする。
messageInput.value = '';
// サーバーに対して message という名前のイベントを送信する。
// ここで message は任意の名前で、サーバー側で受け取る際にイベント名として使用される。
socket.emit('message', message);
}
</script>
</body>
</html>
server_http.js
CORS(Cross-Origin Resouce Sharing)の設定をコメントアウトするとブラウザのコンソールにエラーが出る。つまり、CORS(Cross-Origin Resouce Sharing)の設定をするとエラーが出なくなる。
const hostname = '192.168.2.100';
const port = 3000;
// httpモジュールをrequireを使ってインポートして変数httpに格納する。
const http = require('http');
// httpオブジェクトからcreateServerメソッドを実行する。
// http.createServer()の戻り値は、http.Serverのインスタンスである。
// つまり変数serverには、http.Serverのインスタンスが格納する。
const server = http.createServer();
// Socket.IOの初期化
// http://192.168.2.100:3000/socket.io/socket.io.jsにアクセス可能になる。
const io = require('socket.io')(server,{
// CORS(Cross-Origin Resouce Sharing)の設定
/*
cors: {
// コメントアウトしても正常に動く。
// コメントアウトしたら、origin: '*'と同じ設定になる。
origin: ['http://localhost', 'http://127.0.0.1','https://localhost', 'https://127.0.0.1','http://192.168.2.100','https://192.168.2.100'],
//全てのURLを指定するときは*を使う。
//origin: '*',
},
*/
});
// サーバーは指定したポートとホストで接続を待ち受け、クライアントからのリクエストを聞いて受け付ける状態になる。
// ここでの「listen」は文字通り「接続の待ち受け」や「受信を聴く」という意味で使われている。
server.listen(port, hostname,() => {
console.log(`Server running at http://${hostname}:${port}/`);
});
// クライアント側で socket.emit('message', message);
// を実行すると、サーバーの io.on('message', ...) で定義された
// コールバック関数が呼び出され、クライアントからのメッセージが受信される。
io.on('connection', (socket) => {
console.log('クライアントが接続しました');
// クライアントからのメッセージを受信
// クライアント側で socket.emit('message', message); を実行すると、
// サーバー側で定義された socket.on('message', ...) のコールバック関数
// が実行されるという流れになります。
socket.on('message', (data) => {
console.log('クライアントからのメッセージ:', data);
// 受信したメッセージを全クライアントに送信
// クライアント側でsocket.emit('message', message);を実行した人も含めて送る。
io.emit('message', data);
});
// クライアントとの接続が切断されたときの処理
socket.on('disconnect', () => {
console.log('クライアントが切断しました');
});
});
クロスオリジン(Cross Origin)とは何か?
オリジン =情報源=source=URLと覚えておけば良い。
「クロスオリジン(Cross-Origin)」という用語は、直訳すると「情報源が交差する」という意味になり、異なるオリジン間の制約や制限が交差することを指おり、実際には異なるオリジン間の制約を指す言葉として使用されている。
異なるオリジン間では、ブラウザのセキュリティポリシーによってさまざまな制約が適用される。これにより、異なるオリジン間のリソース共有や通信が制限され、セキュリティ上の脆弱性や悪意のある攻撃を防止することができる。
異なるオリジン間での情報の交換やリクエストの送信には、クロスオリジンリクエストやCORS(Cross-Origin Resource Sharing)などの設定を使用する必要がある。これにより、ブラウザは適切な制約を適用し、セキュリティを維持しながら異なるオリジン間の通信を行うことができる。
したがって、「クロスオリジン」という用語は、異なるオリジン間の制約や制限が交差することを表現するために使用される。
つまり、「クロスオリジン」自体がエラーを示すわけではない。
サーバーサイドのNode.jsのCORSの設定は、クロスオリジンリクエストを許可するための設定である。この設定はブラウザによって制限されるセキュリティポリシーを回避するためのものである。
異なるオリジンはとは、プロトコル(http、https)、ホスト名、およびポート番号が異なる場合に成立する。つまり、IPアドレスやホスト名が同じでも、ポート番号やプロトコル(httpかhttps)が異なる場合は異なるオリジンと見なされる。