git.iko.soy/typeable/servant
on master help sign in
haddocks for all 3 forms of query params (phew)
commit77d52083f1ae94f1d97c9cb2a4e7813362e7cc89 authorAlp Mestanogullari <alpmestan@gmail.com> dateSat 22 Nov 2014, 18:53 (12 years ago) parentc47f4ae
2 files changed+153−10
src/Servant/API/Capture.hs+1−1 src/Servant/API/QueryParam.hs+152−9
src/Servant/API/Capture.hs+1−1
@@ -94,7 +94,7 @@ instance (KnownSymbol capture, ToText a, HasClient sublayout)
9494 where p = unpack (toText val)
9595
9696-- | @"books" :> 'Capture' "isbn" Text@ will appear as
97−-- @/books/:isbn@ in the docs
97+-- @/books/:isbn@ in the docs.
9898instance (KnownSymbol sym, ToCapture (Capture sym a), HasDocs sublayout)
9999 => HasDocs (Capture sym a :> sublayout) where
100100
src/Servant/API/QueryParam.hs+152−9
@@ -21,15 +21,36 @@ import Servant.Common.Text
2121import Servant.Docs
2222import Servant.Server
2323
24−-- * Single query string parameter lookup
25−
26−-- | You must implement:
24+-- | Lookup the value associated to the @sym@ query string parameter
25+-- and try to extract it as a value of type @a@.
26+--
27+-- Example:
2728--
28−-- - a @'FromText' a@ instance for serving
29−-- - a @'ToText' a@ instance for (client-side) querying
30−-- - a @'ToParam' ('QueryParam' sym a)@ instance for automatic documentation generation
29+-- > -- /books?author=<author name>
30+-- > type MyApi = "books" :> QueryParam "author" Text :> Get [Book]
3131data QueryParam sym a
3232
33+-- | If you use @'QueryParam' "author" Text@ in one of the endpoints for your API,
34+-- this automatically requires your server-side handler to be a function
35+-- that takes an argument of type @'Maybe' 'Text'@.
36+--
37+-- This lets servant worry about looking it up in the query string
38+-- and turning it into a value of the type you specify, enclosed
39+-- in 'Maybe', because it may not be there and servant would then
40+-- hand you 'Nothing'.
41+--
42+-- You can control how it'll be converted from 'Text' to your type
43+-- by simply providing an instance of 'FromText' for your type.
44+--
45+-- Example:
46+--
47+-- > type MyApi = "books" :> QueryParam "author" Text :> Get [Book]
48+-- >
49+-- > server :: Server MyApi
50+-- > server = getBooksBy
51+-- > where getBooksBy :: Maybe Text -> EitherT (Int, String) IO [Book]
52+-- > getBooksBy Nothing = ...return all books...
53+-- > getBooksBy (Just author) = ...return books by the given author...
3354instance (KnownSymbol sym, FromText a, HasServer sublayout)
3455 => HasServer (QueryParam sym a :> sublayout) where
3556
@@ -49,6 +70,31 @@ instance (KnownSymbol sym, FromText a, HasServer sublayout)
4970
5071 where paramname = cs $ symbolVal (Proxy :: Proxy sym)
5172
73+-- | If you use a 'QueryParam' in one of your endpoints in your API,
74+-- the corresponding querying function will automatically take
75+-- an additional argument of the type specified by your 'QueryParam',
76+-- enclosed in Maybe.
77+--
78+-- If you give Nothing, nothing will be added to the query string.
79+--
80+-- If you give a non-'Nothing' value, this function will take care
81+-- of inserting a textual representation of this value in the query string.
82+--
83+-- You can control how values for your type are turned into
84+-- text by specifying a 'ToText' instance for your type.
85+--
86+-- Example:
87+--
88+-- > type MyApi = "books" :> QueryParam "author" Text :> Get [Book]
89+-- >
90+-- > myApi :: Proxy MyApi
91+-- > myApi = Proxy
92+-- >
93+-- > getBooksBy :: Maybe Text -> BaseUrl -> EitherT String IO [Book]
94+-- > getBooksBy = client myApi
95+-- > -- then you can just use "getBooksBy" to query that endpoint.
96+-- > -- 'getBooksBy Nothing' for all books
97+-- > -- 'getBooksBy (Just "Isaac Asimov")' to get all books by Isaac Asimov
5298instance (KnownSymbol sym, ToText a, HasClient sublayout)
5399 => HasClient (QueryParam sym a :> sublayout) where
54100
@@ -74,9 +120,38 @@ instance (KnownSymbol sym, ToParam (QueryParam sym a), HasDocs sublayout)
74120 paramP = Proxy :: Proxy (QueryParam sym a)
75121 action' = over params (|> toParam paramP) action
76122
77−-- | Retrieve a list from the query string.
123+-- | Lookup the values associated to the @sym@ query string parameter
124+-- and try to extract it as a value of type @[a]@. This is typically
125+-- meant to support query string parameters of the form
126+-- @param[]=val1&param[]=val2@ and so on. Note that servant doesn't actually
127+-- require the @[]@s and will fetch the values just fine with
128+-- @param=val1&param=val2@, too.
129+--
130+-- Example:
131+--
132+-- > -- /books?authors[]=<author1>&authors[]=<author2>&...
133+-- > type MyApi = "books" :> QueryParams "authors" Text :> Get [Book]
78134data QueryParams sym a
79135
136+-- | If you use @'QueryParams' "authors" Text@ in one of the endpoints for your API,
137+-- this automatically requires your server-side handler to be a function
138+-- that takes an argument of type @['Text']@.
139+--
140+-- This lets servant worry about looking up 0 or more values in the query string
141+-- associated to @authors@ and turning each of them into a value of
142+-- the type you specify.
143+--
144+-- You can control how the individual values are converted from 'Text' to your type
145+-- by simply providing an instance of 'FromText' for your type.
146+--
147+-- Example:
148+--
149+-- > type MyApi = "books" :> QueryParams "authors" Text :> Get [Book]
150+-- >
151+-- > server :: Server MyApi
152+-- > server = getBooksBy
153+-- > where getBooksBy :: [Text] -> EitherT (Int, String) IO [Book]
154+-- > getBooksBy authors = ...return all books by these authors...
80155instance (KnownSymbol sym, FromText a, HasServer sublayout)
81156 => HasServer (QueryParams sym a :> sublayout) where
82157
@@ -98,6 +173,33 @@ instance (KnownSymbol sym, FromText a, HasServer sublayout)
98173 convert Nothing = Nothing
99174 convert (Just v) = fromText v
100175
176+-- | If you use a 'QueryParams' in one of your endpoints in your API,
177+-- the corresponding querying function will automatically take
178+-- an additional argument, a list of values of the type specified
179+-- by your 'QueryParams'.
180+--
181+-- If you give an empty list, nothing will be added to the query string.
182+--
183+-- Otherwise, this function will take care
184+-- of inserting a textual representation of your values in the query string,
185+-- under the same query string parameter name.
186+--
187+-- You can control how values for your type are turned into
188+-- text by specifying a 'ToText' instance for your type.
189+--
190+-- Example:
191+--
192+-- > type MyApi = "books" :> QueryParams "authors" Text :> Get [Book]
193+-- >
194+-- > myApi :: Proxy MyApi
195+-- > myApi = Proxy
196+-- >
197+-- > getBooksBy :: [Text] -> BaseUrl -> EitherT String IO [Book]
198+-- > getBooksBy = client myApi
199+-- > -- then you can just use "getBooksBy" to query that endpoint.
200+-- > -- 'getBooksBy []' for all books
201+-- > -- 'getBooksBy ["Isaac Asimov", "Robert A. Heinlein"]'
202+-- > -- to get all books by Asimov and Heinlein
101203instance (KnownSymbol sym, ToText a, HasClient sublayout)
102204 => HasClient (QueryParams sym a :> sublayout) where
103205
@@ -122,9 +224,29 @@ instance (KnownSymbol sym, ToParam (QueryParams sym a), HasDocs sublayout)
122224 paramP = Proxy :: Proxy (QueryParams sym a)
123225 action' = over params (|> toParam paramP) action
124226
125−-- | Retrieve a value-less boolean from the query string.
126−data QueryFlag a
227+-- | Lookup a potentially value-less query string parameter
228+-- with boolean semantics. If the param @sym@ is there without any value,
229+-- or if it's there with value "true" or "1", it's interpreted as 'True'.
230+-- Otherwise, it's interpreted as 'False'.
231+--
232+-- Example:
233+--
234+-- > -- /books?published
235+-- > type MyApi = "books" :> QueryFlag "published" :> Get [Book]
236+data QueryFlag sym
127237
238+-- | If you use @'QueryFlag' "published"@ in one of the endpoints for your API,
239+-- this automatically requires your server-side handler to be a function
240+-- that takes an argument of type 'Bool'.
241+--
242+-- Example:
243+--
244+-- > type MyApi = "books" :> QueryFlag "published" :> Get [Book]
245+-- >
246+-- > server :: Server MyApi
247+-- > server = getBooks
248+-- > where getBooks :: Bool -> EitherT (Int, String) IO [Book]
249+-- > getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument...
128250instance (KnownSymbol sym, HasServer sublayout)
129251 => HasServer (QueryFlag sym :> sublayout) where
130252
@@ -144,6 +266,27 @@ instance (KnownSymbol sym, HasServer sublayout)
144266 examine v | v == "true" || v == "1" || v == "" = True
145267 | otherwise = False
146268
269+-- | If you use a 'QueryFlag' in one of your endpoints in your API,
270+-- the corresponding querying function will automatically take
271+-- an additional 'Bool' argument.
272+--
273+-- If you give 'False', nothing will be added to the query string.
274+--
275+-- Otherwise, this function will insert a value-less query string
276+-- parameter under the name associated to your 'QueryFlag'.
277+--
278+-- Example:
279+--
280+-- > type MyApi = "books" :> QueryFlag "published" :> Get [Book]
281+-- >
282+-- > myApi :: Proxy MyApi
283+-- > myApi = Proxy
284+-- >
285+-- > getBooks :: Bool -> BaseUrl -> EitherT String IO [Book]
286+-- > getBooks = client myApi
287+-- > -- then you can just use "getBooks" to query that endpoint.
288+-- > -- 'getBooksBy False' for all books
289+-- > -- 'getBooksBy True' to only get _already published_ books
147290instance (KnownSymbol sym, HasClient sublayout)
148291 => HasClient (QueryFlag sym :> sublayout) where
149292