azureサーバーでwebsocket（socket.io）を動かす

azureサーバーでsocket.io使おうとしたらnode.js込みで色々大変だったので記録

##１環境
azure web apps
node.js(v4.0.0)
socket.io(v1.3.5)
とりあえず最小？環境で

##２azureサーバー
<img width="902" alt="スクリーンショット 2015-11-09 16.09.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/53020/730397c4-647c-4eef-3452-0fd14391853f.png">

アプリケーション設定でwebソケットをオンにする

##３デプロイするファイルの準備
サーバーにデプロイするフォルダのルートに
app.js(最初にこのファイルが読み込まれるっぽい。)
index.html(app.jsで読み込む場合)
web.config(以下のように用意)

```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を使う場合)


今回は[こちら](http://qiita.com/hosomichi/items/66b309a6c3c20d910218)のソースを改変したもので、チャットサーバーを起動してみる。

```javascript:app.js
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:index.html
<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でも動く

##４最後に
デプロイに関しては少々長ったらしいので[こちら](https://azure.microsoft.com/ja-jp/documentation/articles/web-sites-publish-source-control/)参照

何か間違いがあればお願いします