engine-io 1.2.6 → 1.2.7
raw patch · 3 files changed
+27/−14 lines, 3 filesdep ~eitherPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: either
API changes (from Hackage documentation)
Files
- Changelog.md +6/−0
- engine-io.cabal +2/−2
- src/Network/EngineIO.hs +19/−12
Changelog.md view
@@ -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.
engine-io.cabal view
@@ -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,
src/Network/EngineIO.hs view
@@ -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