title: Websockets on Tomcat 8 + IIS 8 with ARR 3 are not working
body: <p>I've scoured the internet trying to find anyone who might be experiencing this issue but come up empty handed. So here goes:</p>
  
  <p>We have a java web application (based on Spring MVC 4). It sits behind Microsoft IIS acting as a load balancer / reverse proxy using Application Request Routing (ARR) v3.</p>
  
  <p>This IIS is performing load balancing with ARR for 3 different environments (all running the <strong>same</strong> Java code): <code>dev.example.com</code>, <code>demo.example.com</code> and <code>qa.example.com</code>.</p>
  
  <p>The application serves notifications to users' browsers using WebSockets via SockJS and stompjs and this has all been working well while the application servers were on Tomcat 7. After upgrading the <code>qa.example.com</code> environment to Tomcat 8, the WebSocket connections stopped working - it falls back to XHR POST requests.</p>
  
  <p>I want to stress that no changes were made to IIS, just the <code>qa</code> application server.</p>
  
  <p><strong>Here is a sample request/response from the <code>dev</code> environment (working):</strong></p>
  
  <pre><code>Accept-Encoding: gzip, deflate, sdch
  Accept-Language: en-US,en;q=0.8
  Cache-Control: no-cache
  Connection: Upgrade
  Cookie: &lt;cookies snipped&gt;
  Host: dev.example.com
  Origin: https://dev.example.com
  Pragma: no-cache
  Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
  Sec-WebSocket-Key: E7aIek0X6qcO9PAl1n6w4Q==
  Sec-WebSocket-Version: 13
  Upgrade: websocket
  User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36
  </code></pre>
  
  <p>Response</p>
  
  <pre><code>Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  Connection: Upgrade
  Date: Thu, 22 Oct 2015 02:19:35 GMT
  Expires: 0
  Pragma: no-cache
  Sec-WebSocket-Accept: dKYK05s4eP87iA20aSo/3ntOrPU=
  Server: Microsoft-IIS/8.0
  Strict-Transport-Security: max-age=31536000 ; includeSubDomains
  Upgrade: Websocket
  X-Content-Type-Options: nosniff
  X-Frame-Options: DENY
  X-Powered-By: ARR/3.0
  X-XSS-Protection: 1; mode=block
  </code></pre>
  
  <p><strong>Here is a sample request/response from the <code>qa</code> environment (broken):</strong></p>
  
  <pre><code>Accept-Encoding: gzip, deflate, sdch
  Accept-Language: en-US,en;q=0.8
  Cache-Control: no-cache
  Connection: Upgrade
  Cookie: &lt;cookies snipped&gt;
  Host: qa.example.com
  Origin: https://qa.example.com
  Pragma: no-cache
  Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
  Sec-WebSocket-Key: jTOIAT0+o35+Qi0ZWh2gyQ==
  Sec-WebSocket-Version: 13
  Upgrade: websocket
  User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36
  </code></pre>
  
  <p>Response:</p>
  
  <pre><code>Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  Connection: Upgrade
  Date: Thu, 22 Oct 2015 02:18:30 GMT
  Expires: 0
  Pragma: no-cache
  Sec-WebSocket-Accept: P+fEH8pvxcu3sEoO5fDizjSbwJc=
  Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
  Server: Microsoft-IIS/8.0
  Strict-Transport-Security: max-age=31536000 ; includeSubDomains
  Upgrade: Websocket
  X-Content-Type-Options: nosniff
  X-Frame-Options: DENY
  X-Powered-By: ARR/3.0
  X-XSS-Protection: 1; mode=block
  </code></pre>
  
  <p>The only obvious difference is that the <code>qa</code> response includes a <code>Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15</code> header while the <code>dev</code> response does not.</p>
  
  <p>I turned on "Failed Request Tracing" on IIS to debug the <code>101</code> response and I can see that there are some headers that get overwritten by IIS - the <code>Sec-WebSocket-Accept</code> header namely.</p>
  
  <p>IIS also shows that that request is creating a <code>502.5</code> error. I looked that up and found this: <a href="https://support.microsoft.com/en-us/kb/943891" rel="noreferrer">https://support.microsoft.com/en-us/kb/943891</a> which says that <code>502.5</code> is "WebSocket failure (ARR)" and that's all it says. Weirdly enough though, Chrome Dev Tools shows that it responds with a 101 just like it's supposed to...</p>
  
  <p>I tried this all with a local application server (Tomcat 8 with no IIS) and the websockets worked just fine. Tomcat 7 + IIS + ARR + WebSockets works just fine. Tomcat 8 + IIS + ARR + WebSockets does not.</p>
  
  <p>My exact version of Tomcat 8 is 8.0.28 - but I got the same results on Tomcat 8.0.26.</p>
  
  <p>My next step it to keep downgrading Tomcat 8 through minor versions and see if anything changes. I will update here if I discover anything.</p>
  
  <h1>Update</h1>
  
  <p>Here's a response from my local server (no IIS):</p>
  
  <pre><code>Cache-Control: no-cache, no-store, max-age=0, must-revalidate
  Connection: upgrade
  Date: Thu, 22 Oct 2015 13:59:23 GMT
  Expires: 0
  Pragma: no-cache
  Sec-WebSocket-Accept: 718HnPxHN8crYYzNGFjQf7w8O+Y=
  Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
  Server: Apache-Coyote/1.1
  Strict-Transport-Security: max-age=31536000 ; includeSubDomains
  Upgrade: websocket
  X-Content-Type-Options: nosniff
  X-Frame-Options: DENY
  X-XSS-Protection: 1; mode=block
  </code></pre>
  
  <p>It looks a lot like the broken <code>qa</code> request, but it works great. So I guess the <code>Sec-WebSocket-Extensions</code> thing was a red herring. Also <code>Upgrade: websocket</code> and <code>Connection: upgrade</code> is lower case on my local server, whereas it is <code>Websocket</code> and <code>Upgrade</code> when you put IIS in front.</p>
  
  <p><code>Sec-WebSocket-Extensions</code> also has a trailing space in <code>qa</code> after the <code>permessage-deflate;</code> but the local does not.</p>
  
  <h1>Update 2</h1>
  
  <p>It all works fine on the <code>qa</code> environment in Microsoft Edge (Windows 10) I haven't tried Internet Explorer 11, but I have to assume it probably also works. Firefox and Chrome on OSX do not work.</p>
  
  <h1>Update 3</h1>
  
  <p>Request from Tomcat before it gets modified by IIS/ARR:</p>
  
  <pre><code>HTTP/1.1 101 Switching Protocols
  Server: Apache-Coyote/1.1
  Upgrade: websocket
  Connection: upgrade
  Sec-WebSocket-Accept: luP49lroNK9qTdaNNnSCLXnxAWc=
  Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
  Date: Tue, 27 Oct 2015 21:10:48 GMT
  </code></pre>