content: {-# LANGUAGE DataKinds #-}
  {-# LANGUAGE PolyKinds #-}
  {-# LANGUAGE TypeFamilies #-}
  {-# LANGUAGE DeriveGeneric #-}
  {-# LANGUAGE TypeOperators #-}
  {-# LANGUAGE OverloadedStrings #-}
  
  import Data.Aeson
  import Data.Monoid
  import Data.Proxy
  import Data.Text
  import GHC.Generics
  import Network.Wai
  import Network.Wai.Handler.Warp
  
  import Servant
  
  -- * Example
  
  -- | A greet message data type
  newtype Greet = Greet { msg :: Text }
    deriving (Generic, Show)
  
  instance FromJSON Greet
  instance ToJSON Greet
  
  -- API specification
  type TestApi =
         -- GET /hello/:name?capital={true, false}  returns a Greet as JSON
         "hello" :> Capture "name" Text :> QueryParam "capital" Bool :> Get Greet
  
         -- POST /greet with a Greet as JSON in the request body,
         --             returns a Greet as JSON
    :<|> "greet" :> ReqBody Greet :> Post Greet
  
         -- DELETE /greet/:greetid
    :<|> "greet" :> Capture "greetid" Text :> Delete
  
  testApi :: Proxy TestApi
  testApi = Proxy
  
  -- 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 'EitherT (Int, String) IO' monad.
  server :: Server TestApi
  server = helloH :<|> postGreetH :<|> deleteGreetH
  
    where helloH name Nothing = helloH name (Just False)
          helloH name (Just False) = return . Greet $ "Hello, " <> name
          helloH name (Just True) = return . Greet . toUpper $ "Hello, " <> name
  
          postGreetH greet = return greet
  
          deleteGreetH _ = return ()
  
  -- Turn the server into a WAI app. 'serve' is provided by servant,
  -- more precisely by the Servant.Server module.
  test :: Application
  test = serve testApi server
  
  -- Run the server.
  --
  -- 'run' comes from Network.Wai.Handler.Warp
  runTestServer :: Port -> IO ()
  runTestServer port = run port test
  
  -- Put this all to work!
  main :: IO ()
  main = runTestServer 8001
  