{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} module Nero.Application ( slashRedirect ) where import Data.Monoid ((<>)) import Control.Lens import Nero.Request import Nero.Response import Nero.Match import Nero.Url -- $setup -- >>> :set -XOverloadedStrings -- >>> import Nero -- | Redirect with slash appended URL if only a trailing slash is needed for -- successful matching, otherwise it responds normally. -- -- >>> let mkRequest p = dummyRequest & host .~ "example.com" & path .~ p -- >>> let matcher = match $ "/hello/" <> text <> "/" -- >>> let respond name = ok $ "<h1>Hello " <> name <> "</h1>" -- >>> let app = slashRedirect matcher respond -- -- >>> app (mkRequest "/hello/there") <&> status -- Just "301 Moved Permanently" -- >>> app (mkRequest "/hello/there") >>= preview location -- Just "http://example.com/hello/there/" -- -- >>> app (mkRequest "/hello/there/") <&> status -- Just "200 OK" -- >>> app (mkRequest "/hello/there/") <&> body -- Just "<h1>Hello there</h1>" -- -- >>> app $ mkRequest "/bye/" -- Nothing slashRedirect :: Target a => Matcher a -> (a -> Response) -- ^ What to respond upon matching. -> Request -> Maybe Response slashRedirect m respond request = case request ^? path . m of Just x -> Just $ respond x Nothing -> if isn't m aPath then Nothing else Just . movedPermanently $ request ^. url & path .~ aPath where aPath = request ^. path <> "/"