Home

Awesome

API Server

TravisCI Status

An API Server in Haskell. Written as a demonstration of how to use hasql and scotty together in a realistic (we hope) api server application.

There's a User and a minimal Resource (which can easily be extended or copied). Even these two resources interact in a nice way to demonstrate things like required or optional parameters and token-based authentication.

Setup

This application is "cabalized" and so it should be the same as running any other cabal-managed application. Make sure that you have cabal and cabal-install installed and working. For the majority of users, installing the Haskell Platform will be all you need.

Next clone the repo and then initialize a new project. This project uses cabal freeze to lock-in the versions of the necessary dependencies.

git clone https://github.com/bendyworks/api_server.git
cd api_server

It is good practice to create a sandbox for installing packages into:

cabal sandbox init

Next install the project's dependencies. We'll also install the dependencies for tests:

cabal install --only-dependencies --enable-tests

At this point, go get a snack, it's going to build for a while. Next we need to initialize the database that the app depends upon. There's a script which will set up the database (you can also call db drop to drop the databases) This will create api_dev and api_test databases using the psql command:

./bin/db create

Lastly, we'll set some environment variables. I usually create a .env file with some details like this:

export DATABASE_URL="postgresql://postgres:@localhost:5432/api_dev"
export SMTP_SERVER=localhost
export SMTP_PORT=25
export SMTP_LOGIN=""
export SMTP_PASSWORD=""
export HASK_ENV=DEVELOPMENT
export PORT=3000

⚠️ Note: The same environment variables will need to be set in production.

Just to make sure everything worked, we'll build the tests and run them:

cabal test --show-details=always --test-options="--color"

If you look in the cabal file (api-server.cabal) you can see that the project is split into three pieces:

Undoubtedly, I will have missed something in these docs. Please file an issue and we'll get the setup corrected.

API Flow

The basic flow for the api is as follows:

REQ> POST /users

RSP> user_id: x, api_token: t

REQ> POST /users/$x
     { "resource_email": "email@example.com" }

RSP> "ok" (also sends an email to given address, with uuid)

REQ> GET /verify/$uuid

RSP> {resource_id: r, user_id: x}

REQ> POST /resource
     Header: "Authorization: Token $t"
     { "resource_email": "email@example.com"
     , "resource_name": "some name"
     , "resource_optional": "optional text"
     , "user_id": $x
     }

RSP> { "resource_email": "email@example.com"
     , "resource_name": "some name"
     , "resource_optional": "optional text"
     , "resource_id": $r
     }

Other documentation

There's a series of blog posts that describes how we built this application and the kinds of things that we were hoping to achieve:

Thanks