wss-client 0.2.0.0 → 0.2.1.0
raw patch · 4 files changed
+74/−16 lines, 4 filesdep +envydep +skewsdep +textdep −QuickCheck
Dependencies added: envy, skews, text
Dependencies removed: QuickCheck
Files
- README.md +1/−2
- src/Network/WebSockets/Client.hs +12/−12
- test/Network/WebSockets/ClientSpec.hs +55/−0
- wss-client.cabal +6/−2
README.md view
@@ -5,9 +5,8 @@ ## TODO -- Support non-TLS connection via an HTTP proxy server (I have to modify the [websockets](https://hackage.haskell.org/package/websockets) package to do that).+- Support non-TLS connection via an HTTP proxy server (I have to add one more API to http-client to check if the connection is proxied package to do that). - Add APIs to modify config of both http-client and websockets.-- Test with a mock server. ## Example
src/Network/WebSockets/Client.hs view
@@ -41,15 +41,15 @@ ) where -import qualified Control.Exception as E-import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as BSL-import qualified Network.HTTP.Client as Http+import qualified Control.Exception as E+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as BSL+import qualified Network.HTTP.Client as Http import qualified Network.HTTP.Client.Internal as Http-import Network.HTTP.Client.TLS (tlsManagerSettings)-import qualified Network.WebSockets as WS-import qualified Network.WebSockets.Stream as WS-import Network.URI (parseURI, URI(..), URIAuth(..))+import Network.HTTP.Client.TLS (tlsManagerSettings)+import Network.URI (URI (..), URIAuth (..), parseURI)+import qualified Network.WebSockets as WS+import qualified Network.WebSockets.Stream as WS -- | The main entrypoint to connect by the WebSocket protocol. -- This function automatically closes the created connection@@ -73,9 +73,9 @@ withConnectionFromManager :: Http.Manager -> String -> (WS.Connection -> IO a) -> IO a withConnectionFromManager man rawUrl action = do- (isSecure, host, path) <- parseWsUrl rawUrl+ (isSecure, host, port, path) <- parseWsUrl rawUrl - let httpUrl = (if isSecure then "https://" else "http://") ++ host ++ path+ let httpUrl = (if isSecure then "https://" else "http://") ++ host ++ port ++ path req <- Http.parseRequest $ "GET " ++ httpUrl Http.withConnection req man $ \httpConn -> do@@ -101,7 +101,7 @@ ) -parseWsUrl :: String -> IO (Bool, String, String)+parseWsUrl :: String -> IO (Bool, String, String, String) parseWsUrl raw = do uri <- noteInvalidUrl "Invalid URL given" $ parseURI raw auth <- noteInvalidUrl "No authroity specified" $ uriAuthority uri@@ -111,7 +111,7 @@ scheme = if null scheme' then wss else scheme' isSecure = scheme == wss path = uriPath uri ++ uriQuery uri ++ uriFragment uri- return (isSecure, host, if null path then "/" else path)+ return (isSecure, host, uriPort auth, if null path then "/" else path) where noteInvalidUrl :: String -> Maybe a -> IO a noteInvalidUrl msg =
+ test/Network/WebSockets/ClientSpec.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE OverloadedStrings #-}++module Network.WebSockets.ClientSpec+ ( main+ , spec+ ) where+++import Control.Applicative (empty, (<|>))+import qualified Data.ByteString.Lazy.Char8 as BS+import qualified Data.Text as T+import qualified Network.WebSockets.Skews as Skews+import System.Envy (FromEnv, decodeEnv, env, fromEnv)+import Test.Hspec+import Text.Read (readMaybe)++import qualified Network.WebSockets.Client as WS+++-- `main` is here so that this module can be run from GHCi on its own. It is+-- not needed for automatic spec discovery.+main :: IO ()+main = hspec spec+++newtype PortNumber = PortNumber Int deriving (Eq, Show)++instance FromEnv PortNumber where+ fromEnv = do+ mpn <- (readMaybe <$> env "WSS_CLIENT_TEST_SERVER_PORT") <|> pure (Just 8614)+ PortNumber <$> maybe empty pure mpn+++spec :: Spec+spec = describe "withConnection" $ do+ Right (PortNumber pn) <- runIO decodeEnv++ let host = "localhost"+ server <- runIO $ Skews.start $ Skews.Args host pn++ let withConnection = WS.withConnection ("ws://" ++ host ++ ":" ++ show pn)+ payload = "response"+ response = WS.DataMessage False False False (WS.Binary payload)+ beforeAction = do+ Skews.reinit server+ Skews.setDefaultResponse server payload++ before_ beforeAction $+ it "can send and receive messages via the connection" $ do+ actualResponse <- withConnection $ \conn -> do+ WS.sendTextData conn ("client data" :: T.Text)+ r <- WS.receive conn+ WS.sendClose conn ("Bye" :: BS.ByteString)+ return r+ actualResponse `shouldBe` response
wss-client.cabal view
@@ -1,5 +1,5 @@ name: wss-client-version: 0.2.0.0+version: 0.2.1.0 synopsis: A-little-higher-level WebSocket client. description: A-little-higher-level WebSocket client. Based on http-client and http-client-tls. homepage: https://github.com/iij-ii/wss-client@@ -46,10 +46,14 @@ type: exitcode-stdio-1.0 hs-source-dirs: test main-is: Spec.hs+ other-modules: Network.WebSockets.ClientSpec build-depends: base , wss-client+ , bytestring+ , envy , hspec- , QuickCheck+ , skews+ , text ghc-options: -threaded -rtsopts -with-rtsopts=-N default-language: Haskell2010