on master help sign in
Merge pull request #7 from dlarsson/master
ec3bebeJulian Arni
.gitignore+16−2
@@ -1,3 +1,17 @@
1−.cabal-sandbox
2−cabal.sandbox.config
3dist
1dist
2+cabal-dev
3+*.o
4+*.hi
5+*.chi
6+*.chs.h
7+*.dyn_o
8+*.dyn_hi
9+.virtualenv
10+.hpc
11+.hsenv
12+.cabal-sandbox/
13+cabal.sandbox.config
14+cabal.config
15+*.prof
16+*.aux
17+*.hp
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+71−7
@@ -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 ++ [""]
@@ -583,6 +603,50 @@ instance (KnownSymbol sym, ToParam (QueryFlag sym), HasDocs sublayout)
583 paramP = Proxy :: Proxy (QueryFlag sym)
603 paramP = Proxy :: Proxy (QueryFlag sym)
584 action' = over params (|> toParam paramP) action
604 action' = over params (|> toParam paramP) action
585
605
606+
607+instance (KnownSymbol sym, ToParam (MatrixParam sym a), HasDocs sublayout)
608+ => HasDocs (MatrixParam sym a :> sublayout) where
609+
610+ docsFor Proxy (endpoint, action) =
611+ docsFor sublayoutP (endpoint', action')
612+
613+ where sublayoutP = Proxy :: Proxy sublayout
614+ paramP = Proxy :: Proxy (MatrixParam sym a)
615+ segment = endpoint ^. (path._last)
616+ segment' = action ^. (mxParams._last._1)
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]
624+ symP = Proxy :: Proxy sym
625+
626+
627+instance (KnownSymbol sym, {- ToParam (MatrixParams sym a), -} HasDocs sublayout)
628+ => HasDocs (MatrixParams sym a :> sublayout) where
629+
630+ docsFor Proxy (endpoint, action) =
631+ docsFor sublayoutP (endpoint', action)
632+
633+ where sublayoutP = Proxy :: Proxy sublayout
634+ endpoint' = over path (\p -> p ++ [";" ++ symbolVal symP ++ "=<value>"]) endpoint
635+ symP = Proxy :: Proxy sym
636+
637+
638+instance (KnownSymbol sym, {- ToParam (MatrixFlag sym), -} HasDocs sublayout)
639+ => HasDocs (MatrixFlag sym :> sublayout) where
640+
641+ docsFor Proxy (endpoint, action) =
642+ docsFor sublayoutP (endpoint', action)
643+
644+ where sublayoutP = Proxy :: Proxy sublayout
645+
646+ endpoint' = over path (\p -> p ++ [";" ++ symbolVal symP]) endpoint
647+ symP = Proxy :: Proxy sym
648+
649+
586instance HasDocs Raw where
650instance HasDocs Raw where
587 docsFor _proxy (endpoint, action) =
651 docsFor _proxy (endpoint, action) =
588 single endpoint action
652 single endpoint action