Skip to content

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
  , Get h (RequiredQueryParam "limit" Integer) Request
  , Sets h [RequiredResponseHeader "Content-Type" Text, Body PlainText String] Response
  ) =>
  RequestHandler h ts
myHandler =
  queryParam @"limit" @Integer errorHandler $
    proc request -> do
      let limit :: Integer
          limit = pick @(RequiredQueryParam "limit" Integer) $ from request
      ....

errorHandler ::
  ( StdHandler h m
  , Sets h [RequiredResponseHeader "Content-Type" Text, Body PlainText String] Response
  ) =>
  h (Request `With` ts, Either ParamNotFound ParamParseError) Response
errorHandler = proc (_, err) -> respondA HTTP.badRequest400 PlainText -< 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
  , Get h (RequiredRequestHeader "If-Match" ETag) Request
  ) =>
  RequestHandler h ts
myHandler =
  header @"If-Match" @ETag errorHandler $
    proc request -> do
      let etag :: ETag
          etag = pick @(RequiredRequestHeader "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
  , Get h (Body OctetStream PNGImage) Request
  ) =>
  RequestHandler h ts
myHandler =
  requestBody @PNGImage OctetStream errorHandler $
    proc request -> do
      let img :: PNGImage
          img = pick @(Body OctetStream 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
  , Get h (Body JSON Person) Request
  ) =>
  RequestHandler h ts
myHandler =
  requestBody @Person JSON errorHandler $
    proc request -> do
      let person :: Person
          person = pick @(Body JSON 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.