Add catchAll route and update documentation

This commit is contained in:
sigma-andex 2022-06-13 15:10:20 +01:00
parent 99df474f93
commit 8375ce788b
3 changed files with 59 additions and 2 deletions

View File

@ -8,6 +8,7 @@
* [Adding further types](#adding-further-types)
* [Composing routes](#composing-routes)
* [Reverse routing](#reverse-routing)
* [Catch-all route](#catch-all-route)
* [Working with request headers](#working-with-request-headers)
## Routing introduction
@ -244,6 +245,51 @@ main = serve { port: 8080 } { route, router }
redirect = headers [ Tuple "Location" $ print route $ New account ]
```
### Catch-all route
You can easily create a catch all route by using the predefined `catchAll`.
```purescript
import HTTPurple
data Route = CatchAll (Array String) -- list of paths
derive instance Generic Route _
route :: RouteDuplex' Route
route = mkRoute
{ "CatchAll": catchAll
}
main :: ServerM
main = serve {} { route, router }
where
router { route: CatchAll paths } = ok $ "hello 🗺!"
```
### Routing prefixes
You can create a route prefix such as `/v1/` using the `prefix` method. Here is an example:
```purescript
import HTTPurple
data Route = Home -- list of paths
derive instance Generic Route _
route :: RouteDuplex' Route
route = root $ prefix "v1" $ sum
{ "Home": noArgs
}
main :: ServerM
main = serve {} { route, router }
where
router { route: Home } = ok $ "hello 🗺!"
```
Now all requests need to be prefixed with `/v1/`.
**Note**: `prefix` takes exactly one path segment. If you need two prefixes, e.g. for `/api/v1/` you need to use two prefixes: `root $ prefix "api" $ prefix "v1" $ sum`.
## Matching HTTP Methods

View File

@ -30,7 +30,7 @@ import HTTPurple.Path (Path)
import HTTPurple.Query (Query)
import HTTPurple.Request (Request, fullPath)
import HTTPurple.Response (Response, ResponseM, accepted, accepted', alreadyReported, alreadyReported', badGateway, badGateway', badRequest, badRequest', conflict, conflict', continue, continue', created, created', emptyResponse, emptyResponse', expectationFailed, expectationFailed', failedDependency, failedDependency', forbidden, forbidden', found, found', gatewayTimeout, gatewayTimeout', gone, gone', hTTPVersionNotSupported, hTTPVersionNotSupported', iMUsed, iMUsed', imATeapot, imATeapot', insufficientStorage, insufficientStorage', internalServerError, internalServerError', lengthRequired, lengthRequired', locked, locked', loopDetected, loopDetected', methodNotAllowed, methodNotAllowed', misdirectedRequest, misdirectedRequest', movedPermanently, movedPermanently', multiStatus, multiStatus', multipleChoices, multipleChoices', networkAuthenticationRequired, networkAuthenticationRequired', noContent, noContent', nonAuthoritativeInformation, nonAuthoritativeInformation', notAcceptable, notAcceptable', notExtended, notExtended', notFound, notFound', notImplemented, notImplemented', notModified, notModified', ok, ok', partialContent, partialContent', payloadTooLarge, payloadTooLarge', paymentRequired, paymentRequired', permanentRedirect, permanentRedirect', preconditionFailed, preconditionFailed', preconditionRequired, preconditionRequired', processing, processing', proxyAuthenticationRequired, proxyAuthenticationRequired', rangeNotSatisfiable, rangeNotSatisfiable', requestHeaderFieldsTooLarge, requestHeaderFieldsTooLarge', requestTimeout, requestTimeout', resetContent, resetContent', response, response', seeOther, seeOther', serviceUnavailable, serviceUnavailable', switchingProtocols, switchingProtocols', temporaryRedirect, temporaryRedirect', tooManyRequests, tooManyRequests', uRITooLong, uRITooLong', unauthorized, unauthorized', unavailableForLegalReasons, unavailableForLegalReasons', unprocessableEntity, unprocessableEntity', unsupportedMediaType, unsupportedMediaType', upgradeRequired, upgradeRequired', useProxy, useProxy', variantAlsoNegotiates, variantAlsoNegotiates')
import HTTPurple.Routes (type (<+>), combineRoutes, mkRoute, orElse, (<+>))
import HTTPurple.Routes (type (<+>), combineRoutes, mkRoute, orElse, (<+>), catchAll)
import HTTPurple.Server (ServerM, serve)
import HTTPurple.Status (Status)
import HTTPurple.Validation (fromValidated, fromValidatedE)

View File

@ -1,10 +1,12 @@
module HTTPurple.Routes
( (<+>)
, catchAll
, combineRoutes
, mkRoute
, orElse
, type (<+>)
) where
)
where
import Prelude
@ -19,8 +21,10 @@ import Routing.Duplex as RD
import Routing.Duplex.Generic as RG
import Type.Proxy (Proxy(..))
-- | Type-level operator two combine two route definitions.
infixr 0 type Either as <+>
-- | Combine two routes
combineRoutes ::
forall left right.
RD.RouteDuplex' left ->
@ -31,8 +35,10 @@ combineRoutes (RD.RouteDuplex lEnc lDec) (RD.RouteDuplex rEnc rDec) = (RD.RouteD
enc = lEnc ||| rEnc
dec = (lDec <#> Left) <|> (rDec <#> Right)
-- | Infix operator for `orElse`
infixr 3 combineRoutes as <+>
-- | Combine two request handlers.
orElse ::
forall left right.
(Request left -> ResponseM) ->
@ -42,6 +48,7 @@ orElse ::
orElse leftRouter _ request@{ route: Left l } = leftRouter $ Record.set (Proxy :: _ "route") l request
orElse _ rightRouter request@{ route: Right r } = rightRouter $ Record.set (Proxy :: _ "route") r request
-- | Make a route from a `RoudeDuplex` definition.
mkRoute ::
forall i iGen r.
Generic i iGen =>
@ -49,3 +56,7 @@ mkRoute ::
Record r ->
RD.RouteDuplex i i
mkRoute = RD.root <<< RG.sum
-- | A catch-all route that matches any request.
catchAll :: RD.RouteDuplex' (Array String)
catchAll = RD.many RD.segment