-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathMain.hs
109 lines (101 loc) · 3.3 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Main (main) where
import qualified Control.Concurrent.MVar
import Control.Exception (onException)
import Control.Monad.State.Strict (StateT, get, put, runStateT)
import Data.Int (Int32)
import Data.List (find)
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Network.Wai
import qualified Network.Wai.Handler.Warp
import qualified Network.Wai.Middleware.RequestLogger
import qualified Petstore.API.Api as Petstore
import qualified Petstore.API.Response.CreatePets as Petstore
import qualified Petstore.API.Response.ListPets as Petstore
import qualified Petstore.API.Response.ShowPetById as Petstore
import qualified Petstore.API.Schemas.Error as Petstore
import qualified Petstore.API.Schemas.Pet as Petstore
import qualified Petstore.API.Schemas.Pets as Petstore
main :: IO ()
main = do
-- This tiny example stores the application state in one, central MVar
petsRef <- Control.Concurrent.MVar.newMVar []
let port = 8080
putStrLn ("Running Petstore on port " <> show port)
Network.Wai.Handler.Warp.run port $
Network.Wai.Middleware.RequestLogger.logStdoutDev $
Petstore.application
(runHandler petsRef)
petstore
-- In case the route can not be found in the petstore, we return
-- a 404 error
( \_request respond ->
respond (Network.Wai.responseLBS (toEnum 404) [] "Not found")
)
-- | Runs a handler into IO
runHandler ::
-- | Our global state MVar
Control.Concurrent.MVar.MVar Petstore.Pets ->
-- | The Wai request that matched the handler
Network.Wai.Request ->
-- | The handler itself
StateT Petstore.Pets IO a ->
IO a
runHandler stateRef _request action = do
state <- Control.Concurrent.MVar.takeMVar stateRef
(result, newState) <-
runStateT action state
`onException` Control.Concurrent.MVar.putMVar stateRef state
Control.Concurrent.MVar.putMVar stateRef newState
pure result
-- | The API implementation.
petstore :: Petstore.Api (StateT Petstore.Pets IO)
petstore =
Petstore.Api {createPets, listPets, showPetById}
createPets :: StateT Petstore.Pets IO Petstore.CreatePetsResponse
createPets = do
-- Set a few hardcoded pets to the state
put
[ Petstore.Pet
{ id = 1,
name = "Mila",
tag = Just "🐶"
},
Petstore.Pet
{ id = 2,
name = "바다거북",
tag = Just "🐢"
},
Petstore.Pet
{ id = 3,
name = "Edda",
tag = Just "🐶"
}
]
pure Petstore.CreatePetsResponse201
listPets :: Maybe Int32 -> StateT Petstore.Pets IO Petstore.ListPetsResponse
listPets limit = do
allPets <- get
let pets = take (maybe maxBound fromIntegral limit) allPets
pure (Petstore.ListPetsResponse200 pets Nothing)
showPetById :: Text -> StateT Petstore.Pets IO Petstore.ShowPetByIdResponse
showPetById petId = do
allPets <- get
case find
(\Petstore.Pet {id} -> Text.pack (show id) == petId)
allPets of
Nothing ->
pure $
Petstore.ShowPetByIdDefaultResponse
(toEnum 404)
( Petstore.Error
{ code = 1,
message = "Pet not found"
}
)
Just pet ->
pure $
Petstore.ShowPetByIdResponse200 pet