Safe Haskell | None |
---|---|
Language | Haskell2010 |
Users of this library should a data type representing all possible
routes available in a web application. It is recommended that
this type be named Route
, but this is not required.
Dispatch and Routing
In this example, we will write web application that maintains three counters. The end user will be able to perform various operations that manipulate the values of these counters and ask for their current value. We begin by defining our route type:
>>>
:{
data Counter = Red | Green | Blue deriving (Show,Read) data Route :: [Type] -> [Param] -> Bodiedness -> Type -> Type where AssignR :: Route '[Counter,Int] '[] 'Bodyless () IncrementR :: Route '[Counter] '[] 'Bodyless Int QueryR :: Route '[Counter] '[]Bodyless Int TotalR :: Route '[] '[] 'Bodyless Int data Meta captures querys request response = Meta { metaPath :: Path CaptureCodec captures , metaQuery :: Rec (Query CaptureCodec) querys , metaRequestBody :: RequestBody BodyCodec request , metaResponseBody :: ResponseBody BodyCodec response , metaMethod :: Text } int :: CaptureCodec Int int = showReadCaptureCodec counter :: CaptureCodec Counter counter = showReadCaptureCodec bodyUnit :: BodyCodec () bodyUnit = BodyCodec (pure "text/plain") (const "") (const (Right ())) bodyInt :: BodyCodec Int bodyInt = showReadBodyCodec meta :: Route captures querys request response -> Meta captures querys request response meta x = case x of AssignR -> Meta (match "assign" ./ capture counter ./ match "to" ./ capture int ./ end) qend bodyless (resp bodyUnit) "post" IncrementR -> Meta (match "increment" ./ capture counter ./ end) qend bodyless (resp bodyInt) "post" QueryR -> Meta (match "query" ./ capture counter ./ end) qend bodyless (resp bodyInt) "get" TotalR -> Meta (match "total" ./ end) qend bodyless (resp bodyInt) "get" :}
Now, we can start using our routes. To do this, we take functions that
trasa
exports and partially apply them to the route metadata that
we have created. We can start with prepare and link:
>>>
prepare = prepareWith (metaPath . meta) (metaQuery . meta) (metaRequestBody . meta)
>>>
:t prepare
prepare :: Route captures query request response -> Arguments captures query request (Prepared Route response)>>>
:{
link = linkWith (mapPath captureCodecToCaptureEncoding . metaPath . meta) (mapQuery captureCodecToCaptureEncoding . metaQuery . meta) :}
>>>
:t link
link :: Prepared Route response -> Url
Now we can use link to encode our routes:
>>>
link (prepare AssignR Green 5)
"/assign/Green/to/5"