on 1fef813 help sign in
servant/example/greet.hs
116 lines 4.0 kB history raw
1{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE DeriveGeneric #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE MultiParamTypeClasses #-}
5{-# LANGUAGE OverloadedStrings #-}
6{-# LANGUAGE TypeOperators #-}
7{-# OPTIONS_GHC -fno-warn-orphans #-}
8import Data.Aeson
9import Data.Proxy
10import Data.String.Conversions
11import Data.Text (Text)
12import GHC.Generics
13import Servant.API
14import Servant.Docs
16-- * Example
18-- | A greet message data type
19newtype Greet = Greet Text
20 deriving (Generic, Show)
22-- | We can get JSON support automatically. This will be used to parse
23-- and encode a Greeting as 'JSON'.
24instance FromJSON Greet
25instance ToJSON Greet
27-- | We can also implement 'MimeRender' for additional formats like 'PlainText'.
28instance MimeRender PlainText Greet where
29 toByteString Proxy (Greet s) = "\"" <> cs s <> "\""
31-- We add some useful annotations to our captures,
32-- query parameters and request body to make the docs
33-- really helpful.
34instance ToCapture (Capture "name" Text) where
35 toCapture _ = DocCapture "name" "name of the person to greet"
37instance ToCapture (Capture "greetid" Text) where
38 toCapture _ = DocCapture "greetid" "identifier of the greet msg to remove"
40instance ToParam (QueryParam "capital" Bool) where
41 toParam _ =
42 DocQueryParam "capital"
43 ["true", "false"]
44 "Get the greeting message in uppercase (true) or not (false).\
45 \Default is false."
46 Normal
48instance ToParam (MatrixParam "lang" String) where
49 toParam _ =
50 DocQueryParam "lang"
51 ["en", "sv", "fr"]
52 "Get the greeting message selected language. Default is en."
53 Normal
55instance ToSample Greet where
56 toSample = Just $ Greet "Hello, haskeller!"
58 toSamples =
59 [ ("If you use ?capital=true", Greet "HELLO, HASKELLER")
60 , ("If you use ?capital=false", Greet "Hello, haskeller")
61 ]
63-- We define some introductory sections, these will appear at the top of the
64-- documentation.
65--
66-- We pass them in with 'docsWith', below. If you only want to add
67-- introductions, you may use 'docsWithIntros'
68intro1 :: DocIntro
69intro1 = DocIntro "On proper introductions." -- The title
70 [ "Hello there."
71 , "As documentation is usually written for humans, it's often useful \
72 \to introduce concepts with a few words." ] -- Elements are paragraphs
74intro2 :: DocIntro
75intro2 = DocIntro "This title is below the last"
76 [ "You'll also note that multiple intros are possible." ]
79-- API specification
80type TestApi =
81 -- GET /hello/:name?capital={true, false} returns a Greet as JSON or PlainText
82 "hello" :> MatrixParam "lang" String :> Capture "name" Text :> QueryParam "capital" Bool :> Get '[JSON, PlainText] Greet
84 -- POST /greet with a Greet as JSON in the request body,
85 -- returns a Greet as JSON
86 :<|> "greet" :> ReqBody '[JSON] Greet :> Post '[JSON] Greet
88 -- DELETE /greet/:greetid
89 :<|> "greet" :> Capture "greetid" Text :> Delete
91testApi :: Proxy TestApi
92testApi = Proxy
94-- Build some extra information for the DELETE /greet/:greetid endpoint. We
95-- want to add documentation about a secret unicorn header and some extra
96-- notes.
97extra :: ExtraInfo TestApi
98extra =
99 extraInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $
100 defAction & headers <>~ ["unicorns"]
101 & notes <>~ [ DocNote "Title" ["This is some text"]
102 , DocNote "Second secton" ["And some more"]
103 ]
105-- Generate the data that lets us have API docs. This
106-- is derived from the type as well as from
107-- the 'ToCapture', 'ToParam' and 'ToSample' instances from above.
108--
109-- If you didn't want intros and extra information, you could just call:
110--
111-- > docs testAPI :: API
112docsGreet :: API
113docsGreet = docsWith [intro1, intro2] extra testApi
115main :: IO ()
116main = putStrLn $ markdown docsGreet