From 9de8070bbbc8646b54b5a8e5e968cf2cf17f1834 Mon Sep 17 00:00:00 2001 From: Mirko Westermeier Date: Fri, 16 Feb 2024 14:35:31 +0100 Subject: [PATCH] Restructure WebService code with JSON example --- lib/LiBro/WebService.hs | 29 +++++++++++++++++++++++++++++ lib/LiBro/WebService/API.hs | 9 --------- lib/LiBro/WebService/Server.hs | 10 ---------- lib/LiBro/WebService/State.hs | 25 +++++++++++++++++++++++++ libro-backend.cabal | 7 +++++-- server/Main.hs | 2 +- test/LiBro/WebServiceSpec.hs | 13 ++++++++++--- test/run-all-tests.hs | 2 ++ 8 files changed, 72 insertions(+), 25 deletions(-) create mode 100644 lib/LiBro/WebService.hs delete mode 100644 lib/LiBro/WebService/API.hs delete mode 100644 lib/LiBro/WebService/Server.hs create mode 100644 lib/LiBro/WebService/State.hs diff --git a/lib/LiBro/WebService.hs b/lib/LiBro/WebService.hs new file mode 100644 index 0000000..fe44060 --- /dev/null +++ b/lib/LiBro/WebService.hs @@ -0,0 +1,29 @@ +module LiBro.WebService where + +import Data.Aeson +import Data.Proxy +import Servant +import GHC.Generics + +newtype PersonIDs = PersonIDs {personIDs :: [Int]} deriving Generic +instance ToJSON PersonIDs + +type LiBroAPI = "hello" :> Get '[JSON] PersonIDs + :<|> "yay" :> Get '[PlainText] String + +libroServer :: Server LiBroAPI +libroServer = handleHello + :<|> handleYay + where + handleHello :: Handler PersonIDs + handleHello = return $ PersonIDs [17, 42] + + handleYay :: Handler String + handleYay = return "Yay!" + +libroApi :: Proxy LiBroAPI +libroApi = Proxy + +libro :: Application +libro = serve libroApi libroServer + diff --git a/lib/LiBro/WebService/API.hs b/lib/LiBro/WebService/API.hs deleted file mode 100644 index fdc9231..0000000 --- a/lib/LiBro/WebService/API.hs +++ /dev/null @@ -1,9 +0,0 @@ -module LiBro.WebService.API where - -import Data.Proxy -import Servant.API - -type LiBroAPI = "hello" :> Get '[PlainText] String - -libroApi :: Proxy LiBroAPI -libroApi = Proxy diff --git a/lib/LiBro/WebService/Server.hs b/lib/LiBro/WebService/Server.hs deleted file mode 100644 index cb73d7e..0000000 --- a/lib/LiBro/WebService/Server.hs +++ /dev/null @@ -1,10 +0,0 @@ -module LiBro.WebService.Server where - -import LiBro.WebService.API -import Servant - -server :: Server LiBroAPI -server = return "Hello LiBro!" - -libro :: Application -libro = serve libroApi server diff --git a/lib/LiBro/WebService/State.hs b/lib/LiBro/WebService/State.hs new file mode 100644 index 0000000..6beec0f --- /dev/null +++ b/lib/LiBro/WebService/State.hs @@ -0,0 +1,25 @@ +module LiBro.WebService.State where + +import LiBro.Config +import LiBro.Data +import LiBro.Control +import Control.Concurrent + +data LiBroState = LiBroState + { config :: Config + , mvBlocking :: MVar Blocking + , mvData :: MVar LiBroData + } + +lsConfig :: LiBroState -> IO Config +lsConfig = return . config + +lsData :: LiBroState -> IO LiBroData +lsData = readMVar . mvData + +lsInit :: Config -> IO LiBroState +lsInit config = do + mvb <- newEmptyMVar + mvd <- newEmptyMVar + initData config mvb mvd + return $ LiBroState config mvb mvd diff --git a/libro-backend.cabal b/libro-backend.cabal index fda5d1d..fefc78d 100644 --- a/libro-backend.cabal +++ b/libro-backend.cabal @@ -41,8 +41,8 @@ library , LiBro.Data.Storage , LiBro.Data.SafeText , LiBro.Control - , LiBro.WebService.API - , LiBro.WebService.Server + , LiBro.WebService + , LiBro.WebService.State , LiBro.Util build-depends: aeson , attoparsec @@ -75,6 +75,7 @@ executable libro-backend test-suite libro-backend-test import: consumer default-extensions: OverloadedStrings + , QuasiQuotes , DeriveGeneric type: exitcode-stdio-1.0 hs-source-dirs: test @@ -91,6 +92,7 @@ test-suite libro-backend-test build-depends: libro-backend , hspec , hspec-wai + , hspec-wai-json , QuickCheck , quickcheck-text , generic-arbitrary @@ -108,3 +110,4 @@ test-suite libro-backend-test , text , transformers , vector + , wai diff --git a/server/Main.hs b/server/Main.hs index 93bc118..2b6a3a9 100644 --- a/server/Main.hs +++ b/server/Main.hs @@ -1,7 +1,7 @@ module Main where import LiBro.Config as Conf -import LiBro.WebService.Server +import LiBro.WebService import Network.Wai.Handler.Warp configuredMain :: Config -> IO () diff --git a/test/LiBro/WebServiceSpec.hs b/test/LiBro/WebServiceSpec.hs index ac6f6e9..33d2be5 100644 --- a/test/LiBro/WebServiceSpec.hs +++ b/test/LiBro/WebServiceSpec.hs @@ -2,9 +2,10 @@ module LiBro.WebServiceSpec where import Test.Hspec import Test.Hspec.Wai +import Test.Hspec.Wai.JSON import Test.Hspec.Wai.QuickCheck -import LiBro.WebService.Server +import LiBro.WebService import Data.ByteString spec :: Spec @@ -14,9 +15,15 @@ spec = describe "RESTful JSON web service" $ do helloLibro :: Spec helloLibro = describe "Dummy: hello libro!" $ with (return libro) $ do - describe "Hello endpoint" $ do + describe "Yay endpoint" $ do it "Respond with 200 greeting" $ do - get "/hello" `shouldRespondWith` "Hello LiBro!" {matchStatus = 200} + get "/yay" `shouldRespondWith` "Yay!" {matchStatus = 200} + + describe "Dummy person ID endpoint" $ do + it "Respond with IDs" $ do + get "/hello" `shouldRespondWith` + [json|{"personIDs":[17,42]}|] + {matchStatus = 200} describe "Any other endpoint" $ do it "Respond with 404" $ do diff --git a/test/run-all-tests.hs b/test/run-all-tests.hs index d5459a5..a048e30 100644 --- a/test/run-all-tests.hs +++ b/test/run-all-tests.hs @@ -10,6 +10,7 @@ import qualified LiBro.ConfigSpec as Config import qualified LiBro.ControlSpec as Control import qualified LiBro.TestUtilSpec as TestUtil import qualified LiBro.UtilSpec as Util +import qualified LiBro.WebServiceSpec as WebService withLibreOffice :: IO () -> IO () withLibreOffice runTests = do @@ -31,3 +32,4 @@ main = hspec $ aroundAll_ withLibreOffice $ do Control.spec TestUtil.spec Util.spec + WebService.spec