nginxを挟んでsocket.ioのxhr-pollingを動かすには - すぎゃーんメモ
で調べた通り、現在 nginx+socket.io 0.7系のhttp-pollingが繋がらないようになっていて、DotCloudがまさにそういう環境なので、試してみた。
ちなみに後から知ったのだけど、このあたりについては随分前から既に議論されていたようで。
0.7 doesn't work on Dotcloud, but 0.6.18 does. · Issue #301 · socketio/socket.io · GitHub
動かないパターン
http://docs.dotcloud.com/services/nodejs/を読みつつ、プロジェクトを作って設定ファイルなど作成。
依存モジュールごと全部アップロードして使うことも出来てしまうようだけど、ここでは敢えてそれをせずにpackage.jsonによる自動依存解決に任せる。
{ "name": "sugyan", "version": "0.0.1", "private": true, "dependencies": { "express": ">=2.4.4", "socket.io": ">=0.7.9", "ejs": ">=0.4.3" } }
こんなかんじで書いておくと、dependenciesに書いたものがdeploy時に自動的にインストールされて起動される。
で、こんなかんじの普通のWebAPP+Socket.IOのサーバを書いて動かしてみる。
var express = require('express'); var sio = require('socket.io'); var app = express.createServer(); app.set('view engine', 'ejs'); app.use(express['static'](__dirname + '/public')); app.get('/', function (req, res) { res.render('index'); }); app.listen(8080); var io = sio.listen(app); io.set('transports', ['xhr-polling']); io.sockets.on('connection', function (socket) { setInterval(function () { socket.send('hoge'); }, 1000); });
deployしてアクセスしてみても、やはり繋がらない。前述の記事と同じ問題が起きている模様。
無理矢理動かす
ということで、以下のように無理矢理xhr-pollingのdoWriteメソッドの部分だけ書き換えてみる。headersに"Keep-Alive"を書かないようにするだけ。
var express = require('express'); var sio = require('socket.io'); var app = express.createServer(); app.set('view engine', 'ejs'); app.use(express['static'](__dirname + '/public')); app.get('/', function (req, res) { res.render('index'); }); app.listen(8080); var io = sio.listen(app); io.set('transports', ['xhr-polling']); io.sockets.on('connection', function (socket) { setInterval(function () { socket.send('hoge'); }, 1000); }); var path = require('path'); var HTTPPolling = require(path.join(path.dirname(require.resolve('socket.io')), 'lib', 'transports', 'http-polling')); var XHRPolling = require(path.join(path.dirname(require.resolve('socket.io')), 'lib', 'transports', 'xhr-polling')); XHRPolling.prototype.doWrite = function (data) { HTTPPolling.prototype.doWrite.call(this); var origin = this.req.headers.origin, headers = { 'Content-Type': 'text/plain; charset=UTF-8', 'Content-Length': data === undefined ? 0 : Buffer.byteLength(data) }; if (origin) { // https://developer.mozilla.org/En/HTTP_Access_Control headers['Access-Control-Allow-Origin'] = '*'; if (this.req.headers.cookie) { headers['Access-Control-Allow-Credentials'] = 'true'; } } this.response.writeHead(200, headers); this.response.write(data); this.log.debug(this.name + ' writing', data); };
こうすることで、一応0.7系のSocket.IOでもDotCloud上でxhr-polling使って繋げられるようになる。
全然良い解決策とは思えないけど。
余談
今回検証するにあたって色々試そうとしてたらpackage.jsonからの依存解決がうまく動いていなかったりして、拙い英語でsupport forumに投げてみたりした。
https://dotcloud.zendesk.com/entries/20347516-how-run-npm-install-in-node-js-application
色々調べて丁寧に対応していただき、無事に直ったようです。とりあえず言ってみるもんですね!