Handling Requests
We learned about the core architecture components in the previous chapters. Now, let us use them to extract information from requests.
Query Parameters
If you expect a query parameter in your handler, use the queryParam
middleware:
myHandler ::
StdHandler h m
'[RequiredQueryParam "limit" Integer]
[RequiredHeader "Content-Type" Text, Body String] =>
RequestHandler h req
myHandler =
queryParam @"limit" @Integer errorHandler $
proc request -> do
let limit :: Integer
limit = pick @(RequiredQueryParam "limit" Integer) $ from request
....
errorHandler ::
StdHandler h m '[] [RequiredHeader "Content-Type" Text, Body String] =>
h (Linked req Request, Either ParamNotFound ParamParseError) Response
errorHandler = proc (_, err) -> unlinkA <<< respondA HTTP.badRequest400 "text/plain" -< show err
If the query parameter is missing or invalid, the errorHandler
will be invoked to generate a response. There is also
an optionalQueryParam
middleware that can be used when the query parameter is not required.
Header Values
Extracting header values from a request is very similar to query parameters:
-- Some type representing the ETag header value
data ETag = ....
-- This instance is used to parse the ETag value
instance FromHttpApiData ETag where
....
myHandler ::
StdHandler h m '[RequiredHeader "If-Match" ETag] '[] =>
RequestHandler h req
myHandler =
header @"If-Match" @ETag errorHandler $
proc request -> do
let etag :: ETag
etag = pick @(RequiredHeader "If-Match" ETag) $ from request
....
Body
You can parse the request body to a Haskell value using the requestBody
middleware:
-- Some type representing a PNG image
data PNGImage = ....
-- This instance is used to parse the body
instance FromByteString PNGImage where
....
myHandler ::
StdHandler h m '[Body PNGImage] '[] =>
RequestHandler h req
myHandler =
requestBody @PNGImage (Just "image/png") errorHandler $
proc request -> do
let img :: PNGImage
img = pick @(Body PNGImage) $ from request
....
Use the jsonRequestBody
middleware to parse a JSON
request body:
data Person = ....
-- This instance is used to parse the body
instance FromJSON Person where
....
myHandler ::
StdHandler h m '[JSONBody Person] '[] =>
RequestHandler h req
myHandler =
jsonRequestBody @Person errorHandler $
proc request -> do
let person :: Person
person = pick @(JSONBody Person) $ from request
....
Conclusion
We covered a few common use cases above, but many others are supported by WebGear. See modules under WebGear.Core.Trait
for details.