LoginSignup
37

More than 5 years have passed since last update.

Nginxを使用して、配信したHTMLと同一のポート番号で、socket.ioに接続できるようにする。

Last updated at Posted at 2014-07-29

RailsやFlaskで実装したWebアプリケーションで、socket.ioを使ったチャット機能を追加する場合、
それらのアプリケーションで配信したHTMLに、socket.ioのスクリプトをロードして使う必要がありますが、
socket.ioが起動しているポートをHTMLに記述しなければなりません。

Production環境では、余計なポートを開放したくないので、クライアントからsocket.ioに接続する場合、
Webアプリケーションと同じポートで接続できるようにしたいところです。
前面にNginxをたてて、socket.ioのプロキシとして動作させれば実現できそうです。

前提

  • Webアプリケーションは、ポート80でアクセス可能
  • socket.ioは、ポート3000で起動
  • Nginxは出来るだけ最新のバージョンを使用(v1.6とか)

手順

  1. Webアプリケーションも、socket.ioもNginx経由で、クライアント(Webブラウザ)から接続できるようにする。
  2. path:/socket.io/にアクセスがあったら、起動しているsocket.ioのURLに転送する。(Proxy)

Nginxの設定

/socket.io/にアクセスがあったら、socket.ioに転送するだけです。

// app.conf
upstream io_nodes {
    ip_hash;
    // 起動しているsocket.ioの接続先URL
    server 127.0.0.1:3000;
}

server {
    listen 80;
    server_name foo.docker.dev;

    // Webアプリケーション側
    location / {
        uwsgi_pass  unix:///tmp/uwsgi.sock;
        include     uwsgi_params;
        client_max_body_size 20M;
    }

    // Webブラウザからsocket.ioにアクセスする際のパス`/socket.io/`だった場合、socket.ioに転送(Proxy)
    location /socket.io/ {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_pass http://io_nodes;
    }
}

HTML

Nginxの設定ができていれば、<script>タグで、socket.ioのスクリプトを読み込むのも、初期化するのもホスト名、ポート番号などを書かなくて良くなります。
また、Iptablesなどで、socket.io用のポートは開放する必要はなくなります。

<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io();

  socket.on('connect', function(msg) {
    console.log(msg);
  });
  socket.on('chat message', function(msg) {
    alert(msg);
  });
  socket.on('test message', function(msg) {
    console.log(msg);
  });
</script>

追記

ただ、開発環境でnginxを立ててとかやるのは、めんどくさいので、直接socket.ioにも接続できるようにしたい場合は、
Webアプリケーション側で開発時にだけ、socket.ioの接続先URLを変数か何かに格納しておけばよいでしょう。

<script id="socketIO" src="{{ IO_DIRECT_URL or '' }}/socket.io/socket.io.js"></script>
<script>
  var url;
{%- if IO_DIRECT_URL -%}
  url = {{ IO_DIRECT_URL|tojson|safe }};
{%- endif -%}

  var socket = io(url ? url : undefined);
  socket.on('connect', function(msg) {
    console.log(arguments);
    console.log(msg);
  });
  socket.on('chat message', function(msg) {
    alert(msg);
  });
  socket.on('test message', function(msg) {
    console.log(msg);
  });
</script>

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37