How to set up a simple web service
When we go about building a web service, we start by asking ourselves what sort of functionality the web service should provide to the clients.
For our example service, we will consider a single endpoint that computes the Fibonacci sequence at a given index.
The full specification looks something like this:
API Endpoint: GET /fibonacci/:n
Expected Output:
n >= 0:
Status Code: 200
{
"n":<n>,
"fib": <fib(n)>
}
n < 0:
Status Code: 412
Precondition Failed: n >= 0
By convention, we declare a type called API that consists of the specification for the web service.
1 | type API = "fibonacci" :> Capture "n" Int :> Get '[JSON] Value
|
Then, we define a proxy type which we can lets us pass around our API type as if it's a type argument.
1 2 | api :: Proxy API
api = Proxy
|
Note that the Proxy type only has a single value that can be constructed with the Proxy data constructor, but can take on any type based on the demand. Proxy types are typically used for sending type arguments to functions.
We will now define the handler for the route we defined in the API type.
1 2 3 4 5 | server :: Application
server = serve api fibHandler
where fibHandler n
| n >= 0 = return $ object ["n" .= n, "fib" .= fib n]
| otherwise = throwError $ err412 { errBody = "Precondition Failed: n > 0" }
|
Note the type of fibHandler is:
1 | fibHandler :: Int -> Handler Value
|