wuss 1.1.6 → 1.1.7
raw patch · 11 files changed
+364/−277 lines, 11 filesdep ~basedep ~bytestringdep ~connectionsetup-changedPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, bytestring, connection, network, websockets
API changes (from Hackage documentation)
Files
- CHANGELOG.markdown +7/−0
- CHANGELOG.md +0/−7
- LICENSE.markdown +21/−0
- LICENSE.md +0/−23
- README.markdown +79/−0
- Setup.hs +2/−2
- Wuss.hs +0/−218
- library/Wuss.hs +217/−0
- package.yaml +24/−16
- stack.yaml +1/−1
- wuss.cabal +13/−10
+ CHANGELOG.markdown view
@@ -0,0 +1,7 @@+# Change log++Wuss uses [Semantic Versioning][].+The change log is available through the [releases on GitHub][].++[Semantic Versioning]: http://semver.org/spec/v2.0.0.html+[releases on GitHub]: https://github.com/tfausak/wuss/releases
− CHANGELOG.md
@@ -1,7 +0,0 @@-# Change log--Wuss uses [Semantic Versioning][].-The change log is available through the [releases on GitHub][].--[Semantic Versioning]: http://semver.org/spec/v2.0.0.html-[releases on GitHub]: https://github.com/tfausak/wuss/releases
+ LICENSE.markdown view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2018 Taylor Fausak++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.
− LICENSE.md
@@ -1,23 +0,0 @@-[The MIT License (MIT)][]--Copyright (c) 2016 Taylor Fausak--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.--[The MIT License (MIT)]: https://opensource.org/licenses/MIT
+ README.markdown view
@@ -0,0 +1,79 @@+# [Wuss][]++Secure WebSocket (WSS) clients in Haskell.++[![Version badge][]][version]+[![Build badge][]][build]++---++Wuss is a library that lets you easily create secure WebSocket clients over the+WSS protocol. It is a small addition to [the `websockets` package][] and is+adapted from existing solutions by [@jaspervdj][], [@mpickering][], and+[@elfenlaid][].++- [Installation](#installation)+- [Usage](#usage)++## Installation++To add Wuss as a dependency to your package, add it to your Cabal file.++```+build-depends: wuss+```++For other use cases, install it with Cabal.++``` sh+$ cabal install wuss+```++Wuss uses [Semantic Versioning][]. See [the change log][] for a detailed list+of changes.++## Usage++``` hs+import Wuss++import Control.Concurrent (forkIO)+import Control.Monad (forever, unless, void)+import Data.Text (Text, pack)+import Network.WebSockets (ClientApp, receiveData, sendClose, sendTextData)++main :: IO ()+main = runSecureClient "echo.websocket.org" 443 "/" ws++ws :: ClientApp ()+ws connection = do+ putStrLn "Connected!"++ void . forkIO . forever $ do+ message <- receiveData connection+ print (message :: Text)++ let loop = do+ line <- getLine+ unless (null line) $ do+ sendTextData connection (pack line)+ loop+ loop++ sendClose connection (pack "Bye!")+```++For more information about Wuss, please read [the Haddock documentation][].++[Wuss]: http://taylor.fausak.me/wuss/+[Version badge]: https://www.stackage.org/package/wuss/badge/nightly?label=version+[version]: https://www.stackage.org/package/wuss+[Build badge]: https://travis-ci.org/tfausak/wuss.svg?branch=master+[build]: https://travis-ci.org/tfausak/wuss+[the `websockets` package]: https://hackage.haskell.org/package/websockets+[@jaspervdj]: https://gist.github.com/jaspervdj/7198388+[@mpickering]: https://gist.github.com/mpickering/f1b7ba3190a4bb5884f3+[@elfenlaid]: https://gist.github.com/elfenlaid/7b5c28065e67e4cf0767+[semantic versioning]: http://semver.org/spec/v2.0.0.html+[the change log]: CHANGELOG.md+[the haddock documentation]: https://hackage.haskell.org/package/wuss
Setup.hs view
@@ -1,4 +1,4 @@-import qualified Distribution.Simple+import qualified Distribution.Simple as Cabal main :: IO ()-main = Distribution.Simple.defaultMain+main = Cabal.defaultMain
− Wuss.hs
@@ -1,218 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}--{- |- Wuss is a library that lets you easily create secure WebSocket clients over- the WSS protocol. It is a small addition to- <https://hackage.haskell.org/package/websockets the websockets package>- and is adapted from existing solutions by- <https://gist.github.com/jaspervdj/7198388 @jaspervdj>,- <https://gist.github.com/mpickering/f1b7ba3190a4bb5884f3 @mpickering>, and- <https://gist.github.com/elfenlaid/7b5c28065e67e4cf0767 @elfenlaid>.-- == Example-- > import Wuss- >- > import Control.Concurrent (forkIO)- > import Control.Monad (forever, unless, void)- > import Data.Text (Text, pack)- > import Network.WebSockets (ClientApp, receiveData, sendClose, sendTextData)- >- > main :: IO ()- > main = runSecureClient "echo.websocket.org" 443 "/" ws- >- > ws :: ClientApp ()- > ws connection = do- > putStrLn "Connected!"- >- > void . forkIO . forever $ do- > message <- receiveData connection- > print (message :: Text)- >- > let loop = do- > line <- getLine- > unless (null line) $ do- > sendTextData connection (pack line)- > loop- > loop- >- > sendClose connection (pack "Bye!")--}-module Wuss- ( runSecureClient- , runSecureClientWith- , Config(..)- , defaultConfig- , runSecureClientWithConfig- ) where--import qualified Control.Applicative as Applicative-import qualified Control.Exception as Exception-import qualified Data.Bool as Bool-import qualified Data.ByteString as StrictBytes-import qualified Data.ByteString.Lazy as LazyBytes-import qualified Data.Maybe as Maybe-import qualified Data.String as String-import qualified Network.Connection as Connection-import qualified Network.Socket as Socket-import qualified Network.WebSockets as WebSockets-import qualified Network.WebSockets.Stream as Stream-import qualified System.IO as IO-import qualified System.IO.Error as IO.Error---{- |- A secure replacement for 'Network.WebSockets.runClient'.-- >>> let app _connection = return ()- >>> runSecureClient "echo.websocket.org" 443 "/" app--}-runSecureClient- :: Socket.HostName -- ^ Host- -> Socket.PortNumber -- ^ Port- -> String.String -- ^ Path- -> WebSockets.ClientApp a -- ^ Application- -> IO.IO a-runSecureClient host port path app = do- let options = WebSockets.defaultConnectionOptions- let headers = []- runSecureClientWith host port path options headers app---{- |- A secure replacement for 'Network.WebSockets.runClientWith'.-- >>> let options = defaultConnectionOptions- >>> let headers = []- >>> let app _connection = return ()- >>> runSecureClientWith "echo.websocket.org" 443 "/" options headers app-- If you want to run a secure client without certificate validation, use- 'Network.WebSockets.runClientWithStream'. For example:-- > let host = "echo.websocket.org"- > let port = 443- > let path = "/"- > let options = defaultConnectionOptions- > let headers = []- > let tlsSettings = TLSSettingsSimple- > -- This is the important setting.- > { settingDisableCertificateValidation = True- > , settingDisableSession = False- > , settingUseServerName = False- > }- > let connectionParams = ConnectionParams- > { connectionHostname = host- > , connectionPort = port- > , connectionUseSecure = Just tlsSettings- > , connectionUseSocks = Nothing- > }- >- > context <- initConnectionContext- > connection <- connectTo context connectionParams- > stream <- makeStream- > (fmap Just (connectionGetChunk connection))- > (maybe (return ()) (connectionPut connection . toStrict))- > runClientWithStream stream host path options headers $ \ connection -> do- > -- Do something with the connection.- > return ()--}-runSecureClientWith- :: Socket.HostName -- ^ Host- -> Socket.PortNumber -- ^ Port- -> String.String -- ^ Path- -> WebSockets.ConnectionOptions -- ^ Options- -> WebSockets.Headers -- ^ Headers- -> WebSockets.ClientApp a -- ^ Application- -> IO.IO a-runSecureClientWith host port path options headers app = do- let config = defaultConfig- runSecureClientWithConfig host port path config options headers app----- | Configures a secure WebSocket connection.-data Config = Config- { connectionGet :: Connection.Connection -> IO.IO StrictBytes.ByteString- -- ^ How to get bytes from the connection. Typically- -- 'Connection.connectionGetChunk', but could be something else like- -- 'Connection.connectionGetLine'.- }----- | The default 'Config' value used by 'runSecureClientWith'.-defaultConfig- :: Config-defaultConfig = do- Config- { connectionGet = Connection.connectionGetChunk- }----- | Runs a secure WebSockets client with the given 'Config'.-runSecureClientWithConfig- :: Socket.HostName -- ^ Host- -> Socket.PortNumber -- ^ Port- -> String.String -- ^ Path- -> Config -- ^ Config- -> WebSockets.ConnectionOptions -- ^ Options- -> WebSockets.Headers -- ^ Headers- -> WebSockets.ClientApp a -- ^ Application- -> IO.IO a-runSecureClientWithConfig host port path config options headers app = do- context <- Connection.initConnectionContext- Exception.bracket- (Connection.connectTo context (connectionParams host port))- Connection.connectionClose- (\connection -> do- stream <-- Stream.makeStream (reader config connection) (writer connection)- WebSockets.runClientWithStream stream host path options headers app)---connectionParams- :: Socket.HostName- -> Socket.PortNumber- -> Connection.ConnectionParams-connectionParams host port = do- Connection.ConnectionParams- { Connection.connectionHostname = host- , Connection.connectionPort = port- , Connection.connectionUseSecure = Maybe.Just tlsSettings- , Connection.connectionUseSocks = Maybe.Nothing- }---tlsSettings- :: Connection.TLSSettings-tlsSettings = do- Connection.TLSSettingsSimple- { Connection.settingDisableCertificateValidation = Bool.False- , Connection.settingDisableSession = Bool.False- , Connection.settingUseServerName = Bool.False- }---reader- :: Config- -> Connection.Connection- -> IO.IO (Maybe.Maybe StrictBytes.ByteString)-reader config connection =- IO.Error.catchIOError (do- chunk <- (connectionGet config) connection- Applicative.pure (Maybe.Just chunk))- (\e ->- if IO.Error.isEOFError e- then Applicative.pure Maybe.Nothing- else Exception.throwIO e)---writer- :: Connection.Connection- -> Maybe.Maybe LazyBytes.ByteString- -> IO.IO ()-writer connection maybeBytes = do- case maybeBytes of- Maybe.Nothing -> do- Applicative.pure ()- Maybe.Just bytes -> do- Connection.connectionPut connection (LazyBytes.toStrict bytes)
+ library/Wuss.hs view
@@ -0,0 +1,217 @@+{-# LANGUAGE NoImplicitPrelude #-}++{- |+ Wuss is a library that lets you easily create secure WebSocket clients over+ the WSS protocol. It is a small addition to+ <https://hackage.haskell.org/package/websockets the websockets package>+ and is adapted from existing solutions by+ <https://gist.github.com/jaspervdj/7198388 @jaspervdj>,+ <https://gist.github.com/mpickering/f1b7ba3190a4bb5884f3 @mpickering>, and+ <https://gist.github.com/elfenlaid/7b5c28065e67e4cf0767 @elfenlaid>.++ == Example++ > import Wuss+ >+ > import Control.Concurrent (forkIO)+ > import Control.Monad (forever, unless, void)+ > import Data.Text (Text, pack)+ > import Network.WebSockets (ClientApp, receiveData, sendClose, sendTextData)+ >+ > main :: IO ()+ > main = runSecureClient "echo.websocket.org" 443 "/" ws+ >+ > ws :: ClientApp ()+ > ws connection = do+ > putStrLn "Connected!"+ >+ > void . forkIO . forever $ do+ > message <- receiveData connection+ > print (message :: Text)+ >+ > let loop = do+ > line <- getLine+ > unless (null line) $ do+ > sendTextData connection (pack line)+ > loop+ > loop+ >+ > sendClose connection (pack "Bye!")+-}+module Wuss+ ( runSecureClient+ , runSecureClientWith+ , Config(..)+ , defaultConfig+ , runSecureClientWithConfig+ ) where++import qualified Control.Applicative as Applicative+import qualified Control.Exception as Exception+import qualified Data.Bool as Bool+import qualified Data.ByteString as StrictBytes+import qualified Data.ByteString.Lazy as LazyBytes+import qualified Data.Maybe as Maybe+import qualified Data.String as String+import qualified Network.Connection as Connection+import qualified Network.Socket as Socket+import qualified Network.WebSockets as WebSockets+import qualified Network.WebSockets.Stream as Stream+import qualified System.IO as IO+import qualified System.IO.Error as IO.Error+++{- |+ A secure replacement for 'Network.WebSockets.runClient'.++ >>> let app _connection = return ()+ >>> runSecureClient "echo.websocket.org" 443 "/" app+-}+runSecureClient+ :: Socket.HostName -- ^ Host+ -> Socket.PortNumber -- ^ Port+ -> String.String -- ^ Path+ -> WebSockets.ClientApp a -- ^ Application+ -> IO.IO a+runSecureClient host port path app = do+ let options = WebSockets.defaultConnectionOptions+ runSecureClientWith host port path options [] app+++{- |+ A secure replacement for 'Network.WebSockets.runClientWith'.++ >>> let options = defaultConnectionOptions+ >>> let headers = []+ >>> let app _connection = return ()+ >>> runSecureClientWith "echo.websocket.org" 443 "/" options headers app++ If you want to run a secure client without certificate validation, use+ 'Network.WebSockets.runClientWithStream'. For example:++ > let host = "echo.websocket.org"+ > let port = 443+ > let path = "/"+ > let options = defaultConnectionOptions+ > let headers = []+ > let tlsSettings = TLSSettingsSimple+ > -- This is the important setting.+ > { settingDisableCertificateValidation = True+ > , settingDisableSession = False+ > , settingUseServerName = False+ > }+ > let connectionParams = ConnectionParams+ > { connectionHostname = host+ > , connectionPort = port+ > , connectionUseSecure = Just tlsSettings+ > , connectionUseSocks = Nothing+ > }+ >+ > context <- initConnectionContext+ > connection <- connectTo context connectionParams+ > stream <- makeStream+ > (fmap Just (connectionGetChunk connection))+ > (maybe (return ()) (connectionPut connection . toStrict))+ > runClientWithStream stream host path options headers $ \ connection -> do+ > -- Do something with the connection.+ > return ()+-}+runSecureClientWith+ :: Socket.HostName -- ^ Host+ -> Socket.PortNumber -- ^ Port+ -> String.String -- ^ Path+ -> WebSockets.ConnectionOptions -- ^ Options+ -> WebSockets.Headers -- ^ Headers+ -> WebSockets.ClientApp a -- ^ Application+ -> IO.IO a+runSecureClientWith host port path options headers app = do+ let config = defaultConfig+ runSecureClientWithConfig host port path config options headers app+++-- | Configures a secure WebSocket connection.+data Config = Config+ { connectionGet :: Connection.Connection -> IO.IO StrictBytes.ByteString+ -- ^ How to get bytes from the connection. Typically+ -- 'Connection.connectionGetChunk', but could be something else like+ -- 'Connection.connectionGetLine'.+ }+++-- | The default 'Config' value used by 'runSecureClientWith'.+defaultConfig+ :: Config+defaultConfig = do+ Config+ { connectionGet = Connection.connectionGetChunk+ }+++-- | Runs a secure WebSockets client with the given 'Config'.+runSecureClientWithConfig+ :: Socket.HostName -- ^ Host+ -> Socket.PortNumber -- ^ Port+ -> String.String -- ^ Path+ -> Config -- ^ Config+ -> WebSockets.ConnectionOptions -- ^ Options+ -> WebSockets.Headers -- ^ Headers+ -> WebSockets.ClientApp a -- ^ Application+ -> IO.IO a+runSecureClientWithConfig host port path config options headers app = do+ context <- Connection.initConnectionContext+ Exception.bracket+ (Connection.connectTo context (connectionParams host port))+ Connection.connectionClose+ (\connection -> do+ stream <-+ Stream.makeStream (reader config connection) (writer connection)+ WebSockets.runClientWithStream stream host path options headers app)+++connectionParams+ :: Socket.HostName+ -> Socket.PortNumber+ -> Connection.ConnectionParams+connectionParams host port = do+ Connection.ConnectionParams+ { Connection.connectionHostname = host+ , Connection.connectionPort = port+ , Connection.connectionUseSecure = Maybe.Just tlsSettings+ , Connection.connectionUseSocks = Maybe.Nothing+ }+++tlsSettings+ :: Connection.TLSSettings+tlsSettings = do+ Connection.TLSSettingsSimple+ { Connection.settingDisableCertificateValidation = Bool.False+ , Connection.settingDisableSession = Bool.False+ , Connection.settingUseServerName = Bool.False+ }+++reader+ :: Config+ -> Connection.Connection+ -> IO.IO (Maybe.Maybe StrictBytes.ByteString)+reader config connection =+ IO.Error.catchIOError (do+ chunk <- (connectionGet config) connection+ Applicative.pure (Maybe.Just chunk))+ (\e ->+ if IO.Error.isEOFError e+ then Applicative.pure Maybe.Nothing+ else Exception.throwIO e)+++writer+ :: Connection.Connection+ -> Maybe.Maybe LazyBytes.ByteString+ -> IO.IO ()+writer connection maybeBytes = do+ case maybeBytes of+ Maybe.Nothing -> do+ Applicative.pure ()+ Maybe.Just bytes -> do+ Connection.connectionPut connection (LazyBytes.toStrict bytes)
package.yaml view
@@ -1,5 +1,9 @@+name: wuss+version: 1.1.7+ category: Network-description: Wuss is a library that lets you easily create secure WebSocket+description:+ Wuss is a library that lets you easily create secure WebSocket clients over the WSS protocol. It is a small addition to <https://hackage.haskell.org/package/websockets the websockets package> and is adapted from existing solutions by@@ -7,22 +11,26 @@ <https://gist.github.com/mpickering/f1b7ba3190a4bb5884f3 @mpickering>, and <https://gist.github.com/elfenlaid/7b5c28065e67e4cf0767 @elfenlaid>. extra-source-files:-- CHANGELOG.md-- LICENSE.md-- package.yaml-- stack.yaml-ghc-options: -Wall+ - CHANGELOG.markdown+ - package.yaml+ - README.markdown+ - stack.yaml github: tfausak/wuss-library:- dependencies:- - base ==4.*- - bytestring ==0.10.*- - connection ==0.2.*- - network- - websockets >=0.9 && <0.13- exposed-modules: Wuss+license-file: LICENSE.markdown license: MIT maintainer: Taylor Fausak-name: wuss synopsis: Secure WebSocket (WSS) clients-version: '1.1.6'++dependencies:+ base: '>= 4.9.0 && < 4.11'+ bytestring: '>= 0.10.8 && < 0.11'+ connection: '>= 0.2.6 && < 0.3'+ network: '>= 2.6.3 && < 2.7'+ websockets: '>= 0.9.7 && < 0.13'+ghc-options:+ -Weverything+ -Wno-safe+ -Wno-unsafe++library:+ source-dirs: library
stack.yaml view
@@ -1,1 +1,1 @@-resolver: lts-10.0+resolver: lts-11.0
wuss.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: e39233c673daffa4d7485afeaa4e8c07b536b5a1961b926ce3010592feee0d35+-- hash: 9e579433b8073e0eafb4e01b5bdb8719889b5bf7c0861f28654f5e1f4da9aed5 name: wuss-version: 1.1.6+version: 1.1.7 synopsis: Secure WebSocket (WSS) clients description: Wuss is a library that lets you easily create secure WebSocket clients over the WSS protocol. It is a small addition to <https://hackage.haskell.org/package/websockets the websockets package> and is adapted from existing solutions by <https://gist.github.com/jaspervdj/7198388 @jaspervdj>, <https://gist.github.com/mpickering/f1b7ba3190a4bb5884f3 @mpickering>, and <https://gist.github.com/elfenlaid/7b5c28065e67e4cf0767 @elfenlaid>. category: Network@@ -13,13 +13,14 @@ bug-reports: https://github.com/tfausak/wuss/issues maintainer: Taylor Fausak license: MIT+license-file: LICENSE.markdown build-type: Simple cabal-version: >= 1.10 extra-source-files:- CHANGELOG.md- LICENSE.md+ CHANGELOG.markdown package.yaml+ README.markdown stack.yaml source-repository head@@ -27,13 +28,15 @@ location: https://github.com/tfausak/wuss library- ghc-options: -Wall+ hs-source-dirs:+ library+ ghc-options: -Weverything -Wno-safe -Wno-unsafe build-depends:- base ==4.*- , bytestring ==0.10.*- , connection ==0.2.*- , network- , websockets >=0.9 && <0.13+ base >=4.9.0 && <4.11+ , bytestring >=0.10.8 && <0.11+ , connection >=0.2.6 && <0.3+ , network >=2.6.3 && <2.7+ , websockets >=0.9.7 && <0.13 exposed-modules: Wuss other-modules: