2014-10-25 01:27:39 +02:00
|
|
|
{-# LANGUAGE DataKinds #-}
|
|
|
|
{-# LANGUAGE PolyKinds #-}
|
|
|
|
{-# LANGUAGE TypeFamilies #-}
|
|
|
|
{-# LANGUAGE DeriveGeneric #-}
|
|
|
|
{-# LANGUAGE TypeOperators #-}
|
2014-10-28 09:04:27 +01:00
|
|
|
{-# LANGUAGE FlexibleInstances #-}
|
2014-10-25 01:27:39 +02:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
2014-10-28 15:22:28 +01:00
|
|
|
{-# LANGUAGE QuasiQuotes #-}
|
2014-10-28 09:04:27 +01:00
|
|
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
2014-10-25 01:27:39 +02:00
|
|
|
|
|
|
|
import Control.Concurrent (forkIO, killThread)
|
|
|
|
import Control.Monad.Trans.Either
|
|
|
|
import Data.Aeson
|
|
|
|
import Data.Monoid
|
|
|
|
import Data.Proxy
|
|
|
|
import Data.Text
|
|
|
|
import GHC.Generics
|
|
|
|
import Network.URI
|
|
|
|
import Network.Wai
|
|
|
|
import Network.Wai.Handler.Warp
|
|
|
|
|
|
|
|
import Servant.API
|
|
|
|
import Servant.Client
|
2014-10-28 09:04:27 +01:00
|
|
|
import Servant.Docs
|
2014-10-25 01:27:39 +02:00
|
|
|
import Servant.Server
|
|
|
|
|
|
|
|
-- * Example
|
|
|
|
|
2014-10-28 09:04:27 +01:00
|
|
|
data Greet = Greet { _msg :: Text }
|
2014-10-25 01:27:39 +02:00
|
|
|
deriving (Generic, Show)
|
|
|
|
|
|
|
|
instance FromJSON Greet
|
|
|
|
instance ToJSON Greet
|
|
|
|
|
2014-10-28 09:04:27 +01:00
|
|
|
instance ToCapture (Capture "name" Text) where
|
|
|
|
toCapture _ = DocCapture "name" "name of the person to greet"
|
|
|
|
|
2014-10-28 09:14:10 +01:00
|
|
|
instance ToCapture (Capture "greetid" Text) where
|
|
|
|
toCapture _ = DocCapture "greetid" "identifier of the greet msg to remove"
|
|
|
|
|
2014-10-28 15:06:47 +01:00
|
|
|
instance ToParam (QueryParam "capital" Bool) where
|
2014-10-28 09:04:27 +01:00
|
|
|
toParam _ =
|
2014-10-28 15:06:47 +01:00
|
|
|
DocQueryParam "capital"
|
|
|
|
["true", "false"]
|
|
|
|
"Get the greeting message in uppercase (true) or not (false). Default is false."
|
2014-10-28 09:04:27 +01:00
|
|
|
|
|
|
|
instance ToSample Greet where
|
|
|
|
toSample Proxy = Just (encode g)
|
|
|
|
|
|
|
|
where g = Greet "Hello, haskeller!"
|
|
|
|
|
2014-10-25 01:27:39 +02:00
|
|
|
-- API specification
|
2014-10-28 15:22:28 +01:00
|
|
|
type TestApi =
|
2014-10-28 15:06:47 +01:00
|
|
|
"hello" :> Capture "name" Text :> QueryParam "capital" Bool :> Get Greet
|
2014-10-28 16:29:04 +01:00
|
|
|
:<|> "greet" :> ReqBody Greet :> Post Greet
|
2014-10-28 09:14:10 +01:00
|
|
|
:<|> "delete" :> Capture "greetid" Text :> Delete
|
2014-10-25 01:27:39 +02:00
|
|
|
|
2014-10-28 15:22:28 +01:00
|
|
|
type TestApi2 = [sitemap|
|
2014-10-28 17:32:22 +01:00
|
|
|
GET hello/name:Text/capital:Bool () -> Greet
|
|
|
|
POST greet Greet -> Greet
|
|
|
|
DELETE delete/greetid:Text ()
|
2014-10-28 15:22:28 +01:00
|
|
|
|]
|
|
|
|
|
2014-10-25 01:27:39 +02:00
|
|
|
testApi :: Proxy TestApi
|
|
|
|
testApi = Proxy
|
|
|
|
|
|
|
|
-- Server-side handlers
|
|
|
|
server :: Server TestApi
|
2014-10-28 09:14:10 +01:00
|
|
|
server = hello :<|> greet :<|> delete
|
2014-10-25 01:27:39 +02:00
|
|
|
|
|
|
|
where hello name Nothing = hello name (Just False)
|
|
|
|
hello name (Just False) = return . Greet $ "Hello, " <> name
|
|
|
|
hello name (Just True) = return . Greet . toUpper $ "Hello, " <> name
|
|
|
|
|
|
|
|
greet = return
|
|
|
|
|
2014-10-28 09:14:10 +01:00
|
|
|
delete _ = return ()
|
|
|
|
|
2014-10-25 01:27:39 +02:00
|
|
|
-- Client-side query functions
|
|
|
|
clientApi :: Client TestApi
|
|
|
|
clientApi = client testApi
|
|
|
|
|
|
|
|
getGreet :: Text -> Maybe Bool -> URI -> EitherT String IO Greet
|
|
|
|
postGreet :: Greet -> URI -> EitherT String IO Greet
|
2014-10-28 09:14:10 +01:00
|
|
|
deleteGreet :: Text -> URI -> EitherT String IO ()
|
|
|
|
getGreet :<|> postGreet :<|> deleteGreet = clientApi
|
2014-10-25 01:27:39 +02:00
|
|
|
|
|
|
|
-- Turn the server into a WAI app
|
|
|
|
test :: Application
|
|
|
|
test = serve testApi server
|
|
|
|
|
2014-10-28 09:14:10 +01:00
|
|
|
-- Documentation
|
2014-10-28 09:04:27 +01:00
|
|
|
docsGreet :: API
|
|
|
|
docsGreet = docs testApi
|
|
|
|
|
2014-10-25 01:27:39 +02:00
|
|
|
-- Run the server
|
|
|
|
runTestServer :: Port -> IO ()
|
|
|
|
runTestServer port = run port test
|
|
|
|
|
|
|
|
-- Run some queries against the server
|
|
|
|
main :: IO ()
|
|
|
|
main = do
|
|
|
|
tid <- forkIO $ runTestServer 8001
|
|
|
|
let Just uri = parseURI "http://localhost:8001"
|
|
|
|
print =<< runEitherT (getGreet "alp" (Just True) uri)
|
|
|
|
print =<< runEitherT (getGreet "alp" (Just False) uri)
|
|
|
|
let g = Greet "yo"
|
|
|
|
print =<< runEitherT (postGreet g uri)
|
2014-10-28 09:14:10 +01:00
|
|
|
print =<< runEitherT (deleteGreet "blah" uri)
|
2014-10-25 01:27:39 +02:00
|
|
|
killThread tid
|
2014-10-28 09:04:27 +01:00
|
|
|
putStrLn "\n---------\n"
|
|
|
|
printMarkdown docsGreet
|