Nodejs+socket.io+nginx+ssl+IE = en omöjlig kombination
Vi har nyligen utvecklat ett ganska intressant projekt där vi använt nodejs med socket.io för websockets, satt allt bakom nginx och behövt köra allt under https. Allt har funkat 100% men, för så klart måste det finnas ett men, när man till slut har fått allt att fungera så funkar inte IE.


Efter lite tester kunde vi konstatera att det funkade bra och körde igång att producera en sajt som innehåll det mesta: vanliga hederliga ajax requests med ett REST API, ganska mycket event baserat javascript och så en dos realtid websocketkommunikation (min favorit). Eftersom IE inte klarar av sockets så kunde vi förlita oss på socket.io, som hittar andra sett att simulera det hela (long poll etc etc). Allt såg alltså bra ut i våra tester och vi var glada.
Vi visste dessutom att nginx inte kan hantera http 1.1 internt, vilket krävs för att websockets ska fungera genom det. Anledningen till att man vill kunna köra websockets via nginx är att man i princip kan säga att urlen http://www.foo.com/ ska hanteras som en vanlig http server men att man kanske vill att http://www.foo.com/socket ska hantera med websockets. Snygg och prydligt och nginx fixar resten. Men som sagt, i nu läget är det mest en önskan eftersom det inte fungerar.
I vanliga fall är det enkelt att lösa. Låt nginx hantera alla vanliga request i port 80 och skicka dem vidare till nodejs appen som sitter internt på en annan port, tex 8080. Men om man kommunicerar direkt med 8080 så har man kontakt med websocketdelen. Det kanske inte är lika snyggt men det funkar.
När väl allt detta är på plats så testade vi allt på rätt server med SSL och allt funkar perfekt.
Men, för så klart måste det finnas ett men, när man till slut har fått allt att fungera så funkar inte IE. Det som händer är att IE inte fixar websockets, vilket gör att den kanske kör med xhr-polling, dvs kommunicerar via vanliga http requests. Och eftersom man är tvungen att kommunicera direkt via en annan port än port 80, så anser IE (helt rätt) att man kommunicerar med ett annat domän. Och det får man inte göra om man använder https. Alltså får man "access denied" i javascripten.
Vi har alltså en specifik situation med många variabler gör att just den delen inte fungerar? Vad gör man då?
- Skriver man om websocketdelarna till vanlig ajax? Nej, det skulle kännas som ett stort nederlag.
- Kollar man om nginxs instabila versioner har stöd för websockets (http 1.1) internt? Ja, man kollar och testar men det funkar inte.
- Till slut så hittade jag någon som helt enkelt tog bort äkta websocket som alternativ från socket.io och ändrade så att man inte behöver http 1.1 (dvs ta bort headern "connection: keep-alive"). Och tur för mig att trixet skrevs för fyra dagar sedan. Det trista är naturligtvis att vi tappar äkta websockets, men för användaren är det (nästan) ingen skillnad.
Så efter ändringar config filerna för nginx, våra nodejs filer och mycket testande (mycket testande för det funkade inte rakt av), så kunde vi få allt att fungera.
Sensmoralen är väl att det helt klart är värt att skapa lösningar med "nya" teknologier men att man får vara beredd på att vissa väldigt specifika fall kan få allt krångla. Som vanlig med andra ord. Men som sagt, det är värt besväret.