**Important**: the `Servant` module comes from the *servant-server* package, the one that lets us run webservers that implement a particular API type. It reexports all the types from the *servant* package that let you declare API types as well as everything you need to turn your request handlers into a fully-fledged webserver. This means that in your applications, you can just add *servant-server* as a dependency, import `Servant` and not worry about anything else.
We will write a server that will serve the following API.
> type UserAPI1 = "users" :> Get '[JSON] [User]
Here's what we would like to see when making a GET request to `/users`.
We can now take care of writing the actual webservice that will handle requests
to such an API. This one will be very simple, being reduced to just a single
endpoint. The type of the web application is determined by the API type,
through a *type family* named `Server`. (Type families are just functions that
take types as input and return types.) The `Server` type family will compute
the right type that a bunch of request handlers should have just from the
corresponding API type.
The first thing to know about the `Server` type family is that behind the
scenes it will drive the routing, letting you focus only on the business
logic. The second thing to know is that for each endpoint, your handlers will
by default run in the `EitherT ServantErr IO` monad. This is overridable very
easily, as explained near the end of this guide. Third thing, the type of the
value returned in that monad must be the same as the second argument of the
HTTP method combinator used for the corresponding endpoint. In our case, it
means we must provide a handler of type `EitherT ServantErr IO [User]`. Well,
we have a monad, let's just `return` our list:
> server1 :: Server UserAPI1
> server1 = return users1
That's it. Now we can turn `server` into an actual webserver using [wai](http://hackage.haskell.org/package/wai) and [warp](http://hackage.haskell.org/package/warp):
> userAPI :: Proxy UserAPI1
> userAPI = Proxy
>
> -- 'serve' comes from servant and hands you a WAI Application,
> -- which you can think of as an "abstract" web application,
> -- not yet a webserver.
> app1 :: Application
> app1 = serve userAPI server1
The `userAPI` bit is, alas, boilerplate (we need it to guide type inference).
But that's about as much boilerplate as you get.
And we're done! Let's run our webservice on the port 8081.
> main :: IO ()
> main = run 8081 app1
You can put this all into a file or just grab [servant's
repo](http://github.com/haskell-servant/servant) and look at the
*servant-examples* directory. The code we have just explored is in
*tutorial/T1.hs*, runnable with
`dist/build/tutorial/tutorial 1`.
If you run it, you can go to `http://localhost:8081/users` in your browser or
{"subject":"Hey Alp Mestanogullari, we miss you!","body":"Hi Alp Mestanogullari,\n\nSince you've recently turned 25, have you checked out our latest haskell, mathematics products? Give us a visit!","to":"alp@foo.com","from":"great@company.com"}
```
For reference, here's a list of some combinators from *servant* and for those
that get turned into arguments to the handlers, the type of the argument.
> - `Delete`, `Get`, `Patch`, `Post`, `Put`: these do not become arguments. They provide the return type of handlers, which usually is `EitherT ServantErr IO <something>`.
> - `Capture "something" a` becomes an argument of type `a`.
> - `QueryParam "something" a`, `MatrixParam "something" a`, `Header "something" a` all become arguments of type `Maybe a`, because there might be no value at all specified by the client for these.
> - `QueryFlag "something"` and `MatrixFlag "something"` get turned into arguments of type `Bool`.
> - `QueryParams "something" a` and `MatrixParams "something" a` get turned into arguments of type `[a]`.
> - `ReqBody contentTypes a` gets turned into an argument of type `a`.
The `FromText`/`ToText` classes
===============================
Wait... How does *servant* know how to decode the `Int`s from the URL? Or how
to decode a `ClientInfo` value from the request body? This is what this and the
following two sections address.
`Capture`s and `QueryParam`s are represented by some textual value in URLs.
`Header`s are similarly represented by a pair of a header name and a
corresponding (textual) value in the request's "metadata". This is why we
decided to provide a pair of typeclasses, `FromText` and `ToText` which just
let you say that you can respectively *extract* or *encode* values of some type
Allows you to return an error from your handler (whereas `return` is enough to
return a success).
Most of what you'll be doing in your handlers is running some IO and,
depending on the result, you might sometimes want to throw an error of some
kind and abort early. The next two sections cover how to do just that.
Performing IO
-------------
Another important instance from the list above is `MonadIO m => MonadIO (EitherT e m)`. [`MonadIO`](http://hackage.haskell.org/package/transformers-0.4.3.0/docs/Control-Monad-IO-Class.html) is a class from the *transformers* package defined as:
Obviously, the `IO` monad provides a `MonadIO` instance. Hence for any type `e`, `EitherT e IO` has a `MonadIO` instance. So if you want to run any kind of IO computation in your handlers, just use `liftIO`:
> type IOAPI1 = "myfile.txt" :> Get '[JSON] FileContent
>
> newtype FileContent = FileContent
> { content :: String }
> deriving Generic
>
> instance ToJSON FileContent
>
> server5 :: Server IOAPI1
> server5 = do
> filecontent <- liftIO (readFile "myfile.txt")
> return (FileContent filecontent)
Failing, through `ServantErr`
-----------------------------
If you want to explicitly fail at providing the result promised by an endpoint
using the appropriate HTTP status code (not found, unauthorized, etc) and some
error message, all you have to do is use the `left` function mentioned above
and provide it with the appropriate value of type `ServantErr`, which is
`serveDirectory`'s argument must be a path to a valid directory. You can see an
example below, runnable with `dist/build/tutorial/tutorial 6`
(you **must** run it from within the *servant-examples/* directory!), which is
a webserver that serves the various bits of code covered in this
getting-started.
The API type will be the following.
> type CodeAPI = "code" :> Raw
And the server:
> codeAPI :: Proxy CodeAPI
> codeAPI = Proxy
> server7 :: Server CodeAPI
> server7 = serveDirectory "tutorial"
>
> app3 :: Application
> app3 = serve codeAPI server7
This server will match any request whose path starts with `/code` and will look for a file at the path described by the rest of the request path, inside the *tutorial/* directory of the path you run the program from.
In other words:
- If a client requests `/code/foo.txt`, the server will look for a file at `./tutorial/foo.txt` (and fail)
- If a client requests `/code/T1.hs`, the server will look for a file at `./tutorial/T1.hs` (and succeed)
- If a client requests `/code/foo/bar/baz/movie.mp4`, the server will look for a file at `./tutorial/foo/bar/baz/movie.mp4` (and fail)
> where getUser :: Int -> EitherT ServantErr IO User
> getUser = error "..."
>
> deleteUser :: Int -> EitherT ServantErr IO ()
> deleteUser = error "..."
Note that there's nothing special about `Capture` that lets you "factor it out": this can be done with any combinator. Here are a few examples of APIs with a combinator factored out for which we can write a perfectly valid `Server`.
> -- we just factor out the "users" path fragment
> type API1 = "users" :>
> ( Get '[JSON] [User] -- user listing
> :<|> Capture "userid" Int :> Get '[JSON] User -- view a particular user
> )
>
> -- we factor out the Request Body
> type API2 = ReqBody '[JSON] User :>
> ( Get '[JSON] User -- just display the same user back, don't register it
> :<|> Post '[JSON] () -- register the user. empty response
> )
>
> -- we factor out a Header
> type API3 = Header "Authorization" Token :>
> ( Get '[JSON] SecretData -- get some secret data, if authorized
> :<|> ReqBody '[JSON] SecretData :> Post '[] () -- add some secret data, if authorized
> )
>
> newtype Token = Token ByteString
> newtype SecretData = SecretData ByteString
This approach lets you define APIs modularly and assemble them all into one big API type only at the end.
> type UsersAPI =
> Get '[JSON] [User] -- list users
> :<|> ReqBody '[JSON] User :> Post '[] () -- add a user
> :<|> Capture "userid" Int :>
> ( Get '[JSON] User -- view a user
> :<|> ReqBody '[JSON] User :> Put '[] () -- update a user
> deleteProduct :: Int -> EitherT ServantErr IO ()
> deleteProduct = error "..."
> type CombinedAPI = "users" :> UsersAPI
> :<|> "products" :> ProductsAPI
>
> server10 :: Server CombinedAPI
> server10 = usersServer :<|> productsServer
Finally, we can realize the user and product APIs are quite similar and abstract that away:
> -- API for values of type 'a'
> -- indexed by values of type 'i'
> type APIFor a i =
> Get '[JSON] [a] -- list 'a's
> :<|> ReqBody '[JSON] a :> Post '[] () -- add an 'a'
> :<|> Capture "id" i :>
> ( Get '[JSON] a -- view an 'a' given its "identifier" of type 'i'
> :<|> ReqBody '[JSON] a :> Put '[] () -- update an 'a'
> :<|> Delete '[] () -- delete an 'a'
> )
>
> -- Build the appropriate 'Server'
> -- given the handlers of the right type.
> serverFor :: EitherT ServantErr IO [a] -- handler for listing of 'a's
> -> (a -> EitherT ServantErr IO ()) -- handler for adding an 'a'
> -> (i -> EitherT ServantErr IO a) -- handler for viewing an 'a' given its identifier of type 'i'
> -> (i -> a -> EitherT ServantErr IO ()) -- updating an 'a' with given id
> -> (i -> EitherT ServantErr IO ()) -- deleting an 'a' given its id
> -> Server (APIFor a i)
> serverFor = error "..."
> -- implementation left as an exercise. contact us on IRC
> -- or the mailing list if you get stuck!
Using another monad for your handlers
=====================================
Remember how `Server` turns combinators for HTTP methods into `EitherT ServantErr IO`? Well, actually, there's more to that. `Server` is actually a simple type synonym.
type Server api = ServerT api (EitherT ServantErr IO)
```
`ServerT` is the actual type family that computes the required types for the handlers that's part of the `HasServer` class. It's like `Server` except that it takes a third parameter which is the monad you want your handlers to run in, or more generally the return types of your handlers. This third parameter is used for specifying the return type of the handler for an endpoint, e.g when computing `ServerT (Get '[JSON] Person) SomeMonad`. The result would be `SomeMonad Person`.
The first and main question one might have then is: how do we write handlers that run in another monad? How can we "bring back" the value from a given monad into something *servant* can understand?
Natural transformations
-----------------------
If we have a function that gets us from an `m a` to an `n a`, for any `a`, what
We unfortunately can't use `readerServerT` as an argument of `serve`, because
`serve` wants a `Server ReaderAPI`, i.e., with handlers running in `EitherT
ServantErr IO`. But there's a simple solution to this.
Enter `enter`
-------------
That's right. We have just written `readerToEither`, which is exactly what we
would need to apply to the results of all handlers to make the handlers have the
right type for `serve`. Being cumbersome to do by hand, we provide a function
`enter` which takes a natural transformation between two parametrized types `m`
and `n` and a `ServerT someapi m`, and returns a `ServerT someapi n`.
In our case, we can wrap up our little webservice by using `enter readerToEither` on our handlers.
> readerServer :: Server ReaderAPI
> readerServer = enter readerToEither readerServerT
>
> app4 :: Application
> app4 = serve readerAPI readerServer
And we can indeed see this webservice in action by running `dist/build/tutorial/tutorial 7`.
``` bash
$ curl http://localhost:8081/a
1797
$ curl http://localhost:8081/b
"hi"
```
Conclusion
==========
You're now equipped to write any kind of webservice/web-application using *servant*. One thing not covered here is how to incorporate your own combinators and will be the topic of a page on the website. The rest of this document focuses on *servant-client*, *servant-jquery* and *servant-docs*.
<div style="text-align: center;">
<p><a href="/tutorial/api-type.html">Previous page: A web API as a type</a></p>
<p><a href="/tutorial/client.html">Next page: Deriving Haskell functions to query an API</a></p>