on master help sign in
Added support for matrix parameters
d81704aDaniel Larsson
example/greet.hs+8−1
@@ -36,6 +36,13 @@ instance ToParam (QueryParam "capital" Bool) where
36 "Get the greeting message in uppercase (true) or not (false). Default is false."
36 "Get the greeting message in uppercase (true) or not (false). Default is false."
37 Normal
37 Normal
38
38
39+instance ToParam (MatrixParam "lang" String) where
40+ toParam _ =
41+ DocQueryParam "lang"
42+ ["en", "sv", "fr"]
43+ "Get the greeting message selected language. Default is en."
44+ Normal
45+
39instance ToSample Greet where
46instance ToSample Greet where
40 toSample = Just $ Greet "Hello, haskeller!"
47 toSample = Just $ Greet "Hello, haskeller!"
41
48
@@ -47,7 +54,7 @@ instance ToSample Greet where
47-- API specification
54-- API specification
48type TestApi =
55type TestApi =
49 -- GET /hello/:name?capital={true, false} returns a Greet as JSON
56 -- GET /hello/:name?capital={true, false} returns a Greet as JSON
50− "hello" :> Capture "name" Text :> QueryParam "capital" Bool :> Get Greet
57+ "hello" :> MatrixParam "lang" String :> Capture "name" Text :> QueryParam "capital" Bool :> Get Greet
51
58
52 -- POST /greet with a Greet as JSON in the request body,
59 -- POST /greet with a Greet as JSON in the request body,
53 -- returns a Greet as JSON
60 -- returns a Greet as JSON
src/Servant/Docs.hs+41−14
@@ -216,6 +216,7 @@ data DocQueryParam = DocQueryParam
216 , _paramKind :: ParamKind
216 , _paramKind :: ParamKind
217 } deriving (Eq, Show)
217 } deriving (Eq, Show)
218
218
219+
219-- | Type of GET parameter:
220-- | Type of GET parameter:
220--
221--
221-- - Normal corresponds to @QueryParam@, i.e your usual GET parameter
222-- - Normal corresponds to @QueryParam@, i.e your usual GET parameter
@@ -265,11 +266,12 @@ defResponse = Response 200 []
265-- You can tweak an 'Action' (like the default 'defAction') with these lenses
266-- You can tweak an 'Action' (like the default 'defAction') with these lenses
266-- to transform an action and add some information to it.
267-- to transform an action and add some information to it.
267data Action = Action
268data Action = Action
268− { _captures :: [DocCapture] -- type collected + user supplied info
269+ { _captures :: [DocCapture] -- type collected + user supplied info
269− , _headers :: [Text] -- type collected
270+ , _headers :: [Text] -- type collected
271+ , _params :: [DocQueryParam] -- type collected + user supplied info
270− , _params :: [DocQueryParam] -- type collected + user supplied info
272+ , _mxParams :: [(String, [DocQueryParam])] -- type collected + user supplied info
271− , _rqbody :: Maybe ByteString -- user supplied
273+ , _rqbody :: Maybe ByteString -- user supplied
272− , _response :: Response -- user supplied
274+ , _response :: Response -- user supplied
273 } deriving (Eq, Show)
275 } deriving (Eq, Show)
274
276
275-- Default 'Action'. Has no 'captures', no GET 'params', expects
277-- Default 'Action'. Has no 'captures', no GET 'params', expects
@@ -278,12 +280,13 @@ data Action = Action
278-- Tweakable with lenses.
280-- Tweakable with lenses.
279--
281--
280-- > λ> defAction
282-- > λ> defAction
281−-- > Action {_captures = [], _params = [], _rqbody = Nothing, _response = Response {_respStatus = 200, _respBody = Nothing}}
283+-- > Action {_captures = [], _headers = [], _params = [], _mxParams = [], _rqbody = Nothing, _response = Response {_respStatus = 200, _respBody = Nothing}}
282-- > λ> defAction & response.respStatus .~ 201
284-- > λ> defAction & response.respStatus .~ 201
283−-- > Action {_captures = [], _params = [], _rqbody = Nothing, _response = Response {_respStatus = 201, _respBody = Nothing}}
285+-- > Action {_captures = [], _headers = [], _params = [], _mxParams = [], _rqbody = Nothing, _response = Response {_respStatus = 201, _respBody = Nothing}}
284defAction :: Action
286defAction :: Action
285defAction =
287defAction =
286 Action []
288 Action []
289+ []
287 []
290 []
288 []
291 []
289 Nothing
292 Nothing
@@ -393,6 +396,7 @@ markdown = unlines . concat . map (uncurry printEndpoint) . HM.toList
393 replicate len '-' :
396 replicate len '-' :
394 "" :
397 "" :
395 capturesStr (action ^. captures) ++
398 capturesStr (action ^. captures) ++
399+ mxParamsStr (action ^. mxParams) ++
396 headersStr (action ^. headers) ++
400 headersStr (action ^. headers) ++
397 paramsStr (action ^. params) ++
401 paramsStr (action ^. params) ++
398 rqbodyStr (action ^. rqbody) ++
402 rqbodyStr (action ^. rqbody) ++
@@ -413,6 +417,22 @@ markdown = unlines . concat . map (uncurry printEndpoint) . HM.toList
413 captureStr cap =
417 captureStr cap =
414 "- *" ++ (cap ^. capSymbol) ++ "*: " ++ (cap ^. capDesc)
418 "- *" ++ (cap ^. capSymbol) ++ "*: " ++ (cap ^. capDesc)
415
419
420+ mxParamsStr :: [(String, [DocQueryParam])] -> [String]
421+ mxParamsStr [] = []
422+ mxParamsStr l =
423+ "**Matrix Parameters**: " :
424+ "" :
425+ map segmentStr l ++
426+ "" :
427+ []
428+ segmentStr :: (String, [DocQueryParam]) -> String
429+ segmentStr (segment, l) = unlines $
430+ ("**" ++ segment ++ "**: ") :
431+ "" :
432+ map paramStr l ++
433+ "" :
434+ []
435+
416 headersStr :: [Text] -> [String]
436 headersStr :: [Text] -> [String]
417 headersStr [] = []
437 headersStr [] = []
418 headersStr l = [""] ++ map headerStr l ++ [""]
438 headersStr l = [""] ++ map headerStr l ++ [""]
@@ -584,15 +604,23 @@ instance (KnownSymbol sym, ToParam (QueryFlag sym), HasDocs sublayout)
584 action' = over params (|> toParam paramP) action
604 action' = over params (|> toParam paramP) action
585
605
586
606
587−instance (KnownSymbol sym, {- ToParam (MatrixParam sym a), -} HasDocs sublayout)
607+instance (KnownSymbol sym, ToParam (MatrixParam sym a), HasDocs sublayout)
588 => HasDocs (MatrixParam sym a :> sublayout) where
608 => HasDocs (MatrixParam sym a :> sublayout) where
589
609
590 docsFor Proxy (endpoint, action) =
610 docsFor Proxy (endpoint, action) =
591− docsFor sublayoutP (endpoint', action)
611+ docsFor sublayoutP (endpoint', action')
592
612
593 where sublayoutP = Proxy :: Proxy sublayout
613 where sublayoutP = Proxy :: Proxy sublayout
594−
614+ paramP = Proxy :: Proxy (MatrixParam sym a)
615+ segment = endpoint ^. (path._last)
616+ segment' = action ^. (mxParams._last._1)
595− endpoint' = over path (\p -> p++";"++symbolVal symP) endpoint
617+ endpoint' = over (path._last) (\p -> p ++ ";" ++ symbolVal symP ++ "=<value>") endpoint
618+
619+ action' = if segment' /= segment
620+ -- This is the first matrix parameter for this segment, insert a new entry into the mxParams list
621+ then over mxParams (|> (segment, [toParam paramP])) action
622+ -- We've already inserted a matrix parameter for this segment, append to the existing list
623+ else action & mxParams._last._2 <>~ [toParam paramP]
596 symP = Proxy :: Proxy sym
624 symP = Proxy :: Proxy sym
597
625
598
626
@@ -603,8 +631,7 @@ instance (KnownSymbol sym, {- ToParam (MatrixParams sym a), -} HasDocs sublayout
603 docsFor sublayoutP (endpoint', action)
631 docsFor sublayoutP (endpoint', action)
604
632
605 where sublayoutP = Proxy :: Proxy sublayout
633 where sublayoutP = Proxy :: Proxy sublayout
606−
607− endpoint' = over path (\p -> p++";"++symbolVal symP) endpoint
634+ endpoint' = over path (\p -> p ++ [";" ++ symbolVal symP ++ "=<value>"]) endpoint
608 symP = Proxy :: Proxy sym
635 symP = Proxy :: Proxy sym
609
636
610
637
@@ -616,7 +643,7 @@ instance (KnownSymbol sym, {- ToParam (MatrixFlag sym), -} HasDocs sublayout)
616
643
617 where sublayoutP = Proxy :: Proxy sublayout
644 where sublayoutP = Proxy :: Proxy sublayout
618
645
619− endpoint' = over path (\p -> p++";"++symbolVal symP) endpoint
646+ endpoint' = over path (\p -> p ++ [";" ++ symbolVal symP]) endpoint
620 symP = Proxy :: Proxy sym
647 symP = Proxy :: Proxy sym
621
648
622
649