2016-02-07 06:44:38 +03:00
|
|
|
{-# LANGUAGE DataKinds #-}
|
|
|
|
{-# LANGUAGE DeriveGeneric #-}
|
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
{-# LANGUAGE PolyKinds #-}
|
2017-09-20 20:57:06 +03:00
|
|
|
{-# LANGUAGE TypeApplications #-}
|
2016-02-07 06:44:38 +03:00
|
|
|
{-# LANGUAGE TypeFamilies #-}
|
|
|
|
{-# LANGUAGE TypeOperators #-}
|
|
|
|
|
2017-02-27 22:46:08 +03:00
|
|
|
import Control.Monad.IO.Class (liftIO)
|
2018-09-16 22:10:22 +03:00
|
|
|
import Control.Monad.Reader (reader)
|
2016-02-07 06:44:38 +03:00
|
|
|
import Data.Aeson
|
2016-03-07 07:28:26 +03:00
|
|
|
import Data.Bool
|
2017-02-27 22:46:08 +03:00
|
|
|
import Data.Char (toUpper)
|
|
|
|
import qualified Data.List as L
|
2018-09-16 22:10:22 +03:00
|
|
|
import Data.Maybe (fromMaybe)
|
2016-02-07 06:44:38 +03:00
|
|
|
import Data.Monoid
|
|
|
|
import Data.Proxy
|
2017-02-27 22:46:08 +03:00
|
|
|
import Data.Text hiding (head, length, map,
|
|
|
|
null, toUpper)
|
|
|
|
import qualified Data.Text as T
|
|
|
|
import qualified Data.Text.IO as T
|
2016-02-07 06:44:38 +03:00
|
|
|
import GHC.Generics
|
|
|
|
import Servant.Server.Internal.SnapShims
|
2017-02-27 22:46:08 +03:00
|
|
|
import Snap.Core
|
|
|
|
import Snap.Http.Server
|
2016-02-07 06:44:38 +03:00
|
|
|
|
2017-02-27 22:46:08 +03:00
|
|
|
import Servant
|
2016-02-07 06:44:38 +03:00
|
|
|
import Servant.Server
|
2016-02-19 01:56:26 +03:00
|
|
|
-- import Snap.Util.FileServe
|
2018-09-16 22:10:22 +03:00
|
|
|
import System.Environment (lookupEnv)
|
2016-02-07 06:44:38 +03:00
|
|
|
import API
|
2017-02-27 22:46:08 +03:00
|
|
|
import Snap
|
2016-02-07 06:44:38 +03:00
|
|
|
|
|
|
|
-- * Example
|
|
|
|
|
|
|
|
-- | A greet message data type
|
|
|
|
newtype Greet = Greet { _msg :: Text }
|
|
|
|
deriving (Generic, Show)
|
|
|
|
|
|
|
|
instance FromJSON Greet
|
|
|
|
instance ToJSON Greet
|
|
|
|
|
|
|
|
testApi :: Proxy API
|
|
|
|
testApi = Proxy
|
|
|
|
|
2018-09-16 22:10:22 +03:00
|
|
|
data App = App { appStaticDir :: String }
|
2016-02-19 01:56:26 +03:00
|
|
|
|
2016-02-07 06:44:38 +03:00
|
|
|
-- Server-side handlers.
|
|
|
|
--
|
|
|
|
-- There's one handler per endpoint, which, just like in the type
|
|
|
|
-- that represents the API, are glued together using :<|>.
|
|
|
|
--
|
|
|
|
-- Each handler runs in the 'ExceptT ServantErr IO' monad.
|
2017-09-20 20:57:06 +03:00
|
|
|
server :: Server API '[BasicAuthCheck (Handler App App) ()] (Handler App App)
|
|
|
|
server = return () :<|> return 100 :<|> sayhi :<|> dbl
|
|
|
|
:<|> multi :<|> qna :<|> serveSecret
|
2018-09-16 22:10:22 +03:00
|
|
|
:<|> statics
|
2016-07-19 19:25:58 +03:00
|
|
|
where sayhi :: Maybe Text -> [Text] -> Bool -> Handler App App Text
|
|
|
|
sayhi nm greetings withGusto = case nm of
|
|
|
|
Nothing -> return ("Sorry, who are you?" :: Text)
|
2016-03-07 07:28:26 +03:00
|
|
|
Just n -> do
|
2016-07-19 19:25:58 +03:00
|
|
|
let modifier = bool id T.toUpper withGusto
|
2016-03-07 07:28:26 +03:00
|
|
|
greetPart
|
|
|
|
| null greetings = "Hi, "
|
2016-07-19 19:25:58 +03:00
|
|
|
| length greetings == 1 = L.head greetings <> ", "
|
|
|
|
| otherwise = T.intercalate ", " (L.init greetings)
|
|
|
|
<> ", and " <> L.last greetings <> ", "
|
|
|
|
return . modifier $ greetPart <> n
|
2017-03-02 19:06:10 +03:00
|
|
|
dbl x = if x `elem` [4,13]
|
|
|
|
then throwError $ err500 { errBody = "No unlucky numbers please" }
|
|
|
|
else return $ x * 2
|
2016-05-16 21:32:16 +03:00
|
|
|
multi = return . bool "Box unchecked" "Box Checked"
|
2017-02-27 22:46:08 +03:00
|
|
|
qna q = do
|
|
|
|
liftIO $ do
|
|
|
|
putStrLn $ "qna got: " ++ show q
|
|
|
|
T.putStrLn $ unQuestion q
|
|
|
|
return $ Answer $ unQuestion q
|
2017-09-20 20:57:06 +03:00
|
|
|
serveSecret _ = do
|
|
|
|
req <- getRequest
|
|
|
|
liftIO $ putStrLn (show req)
|
|
|
|
return 101
|
2018-09-16 22:10:22 +03:00
|
|
|
statics = do
|
|
|
|
staticDir <- reader appStaticDir
|
|
|
|
serveDirectory staticDir
|
2016-02-07 06:44:38 +03:00
|
|
|
|
|
|
|
-- Turn the server into a WAI app. 'serve' is provided by servant,
|
|
|
|
-- more precisely by the Servant.Server module.
|
2016-09-18 04:32:43 +03:00
|
|
|
test :: Handler App App ()
|
2017-09-20 20:57:06 +03:00
|
|
|
test = serveSnapWithContext testApi
|
|
|
|
(BasicAuthCheck (\_ -> return @(Handler App App) (Authorized ())) :. EmptyContext) server
|
2016-02-07 06:44:38 +03:00
|
|
|
|
2016-02-19 01:56:26 +03:00
|
|
|
initApp :: SnapletInit App App
|
|
|
|
initApp = makeSnaplet "myapp" "example" Nothing $ do
|
2018-09-16 22:10:22 +03:00
|
|
|
staticDir <- fromMaybe "static" <$> liftIO (lookupEnv "STATIC_DIR")
|
2016-09-18 04:32:43 +03:00
|
|
|
addRoutes [("", test)
|
2016-03-12 12:56:13 +03:00
|
|
|
,("", serveDirectory "static")
|
2016-02-19 01:56:26 +03:00
|
|
|
]
|
2018-09-16 22:10:22 +03:00
|
|
|
return (App staticDir)
|
2016-02-19 01:56:26 +03:00
|
|
|
|
2016-02-07 06:44:38 +03:00
|
|
|
-- Put this all to work!
|
|
|
|
main :: IO ()
|
2016-02-19 01:56:26 +03:00
|
|
|
main = serveSnaplet mempty initApp
|