-- |A compatibility routing layer for WAI applications. module Web.Route.Invertible.Wai ( module Web.Route.Invertible.Common , waiRequest , routeWai , routeWaiError , routeWaiApplicationError , routeWaiApplication ) where import Control.Arrow (second) import Data.Maybe (fromMaybe) import qualified Network.Wai as Wai import Network.HTTP.Types.Header (ResponseHeaders, hContentType) import Network.HTTP.Types.Status (Status) import Web.Route.Invertible.Internal import Web.Route.Invertible.Common import Web.Route.Invertible -- |Convert a 'Wai.Request' to a request. waiRequest :: Wai.Request -> Request waiRequest q = Request { requestHost = maybe [] splitHost $ Wai.requestHeaderHost q , requestSecure = Wai.isSecure q , requestMethod = toMethod $ Wai.requestMethod q , requestPath = Wai.pathInfo q , requestQuery = simpleQueryParams $ map (second $ fromMaybe mempty) $ Wai.queryString q , requestContentType = fromMaybe mempty $ lookup hContentType headers } where headers = Wai.requestHeaders q -- |Lookup a wai request in a route map, returning either an error code and headers or a successful result. routeWai :: Wai.Request -> RouteMap a -> Either (Status, ResponseHeaders) a routeWai = routeRequest . waiRequest -- |Combine a set of applications in a routing map into a single application, calling a custom error handler in case of routing error. routeWaiError :: (Status -> ResponseHeaders -> Wai.Request -> a) -> RouteMap (Wai.Request -> a) -> Wai.Request -> a routeWaiError e m q = either (\(s, h) -> e s h q) (\a -> a q) $ routeWai q m -- |Equivalent to 'routeWaiError'. routeWaiApplicationError :: (Status -> ResponseHeaders -> Wai.Application) -> RouteMap Wai.Application -> Wai.Application routeWaiApplicationError = routeWaiError -- |Combine a set of applications in a routing map into a single application, returning an empty error response in case of routing error. routeWaiApplication :: RouteMap Wai.Application -> Wai.Application routeWaiApplication = routeWaiApplicationError $ \s h _ r -> r $ Wai.responseBuilder s h mempty