カードゲーム対戦サーバ構築への道 1 -リバースプロキシ nginxとNode.jsを繋げる-


2024年12月21日
早急に書き上げる必要のあった「EU周遊記」シリーズが終わり、ものづくりへと戻ります。
まえがき
現在、私は最終的にアナログ形式になるカードゲームの制作を行っております。
この飛行物体の実験室には別館が存在しており、リアルタイム通信など動的なことはそちらで行うことにしています。
私の作品の「棒人間バトル」が現在稼働しているのが別館サーバです。
新たにこのサーバに「カードゲームをプレイできるようなP2P型サーバ」を構築するのが本シリーズの目的です。
今考えている問題、やりたいこと
現在、私のサーバ上には入口となるnginxサーバと、webアプリを動作させるNode.jsサーバが動いています。
nginx は http ないし https による接続となっているため、80番ポートと443番ポートは埋まっています。
なので、Node.jsサーバはこの2つのポートを利用できません。
このため、Node.jsサーバーは「別のポート」でアプリが立ち上がっています。
nginxのサーバにアクセスするにはドメイン"https://flying-object-works.com"をブラウザ上部のアドレスバーにダイレクトに入力すればアクセスできます。
Node.jsのサーバにアクセスするには"https://flying-object-works.com:xxxx(ポート番号)"です。
(nginx側はまともなコンテンツは置いていないので、アクセスは推奨しません)
これではNode.js側のアプリのポートが丸わかりであり、文字列上の見栄えもよくありません。
ルーティングという面から見ても不便です。
なので、"https://flying-object-works.com/stick-battle"と入力すれば、Node.js側にアクセスできるようにリバースプロキシの機能を使います。
nginxのリバースプロキシ
nginxのルート設定ファイル「nginx.conf」にプロキシサーバーの設定を行うことで、橋渡し自体は行えます。
nginx.conf -> httpモジュール -> serverモジュール と来て、この中に以下のような記述を行います。
# serverモジュール は httpモジュールの中に書く server{ server_name flying-object-works.com; location / { root /xxxx; # ルートディレクトリ(ルートフォルダ)の指定 index index.html; # ルートファイルの指定 } # プロキシの設定 location /stick-battle { proxy_pass https://localhost:xxxx(ポート番号); # 橋渡し先の指定 } # ここにssl用設定を記述する }
これで、"https://flying-object-works.com/stick-battle"が"https://flying-object-works.com:xxxx(ポート番号)"へ繋がりました。
実際、htmlないしjsのファイルへの橋渡しはできるのですが、socket.ioからCORSエラーが吐かれます。
(リアルタイム通信機能が遮断される)
CORSエラー
CORSエラーとは、ブラウザのポリシーによる制限に引っかかっていることにより発生するエラー[1]です。
CORS は Cross-Origin Resource Sharing の略称であり、異なるオリジンによるアクセスのことです。これを制限している機能に今回引っかかっています。
要するに、セキュリティ上の対策を目的としたポリシーに引っかかっています。
オリジンとは、プロトコル(スキーム)・ホスト(ドメイン)・ポートで定義されるもの[2]です。
今回の場合は "https://flying-object-works.com"と"https://flying-object-works.com:xxxx(ポート番号)"です。
この問題を回避するため、socket.ioを利用しているNode.js用のコードを2つのオリジンに対応するよう修正します。
Node.jsサーバ・クライアントの設定
error484さんのQiitaの記事内容を参考[3]にし、Node.jsサーバのコードを以下のようにします。(express, socket.io等がインストール済であることを想定しています)
'use strict';
require('dotenv').config();
// express, socket.io の読込
const express = require('express');
const https = require('https');
const socketIO = require('socket.io');
const options = {
key: fs.readFileSync('ssl用鍵のファイルパス'),
cert: fs.readFileSync('ssl用鍵のファイルパス')
}
const app = express();
const server = https.createServer(options, app);
const socketOptions = {
// cors要素に許可するオリジンを指定
cors: {
origin: ["https://flying-object-works.com","https://flying-object-works.com:xxxx(ポート番号)"],
credentials: true
}
};
const io = socketIO(server, socketOptions);
/* 以下サーバの処理 */
これで、2つのオリジンのどちらからアクセスしてもリアルタイムの通信が起動できるようになりました。
実際に"https://flying-object-works.com/stick-battle"にアクセスすると上手く動いていることが分かると思います。
まとめ・次回予告
リバースプロキシを設定してnginxとNode.jsのサーバをつなぐことができました。
次回はP2Pの基幹技術を利用した簡易サーバの立ち上げを行おうと思います。
参考
[1]:Qiita@higakin(y h): CORSエラーってなに?どうすれば解決するの?