azureサーバーでsocket.io使おうとしたらnode.js込みで色々大変だったので記録
1環境
azure web apps
node.js(v4.0.0)
socket.io(v1.3.5)
とりあえず最小?環境で
2azureサーバー

アプリケーション設定でwebソケットをオンにする
3デプロイするファイルの準備
サーバーにデプロイするフォルダのルートに
app.js(最初にこのファイルが読み込まれるっぽい。)
index.html(app.jsで読み込む場合)
web.config(以下のように用意)
<?xml version="1.0" encoding="utf-8"?>
<!--
This configuration file is required if iisnode is used to run node processes behind
IIS or IIS Express. For more information, visit:
https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config
-->
<configuration>
<system.webServer>
<!-- Visit http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx for more information on WebSocket support -->
<webSocket enabled="false" />
<handlers>
<!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
<add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<!-- Do not interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^server.js\/debug[\/]?" />
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<!-- All other URLs are mapped to the node.js site entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="server.js"/>
</rule>
</rules>
</rewrite>
<!-- 'bin' directory has no special meaning in node.js and apps can be placed in it -->
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<!-- Make sure error responses are left untouched -->
<httpErrors existingResponse="PassThrough" />
<!--
You can control how Node is hosted within IIS using the following options:
* watchedFiles: semi-colon separated list of files that will be watched for changes to restart the server
* node_env: will be propagated to node as NODE_ENV environment variable
* debuggingEnabled - controls whether the built-in debugger is enabled
See https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config for a full list of options
-->
<!--<iisnode watchedFiles="web.config;*.js"/>-->
</system.webServer>
</configuration>
参照:http://www.hanselman.com/blog/EnablingWebsocketsForSocketioNodeAppsOnMicrosoftAzure.aspx
どうやらIISが動いて邪魔するみたいなのでそれを無視して、node.jsを動かせ的な感じ?らしい
(これがなくてもnode.jsは動く。あくまでwebsocketを使う場合)
今回はこちらのソースを改変したもので、チャットサーバーを起動してみる。
var fs = require('fs');
var port = process.env.PORT || 8000;
var server = require('http').createServer(function(req,res){
res.writeHead(200,{'Content-Type':'text/html'});
var output = fs.readFileSync('./index.html','utf-8');
res.end(output);
}).listen(port);
var io = require('socket.io').listen(server);
var userHash = {};
io.sockets.on('connection',function(socket){
socket.on('connected',function(name){
var msg = name + 'が入室しました';
userHash[socket.id] = name;
io.sockets.emit('publish',{value:msg});
console.log('connected');
});
socket.on('publish',function(data){
io.sockets.emit('publish',{value:data.value});
});
socket.on('disconnect',function(){
if(userHash[socket.id]){
var msg = userHash[socket.id] + 'が退出しました';
delete userHash[socket.id];
io.sockets.emit('publish',{value:msg});
}
});
});
改変点としては
var port = process.env.PORT || 8000
デプロイした環境ではprocess.env.PORTが動いて勝手にどうにかしてくれるらしい。
ローカル環境では勝手に8000が動くようになってるので、ここは各自自分のポートにすればおk
ついでにfs.readFileSync();には動かしたいファイルのパスを入力
./は現在のディレクトリ、一応
<html>
<head>
<meta charset='utf-8'>
<title>socket.io</title>
</head>
<body>
<input type='text' id='msg_input' style='width:200px;'/>
<button onclick='publishMessage();'>ツイート</button>
<div id='msg'></div>
<script src='./socket.io/socket.io.js'></script>
<script type='text/javascript'>
var socketio = io();
socketio.on('connected',function(name){});
socketio.on('publish',function(data){addMessage(data.value);});
socketio.on('disconnect',function(){});
function start(name){
socketio.emit('connected',name);
}
function publishMessage(){
var textInput = document.getElementById('msg_input');
var msg = '[' + myName + ']' + textInput.value;
socketio.emit('publish',{value:'hage'});
textInput.value = '';
}
function addMessage(msg){
var domMeg = document.createElement('div');
domMeg.innerHTML = new Date().toLocaleTimeString() + ' ' + msg;
msgArea.appendChild(domMeg);
}
var msgArea = document.getElementById('msg');
var myName = Math.floor(Math.random() * 100) + 'さん';
addMessage('あなたは' + myName + 'として入室しました');
start(myName);
</script>
</body>
</html>
こちらの改変点は
var socket.io = io();
とりあえずこうすればローカルでもazureでも動く
4最後に
デプロイに関しては少々長ったらしいのでこちら参照
何か間違いがあればお願いします