purescheme-wai-routing-core-0.1.0.0: Simple Routing functions for Wai Applications

Copyright(c) Fernando Rincon Martin 2020
LicenseApache-2.0 (see the file LICENSE)
MaintainerFernando Rincon Martin <f.rincon@protonmail.com>
Stabilityalpha
Safe HaskellNone
LanguageHaskell2010

Network.Wai.Routing.Purescheme.Core

Contents

Description

This module provides simple routing functions that works on top of Network.Wai applications.

The basic idea is provides functions that modifies an @Application in order to match certain rules. It is inspired on akka http server DSL.

A simple example of a Json rest api:

  restApi :: Application
  restApi = path "hello" 
              $ method GET 
              $ complete 
              $ responseLBS status200 [(hContentType, "text/html")] "<h1>Hellow World!</h1>"

As the result is a Wai @Application we can run it directly with warp server:

  main :: IO ()
  main = run 8080 restApi

The api is in alpha state, so that the api can change in any new release. It is very welcome suggestions and comments.

Synopsis

Basic functionality

Basic Types and Classes

type GenericApplication r = Request -> (r -> IO ResponseReceived) -> IO ResponseReceived Source #

Abstraction of Wai @Application on the type of response

Basic combinators

alternatives :: [GenericApplication r] -> GenericApplication r Source #

Combines multiple generic applications in one This function will try every application for each request, and return the first response that does not fail

In case of rejections (Reection thrown), it will rethrown the first exception with higher priority

Exception handling

handleException :: Exception e => (e -> GenericApplication a) -> GenericApplication a -> GenericApplication a Source #

Capture exceptions and convert to generic applications

withDefaultExceptionHandler :: GenericApplication Response -> GenericApplication Response Source #

By default capture all @Rejection and convert them in specific responses the content type returned is 'text/plain" and the body will contain the error message

Complete or reject requests

complete :: a -> GenericApplication a Source #

Ends the request responding with the argument

completeIO :: IO a -> GenericApplication a Source #

Ends the request excuting the provided IO and responding the result of the IO

Response Manipulatins

mapResponse :: (a -> b) -> GenericApplication a -> GenericApplication b Source #

Maps a response type to another response type

Requests functions

withRequest :: (Request -> GenericApplication a) -> GenericApplication a Source #

Pass the request to the provided function

Uri path functions

path :: Text -> GenericApplication r -> GenericApplication r Source #

Match the remaining path

pathSegment :: Text -> GenericApplication r -> GenericApplication r Source #

Match the next path segment and remove from the request

pathVar :: FromUri a => (a -> GenericApplication r) -> GenericApplication r Source #

Use the next path segment as a variable and remove from the request

pathEnd :: GenericApplication r -> GenericApplication r Source #

Match if all the path has been consumed or the remaining is a trailing slash

Query string functions

singleParameter :: FromUri a => ByteString -> (a -> GenericApplication b) -> GenericApplication b Source #

Match single parameter in the query string, fails when the parameter is not found or the query string contains multiple values for the parameter

maybeSingleParameter :: FromUri a => ByteString -> (Maybe a -> GenericApplication r) -> GenericApplication r Source #

Match single parameter in the query string, if multiple values for the same parameter found then fails

Http method

method :: StdMethod -> GenericApplication e -> GenericApplication e Source #

Match with standard http method

Entity based

Entity Based types

entity :: EntityResponse e -> e Source #

Entity Accessor

Basic entity functions

mapEntity :: (a -> b) -> EntityResponse a -> EntityResponse b Source #

Maps a entity response

withCustomNegotiation :: GenericApplication NegotiatedResponse -> GenericApplication Response Source #

Converts an application of NegotiatedResponse to a normal WAI Application

This will reject the request with not acceptable (406) in case the content negotation fail

Note: This is going to do the content negotiation after the inner application has repond with a NegotiatedResponse. That means, any IO is performed before the conetent negoatiation happen. TODO: Find another way to do custom negotiation Better to use @withCustomNegotiation'

withCustomNegotiation' :: [ByteString] -> GenericApplication NegotiatedResponse -> GenericApplication Response Source #

The same than @withCustomNegotiation but checking the Accept header before doing any IO

negotiated :: [(ByteString, a -> ByteString)] -> EntityResponse a -> NegotiatedResponse Source #

Converts a entity response to a negotiated entity

requestEntity :: [(ByteString, ByteString -> Either String a)] -> (a -> GenericApplication b) -> GenericApplication b Source #

Reads the entity and pass it to provided function

The map provides the accepted media types with the functions that decodes it

As specified in https://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2.1 a missing content type header from the request is treated "application/octet-stream"

Note: This will read all the payload in memory and then decode it so it can blow up the memory. Better to have a guard on the size of the request

ok :: a -> EntityResponse a Source #

Creates an entity response with status 200

created :: a -> EntityResponse a Source #

Creates a entity response with status 201

notFound :: a -> EntityResponse a Source #

Creates an entity response with status 404

badRequest :: a -> EntityResponse a Source #

Creates an entity response with status 400

entityResponse :: Status -> ResponseHeaders -> a -> EntityResponse a Source #

Creates a entity response with the provided status and response headers

Json based entity functions