servant-checked-exceptions: Checked exceptions for Servant APIs.

[ bsd3, library, web ] [ Propose Tags ]

Please see README.md.


[Skip to Readme]

Flags

Automatic Flags
NameDescriptionDefault
buildexample

Build a small example program

Disabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Note: This package has metadata revisions in the cabal description newer than included in the tarball. To unpack the package including the revisions, use 'cabal get'.

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0, 0.1.0.1, 0.2.0.0, 0.3.0.0, 0.3.0.1, 0.3.0.2, 0.4.0.0, 0.4.1.0, 1.0.0.0, 1.1.0.0, 2.0.0.0, 2.1.0.0, 2.2.0.0, 2.2.0.1
Dependencies aeson, base (>=4.9 && <5), bytestring, deepseq, http-api-data, http-client, http-media, lens, natural-transformation, optparse-applicative, servant (>=0.9), servant-checked-exceptions, servant-client (>=0.9), servant-docs (>=0.9), servant-server (>=0.9), text, wai, warp [details]
License BSD-3-Clause
Copyright 2017 Dennis Gosnell
Author Dennis Gosnell
Maintainer cdep.illabout@gmail.com
Revised Revision 1 made by AdamBergmark at 2017-10-29T16:10:18Z
Category Text
Home page https://github.com/cdepillabout/servant-checked-exceptions
Source repo head: git clone git@github.com:cdepillabout/servant-checked-exceptions.git
Uploaded by cdepillabout at 2017-05-02T15:36:11Z
Distributions LTSHaskell:2.2.0.1, Stackage:2.2.0.1
Reverse Dependencies 1 direct, 0 indirect [details]
Executables servant-checked-exceptions-example-server, servant-checked-exceptions-example-docs, servant-checked-exceptions-example-client
Downloads 8958 total (64 in the last 30 days)
Rating 2.0 (votes: 1) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2017-05-02 [all 1 reports]

Readme for servant-checked-exceptions-0.2.0.0

[back to package description]

Servant.Checked.Exceptions

Build Status Hackage Stackage LTS Stackage Nightly BSD3 license

servant-checked-exceptions provides a way to specify errors thrown by a Servant api on the type level. It allows easy composition between different error types.

servant-checked-exceptions provides the Throws data type to signify which errors can be thrown by an api. For instance, imagine a getAuthor api that returns an Author based on an AuthorId:

-- This is a servant-compatible type describing our api.
type Api =
  "author" :>
  Capture "author-id" AuthorId :>
  Throws CouldNotConnectToDbError :>
  Throws AuthorNotFoundError :>
  Get '[JSON] Author

-- These are the two errors that can be thrown:
data CouldNotConnectToDbError = CouldNotConnectToDbError
data AuthorNotFoundError = AuthorNotFoundError

The corresponding handler function uses the Envelope data type to model the possibility of returning an Author successfully, or either CouldNotConnectToDbError or AuthorNotFoundError unsuccessfully. Internally, Envelope is using an open sum-type to easily represent multiple different errors:

getAuthorHandler
  :: AuthorId
  -> Handler (Envelope '[DatabaseError, AuthorNotFoundError] Author)
getAuthorHandler authorId = ...

For more documentation and usage examples, see the documentation on Hackage.

Why would I want to use this?

Using Envelope with its open sum-type to represent errors gives us an easy way to reuse errors on multiple routes.

For instance, imagine that we had another api for updating an author's name, given the author's ID. Using Throws and Envelope, it might look like this:

type Api =
  "update-author-name" :>
  Capture "author-id" AuthorId :>
  Capture "author-name" AuthorName :>
  Throws CouldNotConnectToDbError :>
  Throws AuthorNotFoundError :>
  Throws AuthorNameTooShort :>
  Post '[JSON] Author

data AuthorNameTooShort = AuthorNameTooShort

postChangeAuthorName
  :: AuthorId
  -> AuthorName
  -> Handler (Envelope '[DatabaseError, AuthorNotFoundError, AuthorNameTooShort] Author)
postChangeAuthorName authorId newAuthorName = ...

We are able to reuse the DatabaseError and AuthorNotFoundError. If we try to return an error that is not declared using Throws, GHC will give us an error. We get flexiblity and type-safety.

When using servant-docs to create documentation, only one instance of ToSample needs to be created for each error (DatabaseError, AuthorNotFoundError, and AuthorNameTooShort). Multiple instances of ToSample do not need to be created for every different Envelope used in a handler.

Example

This repository contains an example of using servant-checked-exceptions. This includes an api, server, client, and documentation.

Below I show how to compile and run these examples.

Compile

The examples can be compiled by using the buildexample flag:

$ stack build --flag servant-checked-exceptions:buildexample

This creates three executables. A server, a client, and a documentaiton generator.

Run the server

The server is a small example that will take search queries and return results. The server can be run with the following command:

$ stack exec -- servant-checked-exceptions-example-server

This runs the server on port 8201. Here is an example of using curl to access the server. This will send the query hello:

$ curl \
    --request POST \
    --header 'Accept: application/json' \
    'http://localhost:8201/lax-search/hello'
{"data":"good"}

If you try to send a query that is not hello, the server will return an error:

$ curl \
    --request POST \
    --header 'Accept: application/json' \
    'http://localhost:8201/lax-search/hello'
{"err":"BadSearchTermErr"}

There is also a strict api, that requires hello to be capitalized like Hello:

$ curl \
    --request POST \
    --header 'Accept: application/json' \
    'http://localhost:8201/strict-search/hello'
{"err":"IncorrectCapitalization"}
$ curl \
    --request POST \
    --header 'Accept: application/json' \
    'http://localhost:8201/strict-search/Hello'
{"data":"good"}

Run the client

The client provides a small command line application to query the server. In order to use the client, the server must be running.

Use the client to access the lax search api:

$ stack exec -- servant-checked-exceptions-example-client foobar
the search term was not "Hello"
$ stack exec -- servant-checked-exceptions-example-client hello
Success: good

Use the client to access the strict search api:

$ stack exec -- servant-checked-exceptions-example-client --strict hello
the search term was not capitalized correctly
$ stack exec -- servant-checked-exceptions-example-client --strict Hello
Success: good

Run the documentation generator

The documentation generator will generate documentation for the api in Markdown:

$ stack exec -- servant-checked-exceptions-example-docs

Here is a small example of the documentation that will be generated for the lax search api:

## POST /lax-search/:query

#### Captures:

- *query*: a search string like "hello" or "bye"

#### Response:

- Status code 200
- Headers: []

- Supported content types are:

    - `application/json`

- This is a successful response.

{"data":"good"}

- a completely incorrect search term was used

{"err":"BadSearchTermErr"}

You can see that both the success and error responses are documented.