Initial yesod-websockets
Pinging @gregwebs and @meteficha. Greg: I know you were talking about Sockets.IO support, and Felipe: I thought you might be curious about this relative to yesod-eventsource. Comments welcome :)
This commit is contained in:
parent
56e42936b0
commit
13976667ed
20
yesod-websockets/LICENSE
Normal file
20
yesod-websockets/LICENSE
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
Copyright (c) 2014 Michael Snoyman, http://www.yesodweb.com/
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
2
yesod-websockets/Setup.hs
Normal file
2
yesod-websockets/Setup.hs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import Distribution.Simple
|
||||||
|
main = defaultMain
|
||||||
60
yesod-websockets/Yesod/WebSockets.hs
Normal file
60
yesod-websockets/Yesod/WebSockets.hs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
|
module Yesod.WebSockets
|
||||||
|
( WebsocketsT
|
||||||
|
, webSockets
|
||||||
|
, receiveData
|
||||||
|
, sendTextData
|
||||||
|
, sendBinaryData
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Monad (when)
|
||||||
|
import Control.Monad.IO.Class (MonadIO (liftIO))
|
||||||
|
import Control.Monad.Trans.Control (control)
|
||||||
|
import Control.Monad.Trans.Reader (ReaderT (ReaderT, runReaderT))
|
||||||
|
import qualified Network.Wai.Handler.WebSockets as WaiWS
|
||||||
|
import qualified Network.WebSockets as WS
|
||||||
|
import qualified Yesod.Core as Y
|
||||||
|
|
||||||
|
-- | A transformer for a WebSockets handler.
|
||||||
|
--
|
||||||
|
-- Since 0.1.0
|
||||||
|
type WebsocketsT = ReaderT WS.Connection
|
||||||
|
|
||||||
|
-- | Attempt to run a WebSockets handler. This function first checks if the
|
||||||
|
-- client initiated a WebSockets connection and, if so, runs the provided
|
||||||
|
-- application, short-circuiting the rest of your handler. If the client did
|
||||||
|
-- not request a WebSockets connection, the rest of your handler will be called
|
||||||
|
-- instead.
|
||||||
|
--
|
||||||
|
-- Since 0.1.0
|
||||||
|
webSockets :: (Y.MonadBaseControl IO m, Y.MonadHandler m) => WebsocketsT m () -> m ()
|
||||||
|
webSockets inner = do
|
||||||
|
req <- Y.waiRequest
|
||||||
|
when (WaiWS.isWebSocketsReq req) $
|
||||||
|
Y.sendRawResponse $ \src sink -> control $ \runInIO -> WaiWS.runWebSockets
|
||||||
|
WS.defaultConnectionOptions
|
||||||
|
(WaiWS.getRequestHead req)
|
||||||
|
(\pconn -> do
|
||||||
|
conn <- WS.acceptRequest pconn
|
||||||
|
runInIO $ runReaderT inner conn)
|
||||||
|
src
|
||||||
|
sink
|
||||||
|
|
||||||
|
-- | Receive a piece of data from the client.
|
||||||
|
--
|
||||||
|
-- Since 0.1.0
|
||||||
|
receiveData :: (MonadIO m, WS.WebSocketsData a) => WebsocketsT m a
|
||||||
|
receiveData = ReaderT $ liftIO . WS.receiveData
|
||||||
|
|
||||||
|
-- | Send a textual messsage to the client.
|
||||||
|
--
|
||||||
|
-- Since 0.1.0
|
||||||
|
sendTextData :: (MonadIO m, WS.WebSocketsData a) => a -> WebsocketsT m ()
|
||||||
|
sendTextData x = ReaderT $ liftIO . flip WS.sendTextData x
|
||||||
|
|
||||||
|
-- | Send a binary messsage to the client.
|
||||||
|
--
|
||||||
|
-- Since 0.1.0
|
||||||
|
sendBinaryData :: (MonadIO m, WS.WebSocketsData a) => a -> WebsocketsT m ()
|
||||||
|
sendBinaryData x = ReaderT $ liftIO . flip WS.sendBinaryData x
|
||||||
39
yesod-websockets/sample.hs
Normal file
39
yesod-websockets/sample.hs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{-# LANGUAGE QuasiQuotes, TemplateHaskell, TypeFamilies #-}
|
||||||
|
import Yesod.Core
|
||||||
|
import Yesod.WebSockets
|
||||||
|
import qualified Data.Text.Lazy as TL
|
||||||
|
import Control.Monad (forever)
|
||||||
|
|
||||||
|
data App = App
|
||||||
|
|
||||||
|
instance Yesod App
|
||||||
|
|
||||||
|
mkYesod "App" [parseRoutes|
|
||||||
|
/ HomeR GET
|
||||||
|
|]
|
||||||
|
|
||||||
|
getHomeR :: Handler Html
|
||||||
|
getHomeR = do
|
||||||
|
webSockets $ forever $ do
|
||||||
|
msg <- receiveData
|
||||||
|
sendTextData $ TL.toUpper msg
|
||||||
|
defaultLayout $
|
||||||
|
toWidget
|
||||||
|
[julius|
|
||||||
|
var conn = new WebSocket("ws://localhost:3000/");
|
||||||
|
conn.onopen = function() {
|
||||||
|
document.write("<p>open!</p>");
|
||||||
|
document.write("<button id=button>Send another message</button>")
|
||||||
|
document.getElementById("button").addEventListener("click", function(){
|
||||||
|
var msg = prompt("Enter a message for the server");
|
||||||
|
conn.send(msg);
|
||||||
|
});
|
||||||
|
conn.send("hello world");
|
||||||
|
};
|
||||||
|
conn.onmessage = function(e) {
|
||||||
|
document.write("<p>" + e.data + "</p>");
|
||||||
|
};
|
||||||
|
|]
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = warp 3000 App
|
||||||
28
yesod-websockets/yesod-websockets.cabal
Normal file
28
yesod-websockets/yesod-websockets.cabal
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
-- Initial yesod-websockets.cabal generated by cabal init. For further
|
||||||
|
-- documentation, see http://haskell.org/cabal/users-guide/
|
||||||
|
|
||||||
|
name: yesod-websockets
|
||||||
|
version: 0.1.0.0
|
||||||
|
synopsis: WebSockets support for Yesod
|
||||||
|
description: WebSockets support for Yesod
|
||||||
|
homepage: https://github.com/yesodweb/yesod
|
||||||
|
license: MIT
|
||||||
|
license-file: LICENSE
|
||||||
|
author: Michael Snoyman
|
||||||
|
maintainer: michael@snoyman.com
|
||||||
|
category: Web
|
||||||
|
build-type: Simple
|
||||||
|
cabal-version: >=1.8
|
||||||
|
|
||||||
|
library
|
||||||
|
exposed-modules: Yesod.WebSockets
|
||||||
|
build-depends: base >= 4.5 && < 5
|
||||||
|
, wai-websockets >= 2.1
|
||||||
|
, websockets >= 0.8
|
||||||
|
, transformers >= 0.2
|
||||||
|
, yesod-core >= 1.2.7
|
||||||
|
, monad-control >= 0.3
|
||||||
|
|
||||||
|
source-repository head
|
||||||
|
type: git
|
||||||
|
location: https://github.com/yesodweb/yesod
|
||||||
Loading…
Reference in New Issue
Block a user