diff --git a/Changelog.md b/Changelog.md
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,9 @@
+## 1.2.7
+
+* Support decoding payloads coming through XHR polling transport.
+  Previously, this scenario would lead to HTTP 400 responses.
+* Increased upper bound on `either` to < 4.5.
+
 ## 1.2.6
 
 * Increased upper-bounds of aeson to < 0.10 and of attoparsec to < 0.14.
diff --git a/engine-io.cabal b/engine-io.cabal
--- a/engine-io.cabal
+++ b/engine-io.cabal
@@ -1,5 +1,5 @@
 name: engine-io
-version: 1.2.6
+version: 1.2.7
 synopsis: A Haskell implementation of Engine.IO
 homepage: http://github.com/ocharles/engine.io
 license: BSD3
@@ -33,7 +33,7 @@
     base >=4.6 && <4.9,
     base64-bytestring >=1.0 && <1.1,
     bytestring >=0.10.2.0 && <0.11,
-    either >= 3.4 && <4.4,
+    either >= 3.4 && <4.5,
     free >= 4.9 && <5.0,
     monad-loops >=0.4 && <0.5,
     mwc-random >=0.13 && <0.14,
diff --git a/src/Network/EngineIO.hs b/src/Network/EngineIO.hs
--- a/src/Network/EngineIO.hs
+++ b/src/Network/EngineIO.hs
@@ -208,15 +208,20 @@
 --------------------------------------------------------------------------------
 -- | Parse a stream of bytes into a 'Payload'.
 parsePayload :: Attoparsec.Parser Payload
-parsePayload = Payload <$> go
+parsePayload = Payload <$> (goXHR2 <|> goXHR)
   where
-  go = do
+  goXHR = do
+    len <- AttoparsecC8.decimal <* AttoparsecC8.char ':'
+    packet <- parsePacket' (Attoparsec.take (len - 1)) -- the type consumes 1 byte
+    (V.singleton packet <$ Attoparsec.endOfInput) <|> (V.cons packet <$> goXHR)
+
+  goXHR2 = do
     _ <- Attoparsec.satisfy (`elem` [0, 1])
     len <- parseLength =<< Attoparsec.many1 (Attoparsec.satisfy (inRange (0, 9)))
     _ <- Attoparsec.word8 maxBound
 
     packet <- parsePacket' (Attoparsec.take (len - 1)) -- the type consumes 1 byte
-    (V.singleton packet <$ Attoparsec.endOfInput) <|> (V.cons packet <$> go)
+    (V.singleton packet <$ Attoparsec.endOfInput) <|> (V.cons packet <$> goXHR2)
 
   parseLength bytes = do
     guard (length bytes <= 319)
@@ -398,7 +403,7 @@
 'handler' takes a function as an argument that is called every time a new
 session is created. This function runs in the @m@ monad, so you have access to
 initial web request, which may be useful for performing authentication or
-collecting cookies. This function then returns a 'ServerApp', describing the
+collecting cookies. This function then returns a 'SocketApp', describing the
 main loop and an action to perform on socket disconnection.
 
 -}
@@ -716,9 +721,9 @@
 
 --------------------------------------------------------------------------------
 -- | Create a new 'IO' action to read the socket's raw incoming communications.
--- The result of this call is iteslf an STM action, which will called will return
+-- The result of this call is iteslf an STM action, which when called will return
 -- the next unread incoming packet (or block). This provides you with a separate
--- channel to monitor incoming communications. This may useful to monitor to
+-- channel to monitor incoming communications. It may be useful to monitor this to
 -- determine if the socket has activity.
 --
 -- This is a fairly low level operation, so you will receive *all* packets -
@@ -732,14 +737,14 @@
 {- $intro
 
 @Network.EngineIO@ is a Haskell of implementation of
-<https://github.com/automattic/engine.io Engine.IO>, a realtime framework for
+<https://github.com/automattic/engine.io Engine.IO>, a real-time framework for
 the web. Engine.IO provides you with an abstraction for doing real-time
 communication between a server and a client. Engine.IO abstracts the framing and
 transport away, so that you can have real-time communication over long-polling
 HTTP requests, which are later upgraded to web sockets, if available.
 
 @Network.EngineIO@ needs to be provided with a 'ServerAPI' in order to be
-ran. 'ServerAPI' informs us how to fetch request headers, write HTTP responses
+run. 'ServerAPI' informs us how to fetch request headers, write HTTP responses
 to the client, and run web socket applications. Hackage contains implementations
 of 'ServerAPI' as:
 
@@ -767,9 +772,11 @@
 the socket. We wrap this all in 'Control.Monad.forever' as this connection
 should never terminate.
 
-> handleSocket :: Socket -> IO ()
-> handleSocket s = forever $ atomically $
->   receive s >>= send s
+> handleSocket :: MonadIO m => Socket -> m SocketApp
+> handleSocket s = return $ SocketApp app onDisconnect
+>   where
+>    app = forever $ STM.atomically $ receive s >>= EIO.send s
+>    onDisconnect = STM.atomically $ send s $ TextPacket "Bye!"
 
 Finally, we add a @main@ function to our application to launch it. I'll use
 @engine-io-snap@ as my server implementation:
@@ -777,7 +784,7 @@
 > main :: IO ()
 > main = do
 >   eio <- initialize
->   quickHttpServe $ handler eio handleSocket
+>   quickHttpServe $ handler eio handleSocket snapAPI
 
 This means that /any/ URL works as the Engine.IO server, which is sufficient for
 our example. In a real production application, you will probably want to nest
