I think I have figured out the cause of this. It has to do with way IIS + ARR handles the request, but does not appear to be related to the special path used in 10.6 for internal requests.
The issue seems to be with the Sec-WebSocket-Extensions header, for which Chrome and Firefox pass in a value of permessage-deflate. IIS + ARR passes through this header to the back-end, and the upgraded version of Jetty appears to handle this extension, but it appears IIS + ARR does not know what to do with it.
So, I added a rule to look for all requests with the Upgrade: websocket header, and strip out any Sec-WebSocket-Extensions header (actually, replace with a ";", which has the same effect) and it was then able to connect.
A few notes:
- The rule needs to come before your actual rewrite rules that redirect to the proxy. It can have Action: None and should not Stop processing other rules (or else it will never get to your actual rewrite rule).
- It is not necessary to add HTTP_SEC_WEBSOCKET_EXTENSIONS to the Allowed Server Variables to make this work, as long as the rule is defined within the Global Rules set (i.e. together with the ARR rewrite rules). You can if you want, but you don't need to.
- The rule could be restricted to specific URLs, e.g. if there are other WebSockets on the same server that are not proxied to GeoEvent and do not require this treatment. In my case I allowed it for all requests that contain the Upgrade request header and a non-blank Sec-WebSocket-Extensions request header.
- If the Sec-WebSocket-Extensions header included any other extensions that we wanted to pass through, they would also be lost. This could be prevented by looking for a Sec-WebSocket-Extensions header that contains the permessage-deflate extension specifically, and retaining everything except permessage-deflate. This is not hard to do via regular expressions and back-references. But then what if some other extension gets requested by browsers in the future that IIS + ARR also does not support? I figure it's better to strip out all extensions, for all WebSocket requests that get proxied by IIS, for maximum compatibility.
- The header could also have been rewritten within the same rewrite rule that forwards to the server farm; it didn't need to be a separate rule. I just found it easier and cleaner for our environment to define it that way.
Since this works, I can only assume that NGINX does not pass through this header at all, or else knows how to deal with per-message-deflated content, which might be why the issue was not detected in Esri's in-house testing, which I understand is primarily with NGINX.
Screen shot attached...