Skip to content

Instantly share code, notes, and snippets.

@tfausak
Last active August 10, 2021 18:25
Show Gist options
  • Save tfausak/b33eed5186e8b8e5e361 to your computer and use it in GitHub Desktop.
Save tfausak/b33eed5186e8b8e5e361 to your computer and use it in GitHub Desktop.
Secure WebSockets in Haskell.
-- base ==4.7.0.1
-- bytestring ==0.10.4.0
-- connection ==0.2.4
-- network ==2.4.2.3
-- text ==1.1.0.0
-- websockets ==0.9.3.1
import Control.Concurrent (forkIO)
import Control.Monad (forever, void)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BL
import Data.ByteString.Lazy (toStrict)
import Data.Text (Text, pack)
import Network.Connection (Connection, ConnectionParams (..), TLSSettings (..),
connectionGetChunk, connectionPut, connectTo, initConnectionContext)
import Network.Socket (PortNumber (..))
import Network.WebSockets (ClientApp, ConnectionOptions, Headers,
defaultConnectionOptions, receiveData, runClientWithStream, sendClose,
sendTextData)
import Network.WebSockets.Stream (makeStream)
main :: IO ()
main = runSecureClient "echo.websocket.org" 443 "/" application
application :: ClientApp ()
application connection = do
putStrLn "Connected!"
void . forkIO . forever $ do
message <- receiveData connection
print (message :: Text)
let loop = do
line <- getLine
if null line
then return ()
else do
sendTextData connection (pack line)
loop
loop
sendClose connection (pack "Bye!")
runSecureClient :: String -> PortNumber -> String -> ClientApp a -> IO a
runSecureClient host port path app = do
context <- initConnectionContext
connection <- connectTo context (connectionParams host port)
stream <- makeStream (reader connection) (writer connection)
runClientWithStream stream host path connectionOptions headers app
connectionParams :: String -> PortNumber -> ConnectionParams
connectionParams host port = ConnectionParams
{ connectionHostname = host
, connectionPort = port
, connectionUseSecure = Just tlsSettings
, connectionUseSocks = Nothing
}
tlsSettings :: TLSSettings
tlsSettings = TLSSettingsSimple
{ settingDisableCertificateValidation = False
, settingDisableSession = False
, settingUseServerName = False
}
reader :: Connection -> IO (Maybe BS.ByteString)
reader connection = fmap Just (connectionGetChunk connection)
writer :: Connection -> Maybe BL.ByteString -> IO ()
writer connection = maybe (return ()) (connectionPut connection . toStrict)
connectionOptions :: ConnectionOptions
connectionOptions = defaultConnectionOptions
headers :: Headers
headers = []
@tfausak
Copy link
Author

tfausak commented Apr 16, 2015

If you landed here looking for secure WebSockets in Haskell, check out my library Wuss. It handles this for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment