Module

HTTPurple

Package
purescript-httpurple
Repository
sigma-andex/purescript-httpurple

Re-exports from Data.Generic.Rep

#Generic Source

class Generic a rep | a -> rep

The Generic class asserts the existence of a type function from types to their representations using the type constructors defined in this module.

Re-exports from HTTPurple.Body

#toString Source

toString :: forall m. MonadAff m => RequestBody -> m String

Turn RequestBody into a String

This drains the Readable stream in RequestBody for the first time and returns cached result from then on.

#toStream Source

toStream :: RequestBody -> Readable ()

Return the Readable stream directly from RequestBody

#toBuffer Source

toBuffer :: forall m. MonadAff m => RequestBody -> m Buffer

Turn RequestBody into a Buffer

This drains the Readable stream in RequestBody for the first time and returns cached result from then on.

Re-exports from HTTPurple.Cont

#usingCont Source

usingCont :: forall output m. Applicative m => ContT output m output -> m output

Run the continuation

Re-exports from HTTPurple.Headers

#ResponseHeaders Source

newtype ResponseHeaders

The ResponseHeaders type is a wrapper for a map that represents the set of headers in an HTTP response. A response header can contain multiple values per key, e.g. in the case of multiple Set-Cookie directives.

Instances

  • Semigroup ResponseHeaders

    Allow one ResponseHeaders objects to be appended to another.

  • Show ResponseHeaders

    Allow a ResponseHeaders to be represented as a string. This string is formatted in HTTP headers format.

  • Eq ResponseHeaders

    Compare two ResponseHeaders objects by comparing the underlying Objects.

#RequestHeaders Source

newtype RequestHeaders

The RequestHeaders type is a wrapper for a map that represents the set of headers in an HTTP request. A request header contains maximum one value per key.

Instances

#headers Source

headers :: forall r. ToHeaders r => r -> ResponseHeaders

Create ResponseHeaders from a record, an Array (Tuple String String) or an Array (Tuple String (Array String))

#header Source

header :: String -> String -> ResponseHeaders

Create a singleton header from a key-value pair.

#empty Source

empty :: ResponseHeaders

Return a ResponseHeaders containing no headers.

Re-exports from HTTPurple.Json

#JsonEncoder Source

newtype JsonEncoder json

Constructors

Instances

#JsonDecoder Source

newtype JsonDecoder err json

Constructors

Instances

#toJson Source

toJson :: forall (json :: Type). JsonEncoder json -> json -> String

Serialise a type to json using the given driver.

#fromJson Source

fromJson :: forall (err :: Type) (json :: Type) (m :: Type -> Type). MonadAff m => JsonDecoder err json -> RequestBody -> ContT Response m json

Parse the RequestBody as json using the provided JsonDecoder. If it fails, an empty bad request is returned Returns a continuation

Re-exports from HTTPurple.Lookup

#lookup Source

lookup :: forall c k r. Lookup c k r => c -> k -> Maybe r

Given some type and a key on that type, extract some value that corresponds to that key.

#has Source

has :: forall c k r. Lookup (c r) k r => c r -> k -> Boolean

This simple helper works on any Lookup instance, where the container set has a single type variable, and returns a Boolean indicating if the given key matches any value in the given container.

#at Source

at :: forall c k r. Monoid r => Lookup c k r => c -> k -> r

This simple helper works on any Lookup instance where the return type is a Monoid, and is the same as lookup except that it returns a t instead of a Maybe t. If lookup would return Nothing, then at returns mempty.

#(!@) Source

Operator alias for HTTPurple.Lookup.at (left-associative / precedence 8)

Expose at as the infix operator !@

#(!?) Source

Operator alias for HTTPurple.Lookup.has (left-associative / precedence 8)

Expose has as the infix operator !?

#(!!) Source

Operator alias for HTTPurple.Lookup.lookup (left-associative / precedence 8)

!! is inspired by !! in Data.Array, but note that it differs from !! in Data.Array in that you can use !! for any other instance of Lookup.

Re-exports from HTTPurple.Method

#Method Source

data Method

These are the HTTP methods that HTTPurple understands.

Constructors

Instances

  • Eq Method

    If two Methods are the same constructor, they are equal.

  • Show Method

    Convert a constructor to a String.

Re-exports from HTTPurple.Path

#Path Source

type Path = Array String

The Path type is just sugar for an Array of String segments that are sent in a request and indicates the path of the resource being requested. Note that this type has an implementation of Lookup for Int keys defined by lookupArray in Lookup.purs because lookupArray is defined for any Array of Monoids. So you can do something like path !! 2 to get the path segment at index 2.

Re-exports from HTTPurple.Query

#Query Source

type Query = Object String

The Query type is a Object of Strings, with one entry per query parameter in the request. For any query parameters that don't have values (/some/path?query or /some/path?query=), the value in the Object for that parameter will be the an empty string. Note that this type has an implementation of Lookup for String keys defined by lookupObject in Lookup.purs because lookupObject is defined for any Object of Monoids. So you can do something like query !! "foo" to get the value of the query parameter "foo".

Re-exports from HTTPurple.Request

#Request Source

type Request route = { body :: RequestBody, headers :: RequestHeaders, httpVersion :: Version, method :: Method, path :: Path, query :: Query, route :: route, url :: String }

The Request type is a Record type that includes fields for accessing the different parts of the HTTP request.

#fullPath Source

fullPath :: forall route. Request route -> String

Return the full resolved path, including query parameters. This may not match the requested path--for instance, if there are empty path segments in the request--but it is equivalent.

Re-exports from HTTPurple.Response

#ResponseM Source

type ResponseM = Aff Response

The ResponseM type simply conveniently wraps up an HTTPurple monad that returns a response. This type is the return type of all router/route methods.

#Response Source

type Response = { headers :: ResponseHeaders, status :: Status, writeBody :: Response -> Aff Unit }

A Response is a status code, headers, and a body.

#variantAlsoNegotiates' Source

variantAlsoNegotiates' :: forall m. MonadAff m => ResponseHeaders -> m Response

506 with headers

#variantAlsoNegotiates Source

variantAlsoNegotiates :: forall m. MonadAff m => m Response

506

#useProxy' Source

useProxy' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

305 with headers

#useProxy Source

useProxy :: forall m b. MonadAff m => Body b => b -> m Response

305

#upgradeRequired' Source

upgradeRequired' :: forall m. MonadAff m => ResponseHeaders -> m Response

426 with headers

#upgradeRequired Source

upgradeRequired :: forall m. MonadAff m => m Response

426

#unsupportedMediaType' Source

unsupportedMediaType' :: forall m. MonadAff m => ResponseHeaders -> m Response

415 with headers

#unsupportedMediaType Source

unsupportedMediaType :: forall m. MonadAff m => m Response

415

#unprocessableEntity' Source

unprocessableEntity' :: forall m. MonadAff m => ResponseHeaders -> m Response

422 with headers

#unprocessableEntity Source

unprocessableEntity :: forall m. MonadAff m => m Response

422

#unavailableForLegalReasons' Source

unavailableForLegalReasons' :: forall m. MonadAff m => ResponseHeaders -> m Response

451 with headers

#unavailableForLegalReasons Source

#unauthorized' Source

unauthorized' :: forall m. MonadAff m => ResponseHeaders -> m Response

401 with headers

#unauthorized Source

unauthorized :: forall m. MonadAff m => m Response

401

#uRITooLong' Source

uRITooLong' :: forall m. MonadAff m => ResponseHeaders -> m Response

414 with headers

#uRITooLong Source

uRITooLong :: forall m. MonadAff m => m Response

414

#tooManyRequests' Source

tooManyRequests' :: forall m. MonadAff m => ResponseHeaders -> m Response

429 with headers

#tooManyRequests Source

tooManyRequests :: forall m. MonadAff m => m Response

429

#temporaryRedirect' Source

temporaryRedirect' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

307 with headers

#temporaryRedirect Source

temporaryRedirect :: forall m b. MonadAff m => Body b => b -> m Response

307

#switchingProtocols' Source

switchingProtocols' :: forall m. MonadAff m => ResponseHeaders -> m Response

101 with headers

#switchingProtocols Source

switchingProtocols :: forall m. MonadAff m => m Response

101

#serviceUnavailable' Source

serviceUnavailable' :: forall m. MonadAff m => ResponseHeaders -> m Response

503 with headers

#serviceUnavailable Source

serviceUnavailable :: forall m. MonadAff m => m Response

503

#seeOther' Source

seeOther' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

303 with headers

#seeOther Source

seeOther :: forall m b. MonadAff m => Body b => b -> m Response

303

#response' Source

response' :: forall m b. MonadAff m => Body b => Status -> ResponseHeaders -> b -> m Response

The same as response but with headers.

#response Source

response :: forall m b. MonadAff m => Body b => Status -> b -> m Response

For custom response statuses or providing a body for response codes that don't typically send one.

#resetContent' Source

resetContent' :: forall m. MonadAff m => ResponseHeaders -> m Response

205 with headers

#resetContent Source

resetContent :: forall m. MonadAff m => m Response

205

#requestTimeout' Source

requestTimeout' :: forall m. MonadAff m => ResponseHeaders -> m Response

408 with headers

#requestTimeout Source

requestTimeout :: forall m. MonadAff m => m Response

408

#requestHeaderFieldsTooLarge' Source

requestHeaderFieldsTooLarge' :: forall m. MonadAff m => ResponseHeaders -> m Response

431 with headers

#requestHeaderFieldsTooLarge Source

#rangeNotSatisfiable' Source

rangeNotSatisfiable' :: forall m. MonadAff m => ResponseHeaders -> m Response

416 with headers

#rangeNotSatisfiable Source

rangeNotSatisfiable :: forall m. MonadAff m => m Response

416

#proxyAuthenticationRequired' Source

proxyAuthenticationRequired' :: forall m. MonadAff m => ResponseHeaders -> m Response

407 with headers

#proxyAuthenticationRequired Source

#processing' Source

processing' :: forall m. MonadAff m => ResponseHeaders -> m Response

102 with headers

#processing Source

processing :: forall m. MonadAff m => m Response

102

#preconditionRequired' Source

preconditionRequired' :: forall m. MonadAff m => ResponseHeaders -> m Response

428 with headers

#preconditionRequired Source

preconditionRequired :: forall m. MonadAff m => m Response

428

#preconditionFailed' Source

preconditionFailed' :: forall m. MonadAff m => ResponseHeaders -> m Response

412 with headers

#preconditionFailed Source

preconditionFailed :: forall m. MonadAff m => m Response

412

#permanentRedirect' Source

permanentRedirect' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

308 with headers

#permanentRedirect Source

permanentRedirect :: forall m b. MonadAff m => Body b => b -> m Response

308

#paymentRequired' Source

paymentRequired' :: forall m. MonadAff m => ResponseHeaders -> m Response

402 with headers

#paymentRequired Source

paymentRequired :: forall m. MonadAff m => m Response

402

#payloadTooLarge' Source

payloadTooLarge' :: forall m. MonadAff m => ResponseHeaders -> m Response

413 with headers

#payloadTooLarge Source

payloadTooLarge :: forall m. MonadAff m => m Response

413

#partialContent' Source

partialContent' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

206 with headers

#partialContent Source

partialContent :: forall m b. MonadAff m => Body b => b -> m Response

206

#ok' Source

ok' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

200 with headers

#ok Source

ok :: forall m b. MonadAff m => Body b => b -> m Response

200

#notModified' Source

notModified' :: forall m. MonadAff m => ResponseHeaders -> m Response

304 with headers

#notModified Source

notModified :: forall m. MonadAff m => m Response

304

#notImplemented' Source

notImplemented' :: forall m. MonadAff m => ResponseHeaders -> m Response

501 with headers

#notImplemented Source

notImplemented :: forall m. MonadAff m => m Response

501

#notFound' Source

notFound' :: forall m. MonadAff m => ResponseHeaders -> m Response

404 with headers

#notFound Source

notFound :: forall m. MonadAff m => m Response

404

#notExtended' Source

notExtended' :: forall m. MonadAff m => ResponseHeaders -> m Response

510 with headers

#notExtended Source

notExtended :: forall m. MonadAff m => m Response

510

#notAcceptable' Source

notAcceptable' :: forall m. MonadAff m => ResponseHeaders -> m Response

406 with headers

#notAcceptable Source

notAcceptable :: forall m. MonadAff m => m Response

406

#nonAuthoritativeInformation' Source

nonAuthoritativeInformation' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

203 with headers

#nonAuthoritativeInformation Source

nonAuthoritativeInformation :: forall m b. MonadAff m => Body b => b -> m Response

203

#noContent' Source

noContent' :: forall m. MonadAff m => ResponseHeaders -> m Response

204 with headers

#noContent Source

noContent :: forall m. MonadAff m => m Response

204

#networkAuthenticationRequired' Source

networkAuthenticationRequired' :: forall m. MonadAff m => ResponseHeaders -> m Response

511 with headers

#networkAuthenticationRequired Source

#multipleChoices' Source

multipleChoices' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

300 with headers

#multipleChoices Source

multipleChoices :: forall m b. MonadAff m => Body b => b -> m Response

300

#multiStatus' Source

multiStatus' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

207 with headers

#multiStatus Source

multiStatus :: forall m b. MonadAff m => Body b => b -> m Response

207

#movedPermanently' Source

movedPermanently' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

301 with headers

#movedPermanently Source

movedPermanently :: forall m b. MonadAff m => Body b => b -> m Response

301

#misdirectedRequest' Source

misdirectedRequest' :: forall m. MonadAff m => ResponseHeaders -> m Response

421 with headers

#misdirectedRequest Source

misdirectedRequest :: forall m. MonadAff m => m Response

421

#methodNotAllowed' Source

methodNotAllowed' :: forall m. MonadAff m => ResponseHeaders -> m Response

405 with headers

#methodNotAllowed Source

methodNotAllowed :: forall m. MonadAff m => m Response

405

#loopDetected' Source

loopDetected' :: forall m. MonadAff m => ResponseHeaders -> m Response

508 with headers

#loopDetected Source

loopDetected :: forall m. MonadAff m => m Response

508

#locked' Source

locked' :: forall m. MonadAff m => ResponseHeaders -> m Response

423 with headers

#locked Source

locked :: forall m. MonadAff m => m Response

423

#lengthRequired' Source

lengthRequired' :: forall m. MonadAff m => ResponseHeaders -> m Response

411 with headers

#lengthRequired Source

lengthRequired :: forall m. MonadAff m => m Response

411

#internalServerError' Source

internalServerError' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

500 with headers

#internalServerError Source

internalServerError :: forall m b. MonadAff m => Body b => b -> m Response

500

#insufficientStorage' Source

insufficientStorage' :: forall m. MonadAff m => ResponseHeaders -> m Response

507 with headers

#insufficientStorage Source

insufficientStorage :: forall m. MonadAff m => m Response

507

#imATeapot' Source

imATeapot' :: forall m. MonadAff m => ResponseHeaders -> m Response

418 with headers

#imATeapot Source

imATeapot :: forall m. MonadAff m => m Response

418

#iMUsed' Source

iMUsed' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

226 with headers

#iMUsed Source

iMUsed :: forall m b. MonadAff m => Body b => b -> m Response

226

#hTTPVersionNotSupported' Source

hTTPVersionNotSupported' :: forall m. MonadAff m => ResponseHeaders -> m Response

505 with headers

#hTTPVersionNotSupported Source

hTTPVersionNotSupported :: forall m. MonadAff m => m Response

505

#gone' Source

gone' :: forall m. MonadAff m => ResponseHeaders -> m Response

410 with headers

#gone Source

gone :: forall m. MonadAff m => m Response

410

#gatewayTimeout' Source

gatewayTimeout' :: forall m. MonadAff m => ResponseHeaders -> m Response

504 with headers

#gatewayTimeout Source

gatewayTimeout :: forall m. MonadAff m => m Response

504

#found' Source

found' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

302 with headers

#found Source

found :: forall m b. MonadAff m => Body b => b -> m Response

302

#forbidden' Source

forbidden' :: forall m. MonadAff m => ResponseHeaders -> m Response

403 with headers

#forbidden Source

forbidden :: forall m. MonadAff m => m Response

403

#failedDependency' Source

failedDependency' :: forall m. MonadAff m => ResponseHeaders -> m Response

424 with headers

#failedDependency Source

failedDependency :: forall m. MonadAff m => m Response

424

#expectationFailed' Source

expectationFailed' :: forall m. MonadAff m => ResponseHeaders -> m Response

417 with headers

#expectationFailed Source

expectationFailed :: forall m. MonadAff m => m Response

417

#emptyResponse' Source

emptyResponse' :: forall m. MonadAff m => Status -> ResponseHeaders -> m Response

The same as emptyResponse but with headers.

#emptyResponse Source

emptyResponse :: forall m. MonadAff m => Status -> m Response

The same as response but without a body.

#created' Source

created' :: forall m. MonadAff m => ResponseHeaders -> m Response

201 with headers

#created Source

created :: forall m. MonadAff m => m Response

201

#continue' Source

continue' :: forall m. MonadAff m => ResponseHeaders -> m Response

100 with headers

#continue Source

continue :: forall m. MonadAff m => m Response

100

#conflict' Source

conflict' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

409 with headers

#conflict Source

conflict :: forall m b. MonadAff m => Body b => b -> m Response

409

#badRequest' Source

badRequest' :: forall m b. MonadAff m => Body b => ResponseHeaders -> b -> m Response

400 with headers

#badRequest Source

badRequest :: forall m b. MonadAff m => Body b => b -> m Response

400

#badGateway' Source

badGateway' :: forall m. MonadAff m => ResponseHeaders -> m Response

502 with headers

#badGateway Source

badGateway :: forall m. MonadAff m => m Response

502

#alreadyReported' Source

alreadyReported' :: forall m. MonadAff m => ResponseHeaders -> m Response

208 with headers

#alreadyReported Source

alreadyReported :: forall m. MonadAff m => m Response

208

#accepted' Source

accepted' :: forall m. MonadAff m => ResponseHeaders -> m Response

202 with headers

#accepted Source

accepted :: forall m. MonadAff m => m Response

202

Re-exports from HTTPurple.Routes

#orElse Source

orElse :: forall left right. (Request left -> ResponseM) -> (Request right -> ResponseM) -> Request (left <+> right) -> ResponseM

Combine two request handlers.

#mkRoute Source

mkRoute :: forall i iGen r. Generic i iGen => GRouteDuplex iGen r => Record r -> RouteDuplex i i

Make a route from a RoudeDuplex definition.

#combineRoutes Source

combineRoutes :: forall left right. RouteDuplex' left -> RouteDuplex' right -> RouteDuplex' (Either left right)

Combine two routes

#catchAll Source

catchAll :: RouteDuplex' (Array String)

A catch-all route that matches any request.

#(<+>) Source

Operator alias for HTTPurple.Routes.combineRoutes (right-associative / precedence 3)

Infix operator for orElse

#type (<+>) Source

Operator alias for Data.Either.Either (right-associative / precedence 0)

Type-level operator two combine two route definitions.

Re-exports from HTTPurple.Server

#ServerM Source

type ServerM = Effect (Effect Unit -> Effect Unit)

The ServerM is just an Effect containing a callback to close the server. This type is the return type of the HTTPurple serve and related methods.

#serve Source

serve :: forall route from fromRL via missing missingList. RowToList missing missingList => FillableFields missingList () missing => Union via missing (ListenOptionsR) => RowToList from fromRL => JustifiableFields fromRL from () via => Record from -> RoutingSettings route -> ServerM

Given a ListenOptions and a RoutingSettings, creates and runs a HTTPurple server.

Re-exports from HTTPurple.Status

#Status Source

type Status = Int

The Status type enumerates all valid HTTP response status codes.

Re-exports from HTTPurple.Validation

#fromValidatedE Source

fromValidatedE :: forall input err validated m. MonadAff m => (input -> Either err validated) -> (err -> m Response) -> input -> ContT Response m validated

Validate an input using a validate function. If validation fails, the error handler is called. Returns a continuation

#fromValidated Source

fromValidated :: forall input err validated m. MonadAff m => (input -> Either err validated) -> input -> ContT Response m validated

Validate an input using a validate function. If validation fails, a bad request is resturned. Returns a continuation

Re-exports from Routing.Duplex

#RouteDuplex'

type RouteDuplex' a = RouteDuplex a a

A type restricted variant of RouteDuplex where input and output are the same type. This type will typically be your custom Route data type representing valid routes within your application.

#RouteDuplex

data RouteDuplex i o

The core abstraction of this library. The values of this type can be used both for parsing values of type o from String as well as printing values of type i into String.

For most purposes, you'll likely want RouterDuplex' which uses the same type for both parameters.

Constructors

  • RouteDuplex (i -> RoutePrinter) (RouteParser o)

Instances

  • Functor (RouteDuplex i)
  • Apply (RouteDuplex i)
  • Applicative (RouteDuplex i)
  • Profunctor RouteDuplex
  • (IsSymbol sym, Cons sym (RouteDuplex String String -> RouteDuplex a b) rx1 r1, Cons sym a rx2 r2, Cons sym b r3 rx3, Lacks sym r3, RouteDuplexBuildParams rest r1 r2 rx3 r4) => RouteDuplexBuildParams (Cons sym (RouteDuplex String String -> RouteDuplex a b) rest) r1 r2 r3 r4

#RouteDuplexBuildParams

class RouteDuplexBuildParams :: RowList Type -> Row Type -> Row Type -> Row Type -> Row Type -> Constraintclass RouteDuplexBuildParams (rl :: RowList Type) (r1 :: Row Type) (r2 :: Row Type) (r3 :: Row Type) (r4 :: Row Type) | rl -> r1 r2 r3 r4 where

Members

  • buildParams :: Proxy rl -> Record r1 -> RouteDuplex (Record r2) (Record r3) -> RouteDuplex (Record r2) (Record r4)

Instances

  • (IsSymbol sym, Cons sym (RouteDuplex String String -> RouteDuplex a b) rx1 r1, Cons sym a rx2 r2, Cons sym b r3 rx3, Lacks sym r3, RouteDuplexBuildParams rest r1 r2 rx3 r4) => RouteDuplexBuildParams (Cons sym (RouteDuplex String String -> RouteDuplex a b) rest) r1 r2 r3 r4
  • RouteDuplexBuildParams Nil r1 r2 r3 r3

#RouteDuplexParams

class RouteDuplexParams :: Row Type -> Row Type -> Constraintclass RouteDuplexParams (r1 :: Row Type) (r2 :: Row Type) | r1 -> r2 where

Members

  • params :: Record r1 -> RouteDuplex' (Record r2)

    Builds a RouteDuplex from a record of query parameter parsers/printers, where each property corresponds to a query parameter with the same name.

    search =
      params
        { page: int
        , filter: optional <<< string
        }
    
    parse search "?page=3&filter=Galaxy%20Quest" ==
      Right { page: 3, filter: Just "Galaxy Quest" }
    

Instances

  • (RowToList r1 rl, RouteDuplexBuildParams rl r1 r2 () r2) => RouteDuplexParams r1 r2

#suffix

suffix :: forall a b. RouteDuplex a b -> String -> RouteDuplex a b

Similar to prefix. Strips (when parsing) or adds (when printing) a given string segment from the end of the path. The same precautions for prefix apply here.

#string

string :: RouteDuplex' String -> RouteDuplex' String

This does nothing (internally it's defined as identity). It can be used to restrict a type parameter of a polymorphic RouteDuplex' a to String.

#segment

segment :: RouteDuplex' String

Consumes or prints a single path segment. Note: URI encoding and decoding is done automatically.

parse segment "abc"         == Right "abc"
parse segment "abc%20def"   == Right "abc def" -- automatic decoding of uri components
parse segment "abc/def"     == Right "abc"
parse segment "/abc"        == Right "" -- the empty string before the first '/'
parse (root segment) "/abc" == Right "abc"

print segment "hello there" == "hello%20there"
print segment "" == "/"

#root

root :: forall a b. RouteDuplex a b -> RouteDuplex a b

Modifies a given codec to require a prefix of '/'. You can think of it as stripping and adding the '/' at the beginning of path, failing if it's not there.

parse (root segment) "/abc" == Right "abc"
parse (root segment) "abc" == Left (Expected "" "abc")

print (root segment) "abc" == "/abc"

#rest

rest :: RouteDuplex' (Array String)

Consumes or prints all the remaining segments.

parse rest "" == Right []
parse (path "a/b" rest) "a/b/c/d" == Right ["c", "d"]

print rest ["a", "b"] == "a/b"

#record

record :: forall r. RouteDuplex r (Record ())

Combined with prop or :=, builds a Record where the order of parsing and printing matters.

date =
  record
    # prop (Proxy :: _ "year") (int segment)
    # prop (Proxy :: _ "month") (int segment)
    # prop (Proxy :: _ "day") (int segment)

parse (path "blog" date) "blog/2019/1/2" ==
  Right { year: 2019, month: 1, day: 2 }

#prop

prop :: forall sym a b r1 r2 r3 rx. IsSymbol sym => Cons sym a rx r1 => Cons sym b r2 r3 => Lacks sym r2 => Proxy sym -> RouteDuplex a b -> RouteDuplex (Record r1) (Record r2) -> RouteDuplex (Record r1) (Record r3)

See record.

#print

print :: forall i o. RouteDuplex i o -> i -> String

Renders a value of type i into a String representation of URI path, query and fragment (hash).

#prefix

prefix :: forall a b. String -> RouteDuplex a b -> RouteDuplex a b

Strips (when parsing) or adds (when printing) a given string segment of the path. Note: this combinator only deals with a single segment. If you pass it a string containing '/' it will percent encode it and treat it as single segment. E.g. prefix "/api/v1" will attempt to match single segment "%2Fapi%2Fv1" which is probably not what you want. See path if you want to deal with prefixes consisting of multiple segments.

parse (prefix "api" segment) "api/a" == Right "a"

parse (prefix "/api/v1" segment)) "/api/v1/a" == Left (Expected "/api/v1" "")

-- contrast with `path`
parse (path "/api/v1" segment)) "/api/v1/a" == Right "a"

#path

path :: forall a b. String -> RouteDuplex a b -> RouteDuplex a b

Strips (when parsing) or adds (when printing) a given String prefix, potentially consisting of multiple path segments. Constrast this with prefix, which only deals with single segment.

parse (path "/api/v1" segment) "/api/v1/a" == Right "a"
parse (path "/api/v1" segment) "/api/v2/a" == Left (Expected "v1" "v2")

#parse

parse :: forall i o. RouteDuplex i o -> String -> Either RouteError o

Uses a given codec to parse a value of type o out of String representing the path, query and fragment (hash) of a URI (see URI - generic syntax) or produce a RouteError if parsing fails.

#param

param :: String -> RouteDuplex' String

param name consumes or prints a query parameter with the given name. Parsing will fail if the parameter is not there.

parse (param "search") "?search=keyword" == Right "keyword"
parse (param "search") "/"               == Left (MissingParam "search")
parse (optional (param "search")) "/"    == Right Nothing

#optional

optional :: forall a b. RouteDuplex a b -> RouteDuplex (Maybe a) (Maybe b)

Augments the behavior of a given codec by making it return Nothing if parsing fails, or Just value if it succeeds.

parse (optional segment) "a"        == Right (Just "a")
parse (optional segment) ""         == Right Nothing

print (optional segment) (Just "a") == "a"
print (optional segment) Nothing    == ""

#many1

many1 :: forall f a b. Foldable f => Alt f => Applicative f => RouteDuplex a b -> RouteDuplex (f a) (f b)

Repeatedly applies a given codec to parse one or more values from path segments. Parsing will fail if no segment can be parsed.

parse (many1 (int segment)) "1/2/3/x" == Right [1,2,3]
parse (many1 (int segment)) "x",      == Left (Expected "Int" "x") :: Either RouteError (Array Int)

#many

many :: forall f a b. Foldable f => Alternative f => RouteDuplex a b -> RouteDuplex (f a) (f b)

Similar to many1, except also succeeds when no values can be parsed.

parse (many (int segment)) "1/2/3/x" == Right [1,2,3]
parse (many (int segment)) "x",      == Right []

#int

int :: RouteDuplex' String -> RouteDuplex' Int

Refines a codec of Strings to Ints.

parse (int segment) "1"  == Right 1
parse (int segment) "x"  == Left (Expected "Int" "x")

print (int segment) 1    == "1"

#flag

flag :: RouteDuplex' String -> RouteDuplex' Boolean

Consumes or prints a query flag (i.e. parameter without value). Note: that this combinator ignores the value of the parameter. It only cares about its presence/absence. Presence is interpreted as true, absence as false.

parse (flag (param "x")) "?x"        == Right true
parse (flag (param "x")) "?x=true",  == Right true
parse (flag (param "x")) "?x=false", == Right true -- value is ignored, what matters is presence of the parameter x
parse (flag (param "x")) "?y",       == Right false

#end

end :: forall a b. RouteDuplex a b -> RouteDuplex a b

end codec will only suceed if codec succeeds and there are no additional path segments remaining to be processed.

parse (end segment) "abc" == Right "abc"
parse (end segment) "abc/def" == Left (ExpectedEndOfPath "def")

#default

default :: forall a b. b -> RouteDuplex a b -> RouteDuplex a b

Sets a default value which will be returned when parsing fails. Does not influence printing in any way.

parse (default 0 $ int segment) "1" == Right 1
parse (default 0 $ int segment) "x" == Right 0

#boolean

boolean :: RouteDuplex' String -> RouteDuplex' Boolean

Refines a codec of Strings to Booleans, where true and false are the strings "true" and "false", and other strings are rejected.

parse (boolean segment) "true"  == Right true
parse (boolean segment) "x"     == Left (Expected "Boolean" "x")

print (boolean segment) true    == "true"

#as

as :: forall s a b. (a -> s) -> (String -> Either String b) -> RouteDuplex s String -> RouteDuplex a b

Builds a codec for a custom type out of printer and parser functions.

data Sort = Asc | Desc

sortToString :: Sort -> String
sortToString = case _ of
  Asc -> "asc"
  Desc -> "desc"

sortFromString :: String -> Either String Sort
sortFromString = case _ of
  "asc" -> Right Asc
  "desc" -> Right Desc
  val -> Left $ "Not a sort: " <> val

sort :: RouteDuplex' String -> RouteDuplex' Sort
sort = as sortToString sortFromString

#(:=)

Operator alias for Routing.Duplex.prop (non-associative / precedence 2)

Re-exports from Routing.Duplex.Generic

#GRouteDuplex

class GRouteDuplex :: Type -> Row Type -> Constraintclass GRouteDuplex rep (r :: Row Type) | rep -> r

Instances

  • (GRouteDuplex a r, GRouteDuplex b r) => GRouteDuplex (Sum a b) r
  • (IsSymbol sym, Cons sym (RouteDuplex a a) rx r, GRouteDuplexCtr a b) => GRouteDuplex (Constructor sym b) r

#GRouteDuplexCtr

class GRouteDuplexCtr a b | a -> b

Instances

  • GRouteDuplexCtr (Product a b) (Product a b)
  • GRouteDuplexCtr NoArguments NoArguments
  • GRouteDuplexCtr (Argument a) (Argument a)
  • GRouteDuplexCtr a (Argument a)

#sum

sum :: forall a rep r. Generic a rep => GRouteDuplex rep r => Record r -> RouteDuplex' a

#product

product :: forall a b c. GRouteDuplexCtr b c => RouteDuplex' a -> RouteDuplex' b -> RouteDuplex' (Product (Argument a) c)

#noArgs

noArgs :: RouteDuplex' NoArguments

#(~)

Operator alias for Routing.Duplex.Generic.product (right-associative / precedence 0)

Re-exports from Routing.Duplex.Generic.Syntax

#gparams

gparams :: forall a b c. GParams a b c => a -> b -> RouteDuplex' c

#gsep

gsep :: forall a b c. GSep a b c => a -> b -> RouteDuplex' c

#(?)

Operator alias for Routing.Duplex.Generic.Syntax.gparams (non-associative / precedence 8)

#(/)

Operator alias for Routing.Duplex.Generic.Syntax.gsep (right-associative / precedence 1)