@@ -0,0 +1,1176 @@
1+---
2+title: Serving an API
3+toc: true
4+---
5+
6+Enough chit-chat about type-level combinators and representing an API as a
7+type. Can we have a webservice already?
8+
9+If you want to follow along with the code and run the examples while you read this guide:
10+
11+``` bash
12+cabal get servant-examples
13+cd servant-examples-<VERSION>
14+cabal sandbox init
15+cabal install --dependencies-only
16+cabal configure && cabal build
17+```
18+
19+This will produce a `tutorial` executable in the
20+`dist/build/tutorial` directory that just runs the example corresponding
21+to the number specified as a command line argument:
22+
23+``` bash
24+$ dist/build/tutorial/tutorial
25+Usage: tutorial N
26+ where N is the number of the example you want to run.
27+```
28+
29+A first example
30+===============
31+
32+Equipped with some basic knowledge about the way we represent API, let's now write our first webservice.
33+
34+The source for this tutorial section is a literate haskell file, so first we
35+need to have some language extensions and imports:
36+
37+> {-# LANGUAGE DataKinds #-}
38+> {-# LANGUAGE DeriveGeneric #-}
39+> {-# LANGUAGE FlexibleInstances #-}
40+> {-# LANGUAGE GeneralizedNewtypeDeriving #-}
41+> {-# LANGUAGE MultiParamTypeClasses #-}
42+> {-# LANGUAGE OverloadedStrings #-}
43+> {-# LANGUAGE ScopedTypeVariables #-}
44+> {-# LANGUAGE TypeOperators #-}
45+>
46+> module Server where
47+>
48+> import Control.Monad.IO.Class
49+> import Control.Monad.Reader
50+> import Control.Monad.Trans.Either
51+> import Data.Aeson
52+> import Data.Aeson.Types
53+> import Data.Attoparsec.ByteString
54+> import Data.ByteString (ByteString)
55+> import Data.Int
56+> import Data.List
57+> import Data.String.Conversions
58+> import Data.Time.Calendar
59+> import GHC.Generics
60+> import Lucid
61+> import Network.HTTP.Media ((//), (/:))
62+> import Network.Wai
63+> import Network.Wai.Handler.Warp
64+> import Servant
65+> import System.Directory
66+> import Text.Blaze
67+> import Text.Blaze.Html.Renderer.Utf8
68+> import qualified Data.Aeson.Parser
69+> import qualified Text.Blaze.Html
70+
71+``` haskell
72+{-# LANGUAGE TypeFamilies #-}
73+```
74+
75+**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.
76+
77+We will write a server that will serve the following API.
78+
79+> type UserAPI1 = "users" :> Get '[JSON] [User]
80+
81+Here's what we would like to see when making a GET request to `/users`.
82+
83+``` javascript
84+[ {"name": "Isaac Newton", "age": 372, "email": "isaac@newton.co.uk", "registration_date": "1683-03-01"}
85+, {"name": "Albert Einstein", "age": 136, "email": "ae@mc2.org", "registration_date": "1905-12-01"}
86+]
87+```
88+
89+Now let's define our `User` data type and write some instances for it.
90+
91+> data User = User
92+> { name :: String
93+> , age :: Int
94+> , email :: String
95+> , registration_date :: Day
96+> } deriving (Eq, Show, Generic)
97+>
98+> instance ToJSON User
99+
100+Nothing funny going on here. But we now can define our list of two users.
101+
102+> users1 :: [User]
103+> users1 =
104+> [ User "Isaac Newton" 372 "isaac@newton.co.uk" (fromGregorian 1683 3 1)
105+> , User "Albert Einstein" 136 "ae@mc2.org" (fromGregorian 1905 12 1)
106+> ]
107+
108+Let's also write our API type.
109+
110+``` haskell
111+type UserAPI1 = "users" :> Get '[JSON] [User]
112+```
113+
114+We can now take care of writing the actual webservice that will handle requests
115+to such an API. This one will be very simple, being reduced to just a single
116+endpoint. The type of the web application is determined by the API type,
117+through a *type family* named `Server`. (Type families are just functions that
118+take types as input and return types.) The `Server` type family will compute
119+the right type that a bunch of request handlers should have just from the
120+corresponding API type.
121+
122+The first thing to know about the `Server` type family is that behind the
123+scenes it will drive the routing, letting you focus only on the business
124+logic. The second thing to know is that for each endpoint, your handlers will
125+by default run in the `EitherT ServantErr IO` monad. This is overridable very
126+easily, as explained near the end of this guide. Third thing, the type of the
127+value returned in that monad must be the same as the second argument of the
128+HTTP method combinator used for the corresponding endpoint. In our case, it
129+means we must provide a handler of type `EitherT ServantErr IO [User]`. Well,
130+we have a monad, let's just `return` our list:
131+
132+> server1 :: Server UserAPI1
133+> server1 = return users1
134+
135+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):
136+
137+> userAPI :: Proxy UserAPI1
138+> userAPI = Proxy
139+>
140+> -- 'serve' comes from servant and hands you a WAI Application,
141+> -- which you can think of as an "abstract" web application,
142+> -- not yet a webserver.
143+> app1 :: Application
144+> app1 = serve userAPI server1
145+
146+The `userAPI` bit is, alas, boilerplate (we need it to guide type inference).
147+But that's about as much boilerplate as you get.
148+
149+And we're done! Let's run our webservice on the port 8081.
150+
151+> main :: IO ()
152+> main = run 8081 app1
153+
154+You can put this all into a file or just grab [servant's
155+repo](http://github.com/haskell-servant/servant) and look at the
156+*servant-examples* directory. The code we have just explored is in
157+*tutorial/T1.hs*, runnable with
158+`dist/build/tutorial/tutorial 1`.
159+
160+If you run it, you can go to `http://localhost:8081/users` in your browser or
161+query it with curl and you see:
162+
163+``` bash
164+$ curl http://localhost:8081/users
165+[{"email":"isaac@newton.co.uk","registration_date":"1683-03-01","age":372,"name":"Isaac Newton"},{"email":"ae@mc2.org","registration_date":"1905-12-01","age":136,"name":"Albert Einstein"}]
166+```
167+
168+More endpoints
169+==============
170+
171+What if we want more than one endpoint? Let's add `/albert` and `/isaac` to view the corresponding users encoded in JSON.
172+
173+> type UserAPI2 = "users" :> Get '[JSON] [User]
174+> :<|> "albert" :> Get '[JSON] User
175+> :<|> "isaac" :> Get '[JSON] User
176+
177+And let's adapt our code a bit.
178+
179+> isaac :: User
180+> isaac = User "Isaac Newton" 372 "isaac@newton.co.uk" (fromGregorian 1683 3 1)
181+>
182+> albert :: User
183+> albert = User "Albert Einstein" 136 "ae@mc2.org" (fromGregorian 1905 12 1)
184+>
185+> users2 :: [User]
186+> users2 = [isaac, albert]
187+
188+Now, just like we separate the various endpoints in `UserAPI` with `:<|>`, we
189+are going to separate the handlers with `:<|>` too! They must be provided in
190+the same order as the one they appear in in the API type.
191+
192+> server2 :: Server UserAPI2
193+> server2 = return users2
194+> :<|> return albert
195+> :<|> return isaac
196+
197+And that's it! You can run this example with
198+`dist/build/tutorial/tutorial 2` and check out the data available
199+at `/users`, `/albert` and `/isaac`.
200+
201+From combinators to handler arguments
202+=====================================
203+
204+Fine, we can write trivial webservices easily, but none of the two above use
205+any "fancy" combinator from servant. Let's address this and use `QueryParam`,
206+`Capture` and `ReqBody` right away. You'll see how each occurence of these
207+combinators in an endpoint makes the corresponding handler receive an
208+argument of the appropriate type automatically. You don't have to worry about
209+manually looking up URL captures or query string parameters, or
210+decoding/encoding data from/to JSON. Never.
211+
212+We are going to use the following data types and functions to implement a server for `API`.
213+
214+> type API = "position" :> Capture "x" Int :> Capture "y" Int :> Get '[JSON] Position
215+> :<|> "hello" :> QueryParam "name" String :> Get '[JSON] HelloMessage
216+> :<|> "marketing" :> ReqBody '[JSON] ClientInfo :> Post '[JSON] Email
217+>
218+> data Position = Position
219+> { x :: Int
220+> , y :: Int
221+> } deriving Generic
222+>
223+> instance ToJSON Position
224+>
225+> newtype HelloMessage = HelloMessage { msg :: String }
226+> deriving Generic
227+>
228+> instance ToJSON HelloMessage
229+>
230+> data ClientInfo = ClientInfo
231+> { clientName :: String
232+> , clientEmail :: String
233+> , clientAge :: Int
234+> , clientInterestedIn :: [String]
235+> } deriving Generic
236+>
237+> instance FromJSON ClientInfo
238+> instance ToJSON ClientInfo
239+>
240+> data Email = Email
241+> { from :: String
242+> , to :: String
243+> , subject :: String
244+> , body :: String
245+> } deriving Generic
246+>
247+> instance ToJSON Email
248+>
249+> emailForClient :: ClientInfo -> Email
250+> emailForClient c = Email from' to' subject' body'
251+>
252+> where from' = "great@company.com"
253+> to' = clientEmail c
254+> subject' = "Hey " ++ clientName c ++ ", we miss you!"
255+> body' = "Hi " ++ clientName c ++ ",\n\n"
256+> ++ "Since you've recently turned " ++ show (clientAge c)
257+> ++ ", have you checked out our latest "
258+> ++ intercalate ", " (clientInterestedIn c)
259+> ++ " products? Give us a visit!"
260+
261+We can implement handlers for the three endpoints:
262+
263+> server3 :: Server API
264+> server3 = position
265+> :<|> hello
266+> :<|> marketing
267+>
268+> where position :: Int -> Int -> EitherT ServantErr IO Position
269+> position x y = return (Position x y)
270+>
271+> hello :: Maybe String -> EitherT ServantErr IO HelloMessage
272+> hello mname = return . HelloMessage $ case mname of
273+> Nothing -> "Hello, anonymous coward"
274+> Just n -> "Hello, " ++ n
275+>
276+> marketing :: ClientInfo -> EitherT ServantErr IO Email
277+> marketing clientinfo = return (emailForClient clientinfo)
278+
279+Did you see that? The types for your handlers changed to be just what we
280+needed! In particular:
281+
282+ - a `Capture "something" a` becomes an argument of type `a` (for `position`);
283+ - a `QueryParam "something" a` becomes an argument of type `Maybe a` (because
284+an endpoint can technically be accessed without specifying any query
285+string parameter, we decided to "force" handlers to be aware that the
286+parameter might not always be there);
287+
288+ - a `ReqBody contentTypeList a` becomes an argument of type `a`;
289+
290+And that's it. You can see this example in action by running `dist/build/tutorial/tutorial 3`.
291+
292+``` bash
293+$ curl http://localhost:8081/position/1/2
294+{"x":1,"y":2}
295+$ curl http://localhost:8081/hello
296+{"msg":"Hello, anonymous coward"}
297+$ curl http://localhost:8081/hello?name=Alp
298+{"msg":"Hello, Alp"}
299+$ curl -X POST -d '{"name":"Alp Mestanogullari", "email" : "alp@foo.com", "age": 25, "interested_in": ["haskell", "mathematics"]}' -H 'Accept: application/json' -H 'Content-type: application/json' http://localhost:8081/marketing
300+{"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"}
301+```
302+
303+For reference, here's a list of some combinators from *servant* and for those
304+that get turned into arguments to the handlers, the type of the argument.
305+
306+ > - `Delete`, `Get`, `Patch`, `Post`, `Put`: these do not become arguments. They provide the return type of handlers, which usually is `EitherT ServantErr IO <something>`.
307+ > - `Capture "something" a` becomes an argument of type `a`.
308+ > - `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.
309+ > - `QueryFlag "something"` and `MatrixFlag "something"` get turned into arguments of type `Bool`.
310+ > - `QueryParams "something" a` and `MatrixParams "something" a` get turned into arguments of type `[a]`.
311+ > - `ReqBody contentTypes a` gets turned into an argument of type `a`.
312+
313+The `FromText`/`ToText` classes
314+===============================
315+
316+Wait... How does *servant* know how to decode the `Int`s from the URL? Or how
317+to decode a `ClientInfo` value from the request body? This is what this and the
318+following two sections address.
319+
320+`Capture`s and `QueryParam`s are represented by some textual value in URLs.
321+`Header`s are similarly represented by a pair of a header name and a
322+corresponding (textual) value in the request's "metadata". This is why we
323+decided to provide a pair of typeclasses, `FromText` and `ToText` which just
324+let you say that you can respectively *extract* or *encode* values of some type
325+*from*/*to* text. Here are the definitions:
326+
327+``` haskell
328+class FromText a where
329+ fromText :: Text -> Maybe a
330+
331+class ToText a where
332+ toText :: a -> Text
333+```
334+
335+And as long as the type that a `Capture`/`QueryParam`/`Header`/etc will be
336+decoded to provides a `FromText` instance, it will Just Work. *servant*
337+provides a decent number of instances, but here are some examples of defining
338+your own.
339+
340+> -- A typical enumeration
341+> data Direction
342+> = Up
343+> | Down
344+> | Left
345+> | Right
346+>
347+> instance FromText Direction where
348+> -- requires {-# LANGUAGE OverloadedStrings #-}
349+> fromText "up" = Just Up
350+> fromText "down" = Just Down
351+> fromText "left" = Just Server.Left
352+> fromText "right" = Just Server.Right
353+> fromText _ = Nothing
354+>
355+> instance ToText Direction where
356+> toText Up = "up"
357+> toText Down = "down"
358+> toText Server.Left = "left"
359+> toText Server.Right = "right"
360+>
361+> newtype UserId = UserId Int64
362+> deriving (FromText, ToText)
363+
364+or writing the instances by hand:
365+
366+``` haskell
367+instance FromText UserId where
368+ fromText = fmap UserId fromText
369+
370+instance ToText UserId where
371+ toText (UserId i) = toText i
372+```
373+
374+There's not much else to say about these classes. You will need instances for
375+them when using `Capture`, `QueryParam`, `QueryParams`, `MatrixParam`,
376+`MatrixParams` and `Header` with your types. You will need `FromText` instances
377+for server-side request handlers and `ToText` instances only when using
378+*servant-client*, as described in the [section about deriving haskell
379+functions to query an API](/tutorial/client.html).
380+
381+Using content-types with your data types
382+========================================
383+
384+The same principle was operating when decoding request bodies from JSON, and
385+responses *into* JSON. (JSON is just the running example - you can do this with
386+any content-type.)
387+
388+This section introduces a couple of typeclasses provided by *servant* that make
389+all of this work.
390+
391+The truth behind `JSON`
392+-----------------------
393+
394+What exactly is `JSON`? Like the 3 other content types provided out of the box
395+by *servant*, it's a really dumb data type.
396+
397+``` haskell
398+data JSON
399+data PlainText
400+data FormUrlEncoded
401+data OctetStream
402+```
403+
404+Obviously, this is not all there is to `JSON`, otherwise it would be quite
405+pointless. Like most of the data types in *servant*, `JSON` is mostly there as
406+a special *symbol* that's associated with encoding (resp. decoding) to (resp.
407+from) the *JSON* format. The way this association is performed can be
408+decomposed into two steps.
409+
410+The first step is to provide a proper
411+[`MediaType`](https://hackage.haskell.org/package/http-media-0.6.2/docs/Network-HTTP-Media.html)
412+representation for `JSON`, or for your own content types. If you look at the
413+haddocks from this link, you can see that we just have to specify
414+`application/json` using the appropriate functions. In our case, we can just
415+use `(//) :: ByteString -> ByteString -> MediaType`. The precise way to specify
416+the `MediaType` is to write an instance for the `Accept` class:
417+
418+``` haskell
419+-- for reference:
420+class Accept ctype where
421+ contentType :: Proxy ctype -> MediaType
422+
423+instance Accept JSON where
424+ contentType _ = "application" // "json"
425+```
426+
427+The second step is centered around the `MimeRender` and `MimeUnrender` classes.
428+These classes just let you specify a way to respectively encode and decode
429+values respectively into or from your content-type's representation.
430+
431+``` haskell
432+class Accept ctype => MimeRender ctype a where
433+ mimeRender :: Proxy ctype -> a -> ByteString
434+ -- alternatively readable as:
435+ mimeRender :: Proxy ctype -> (a -> ByteString)
436+```
437+
438+Given a content-type and some user type, `MimeRender` provides a function that
439+encodes values of type `a` to lazy `ByteString`s.
440+
441+In the case of `JSON`, this is easily dealt with! For any type `a` with a
442+`ToJSON` instance, we can render values of that type to JSON using
443+`Data.Aeson.encode`.
444+
445+``` haskell
446+instance ToJSON a => MimeRender JSON a where
447+ mimeRender _ = encode
448+```
449+
450+And now the `MimeUnrender` class, which lets us extract values from lazy
451+`ByteString`s, alternatively failing with an error string.
452+
453+``` haskell
454+class Accept ctype => MimeUnrender ctype a where
455+ mimeUnrender :: Proxy ctype -> ByteString -> Either String a
456+ -- alternatively:
457+ mimeUnrender :: Proxy ctype -> (ByteString -> Either String a)
458+```
459+
460+We don't have much work to do there either, `Data.Aeson.eitherDecode` is
461+precisely what we need. However, it only allows arrays and objects as toplevel
462+JSON values and this has proven to get in our way more than help us so we wrote
463+our own little function around *aeson* and *attoparsec* that allows any type of
464+JSON value at the toplevel of a "JSON document". Here's the definition in case
465+you are curious.
466+
467+> eitherDecodeLenient :: FromJSON a => ByteString -> Either String a
468+> eitherDecodeLenient input = do
469+> v :: Value <- parseOnly (Data.Aeson.Parser.value <* endOfInput) (cs input)
470+> parseEither parseJSON v
471+
472+This function is exactly what we need for our `MimeUnrender` instance.
473+
474+``` haskell
475+instance FromJSON a => MimeUnrender JSON a where
476+ mimeUnrender _ = eitherDecodeLenient
477+```
478+
479+And this is all the code that lets you use `JSON` for with `ReqBody`, `Get`,
480+`Post` and friends. We can check our understanding by implementing support
481+for an `HTML` content type, so that users of your webservice can access an
482+HTML representation of the data they want, ready to be included in any HTML
483+document, e.g. using [jQuery's `load` function](https://api.jquery.com/load/), simply by adding `Accept:
484+text/html` to their request headers.
485+
486+Case-studies: *servant-blaze* and *servant-lucid*
487+-------------------------------------------------
488+
489+These days, most of the haskellers who write their HTML UIs directly from
490+Haskell use either [blaze-html](http://hackage.haskell.org/package/blaze-html)
491+or [lucid](http://hackage.haskell.org/package/lucid). The best option for
492+*servant* is obviously to support both (and hopefully other templating
493+solutions!).
494+
495+> data HTMLLucid
496+
497+Once again, the data type is just there as a symbol for the encoding/decoding
498+functions, except that this time we will only worry about encoding since
499+*blaze-html* and *lucid* don't provide a way to extract data from HTML.
500+
501+Both packages also have the same `Accept` instance for their `HTMLLucid` type.
502+
503+> instance Accept HTMLLucid where
504+> contentType _ = "text" // "html" /: ("charset", "utf-8")
505+
506+Note that this instance uses the `(/:)` operator from *http-media* which lets
507+us specify additional information about a content-type, like the charset here.
508+
509+The rendering instances for both packages both call similar functions that take
510+types with an appropriate instance to an "abstract" HTML representation and
511+then write that to a `ByteString`.
512+
513+For *lucid*:
514+
515+> instance ToHtml a => MimeRender HTMLLucid a where
516+> mimeRender _ = renderBS . toHtml
517+>
518+> -- let's also provide an instance for lucid's
519+> -- 'Html' wrapper.
520+> instance MimeRender HTMLLucid (Html a) where
521+> mimeRender _ = renderBS
522+
523+For *blaze-html*:
524+
525+> -- For this tutorial to compile 'HTMLLucid' and 'HTMLBlaze' have to be
526+> -- distinct. Usually you would stick to one html rendering library and then
527+> -- you can go with one 'HTML' type.
528+> data HTMLBlaze
529+>
530+> instance Accept HTMLBlaze where
531+> contentType _ = "text" // "html" /: ("charset", "utf-8")
532+>
533+> instance ToMarkup a => MimeRender HTMLBlaze a where
534+> mimeRender _ = renderHtml . Text.Blaze.Html.toHtml
535+>
536+> -- while we're at it, just like for lucid we can
537+> -- provide an instance for rendering blaze's 'Html' type
538+> instance MimeRender HTMLBlaze Text.Blaze.Html.Html where
539+> mimeRender _ = renderHtml
540+
541+Both [servant-blaze](http://hackage.haskell.org/package/servant-blaze) and
542+[servant-lucid](http://hackage.haskell.org/package/servant-lucid) let you use
543+`HTMLLucid` in any content type list as long as you provide an instance of the
544+appropriate class (`ToMarkup` for *blaze-html*, `ToHtml` for *lucid*).
545+
546+We can now write webservice that uses *servant-lucid* to show the `HTMLLucid`
547+content type in action. First off, imports and pragmas as usual.
548+
549+We will be serving the following API:
550+
551+> type PersonAPI = "persons" :> Get '[JSON, HTMLLucid] [Person]
552+
553+where `Person` is defined as follows:
554+
555+> data Person = Person
556+> { firstName :: String
557+> , lastName :: String
558+> } deriving Generic -- for the JSON instance
559+>
560+> instance ToJSON Person
561+
562+Now, let's teach *lucid* how to render a `Person` as a row in a table, and then
563+a list of `Person`s as a table with a row per person.
564+
565+> -- HTML serialization of a single person
566+> instance ToHtml Person where
567+> toHtml person =
568+> tr_ $ do
569+> td_ (toHtml $ firstName person)
570+> td_ (toHtml $ lastName person)
571+>
572+> -- do not worry too much about this
573+> toHtmlRaw = toHtml
574+>
575+> -- HTML serialization of a list of persons
576+> instance ToHtml [Person] where
577+> toHtml persons = table_ $ do
578+> tr_ $ do
579+> th_ "first name"
580+> th_ "last name"
581+>
582+> -- this just calls toHtml on each person of the list
583+> -- and concatenates the resulting pieces of HTML together
584+> foldMap toHtml persons
585+>
586+> toHtmlRaw = toHtml
587+
588+We create some `Person` values and serve them as a list:
589+
590+> persons :: [Person]
591+> persons =
592+> [ Person "Isaac" "Newton"
593+> , Person "Albert" "Einstein"
594+> ]
595+>
596+> personAPI :: Proxy PersonAPI
597+> personAPI = Proxy
598+>
599+> server4 :: Server PersonAPI
600+> server4 = return persons
601+>
602+> app2 :: Application
603+> app2 = serve personAPI server4
604+
605+And we're good to go. You can run this example with `dist/build/tutorial/tutorial 4`.
606+
607+``` bash
608+ $ curl http://localhost:8081/persons
609+ [{"lastName":"Newton","firstName":"Isaac"},{"lastName":"Einstein","firstName":"Albert"}]
610+ $ curl -H 'Accept: text/html' http://localhost:8081/persons
611+ <table><tr><td>first name</td><td>last name</td></tr><tr><td>Isaac</td><td>Newton</td></tr><tr><td>Albert</td><td>Einstein</td></tr></table>
612+ # or just point your browser to http://localhost:8081/persons
613+```
614+
615+The `EitherT ServantErr IO` monad
616+=================================
617+
618+At the heart of the handlers is the monad they run in, namely `EitherT
619+ServantErr IO`. One might wonder: why this monad? The answer is that it is the
620+simplest monad with the following properties:
621+
622+- it lets us both return a successful result (with the `Right` branch of
623+`Either`) or "fail" with a descriptive error (with the `Left` branch of
624+`Either`);
625+- it lets us perform IO, which is absolutely vital since most webservices exist
626+as interfaces to databases that we interact with in `IO`;
627+
628+Let's recall some definitions.
629+
630+``` haskell
631+-- from the Prelude
632+data Either e a = Left e | Right a
633+
634+-- from the 'either' package at
635+-- http://hackage.haskell.org/package/either-4.3.3.2/docs/Control-Monad-Trans-Either.html
636+newtype EitherT e m a
637+ = EitherT { runEitherT :: m (Either e a) }
638+```
639+
640+In short, this means that a handler of type `EitherT ServantErr IO a` is simply
641+equivalent to a computation of type `IO (Either ServantErr a)`, that is, an IO
642+action that either returns an error or a result.
643+
644+The aforementioned `either` package is worth taking a look at. Perhaps most
645+importantly:
646+
647+``` haskell
648+left :: Monad m => e -> EitherT e m a
649+```
650+Allows you to return an error from your handler (whereas `return` is enough to
651+return a success).
652+
653+Most of what you'll be doing in your handlers is running some IO and,
654+depending on the result, you might sometimes want to throw an error of some
655+kind and abort early. The next two sections cover how to do just that.
656+
657+Performing IO
658+-------------
659+
660+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:
661+
662+``` haskell
663+class Monad m => MonadIO m where
664+ liftIO :: IO a -> m a
665+```
666+
667+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`:
668+
669+> type IOAPI1 = "myfile.txt" :> Get '[JSON] FileContent
670+>
671+> newtype FileContent = FileContent
672+> { content :: String }
673+> deriving Generic
674+>
675+> instance ToJSON FileContent
676+>
677+> server5 :: Server IOAPI1
678+> server5 = do
679+> filecontent <- liftIO (readFile "myfile.txt")
680+> return (FileContent filecontent)
681+
682+Failing, through `ServantErr`
683+-----------------------------
684+
685+If you want to explicitly fail at providing the result promised by an endpoint
686+using the appropriate HTTP status code (not found, unauthorized, etc) and some
687+error message, all you have to do is use the `left` function mentioned above
688+and provide it with the appropriate value of type `ServantErr`, which is
689+defined as:
690+
691+``` haskell
692+data ServantErr = ServantErr
693+ { errHTTPCode :: Int
694+ , errReasonPhrase :: String
695+ , errBody :: ByteString -- lazy bytestring
696+ , errHeaders :: [Header]
697+ }
698+```
699+
700+Many standard values are provided out of the box by the `Servant.Server`
701+module. If you want to use these values but add a body or some headers, just
702+use record update syntax:
703+
704+> failingHandler :: EitherT ServantErr IO ()
705+> failingHandler = left myerr
706+>
707+> where myerr :: ServantErr
708+> myerr = err503 { errBody = "Sorry dear user." }
709+
710+Here's an example where we return a customised 404-Not-Found error message in
711+the response body if "myfile.txt" isn't there:
712+
713+> server6 :: Server IOAPI1
714+> server6 = do
715+> exists <- liftIO (doesFileExist "myfile.txt")
716+> if exists
717+> then liftIO (readFile "myfile.txt") >>= return . FileContent
718+> else left custom404Err
719+>
720+> where custom404Err = err404 { errBody = "myfile.txt just isn't there, please leave this server alone." }
721+
722+Let's run this server (`dist/build/tutorial/tutorial 5`) and
723+query it, first without the file and then with the file.
724+
725+``` bash
726+ $ curl --verbose http://localhost:8081/myfile.txt
727+ [snip]
728+ * Connected to localhost (127.0.0.1) port 8081 (#0)
729+ > GET /myfile.txt HTTP/1.1
730+ > User-Agent: curl/7.30.0
731+ > Host: localhost:8081
732+ > Accept: */*
733+ >
734+ < HTTP/1.1 404 Not Found
735+ [snip]
736+ myfile.txt just isnt there, please leave this server alone.
737+
738+ $ echo Hello > myfile.txt
739+
740+ $ curl --verbose http://localhost:8081/myfile.txt
741+ [snip]
742+ * Connected to localhost (127.0.0.1) port 8081 (#0)
743+ > GET /myfile.txt HTTP/1.1
744+ > User-Agent: curl/7.30.0
745+ > Host: localhost:8081
746+ > Accept: */*
747+ >
748+ < HTTP/1.1 200 OK
749+ [snip]
750+ < Content-Type: application/json
751+ [snip]
752+ {"content":"Hello\n"}
753+```
754+
755+Response headers
756+================
757+
758+To add headers to your response, use [addHeader](http://hackage.haskell.org/package/servant-0.4.4/docs/Servant-API-ResponseHeaders.html).
759+Note that this changes the type of your API, as we can see in the following example:
760+
761+> type MyHandler = Get '[JSON] (Headers '[Header "X-An-Int" Int] User)
762+>
763+> myHandler :: Server MyHandler
764+> myHandler = return $ addHeader 1797 albert
765+
766+
767+Serving static files
768+====================
769+
770+*servant-server* also provides a way to just serve the content of a directory
771+under some path in your web API. As mentioned earlier in this document, the
772+`Raw` combinator can be used in your APIs to mean "plug here any WAI
773+application". Well, servant-server provides a function to get a file and
774+directory serving WAI application, namely:
775+
776+``` haskell
777+-- exported by Servant and Servant.Server
778+serveDirectory :: FilePath -> Server Raw
779+```
780+
781+`serveDirectory`'s argument must be a path to a valid directory. You can see an
782+example below, runnable with `dist/build/tutorial/tutorial 6`
783+(you **must** run it from within the *servant-examples/* directory!), which is
784+a webserver that serves the various bits of code covered in this
785+getting-started.
786+
787+The API type will be the following.
788+
789+> type CodeAPI = "code" :> Raw
790+
791+And the server:
792+
793+> codeAPI :: Proxy CodeAPI
794+> codeAPI = Proxy
795+
796+> server7 :: Server CodeAPI
797+> server7 = serveDirectory "tutorial"
798+>
799+> app3 :: Application
800+> app3 = serve codeAPI server7
801+
802+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.
803+
804+In other words:
805+
806+- If a client requests `/code/foo.txt`, the server will look for a file at `./tutorial/foo.txt` (and fail)
807+- If a client requests `/code/T1.hs`, the server will look for a file at `./tutorial/T1.hs` (and succeed)
808+- 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)
809+
810+Here is our little server in action.
811+
812+``` haskell
813+$ curl http://localhost:8081/code/T1.hs
814+{-# LANGUAGE DataKinds #-}
815+{-# LANGUAGE TypeFamilies #-}
816+{-# LANGUAGE DeriveGeneric #-}
817+{-# LANGUAGE TypeOperators #-}
818+module T1 where
819+
820+import Data.Aeson
821+import Data.Time.Calendar
822+import GHC.Generics
823+import Network.Wai
824+import Servant
825+
826+data User = User
827+ { name :: String
828+ , age :: Int
829+ , email :: String
830+ , registration_date :: Day
831+ } deriving (Eq, Show, Generic)
832+
833+-- orphan ToJSON instance for Day. necessary to derive one for User
834+instance ToJSON Day where
835+ -- display a day in YYYY-mm-dd format
836+ toJSON d = toJSON (showGregorian d)
837+
838+instance ToJSON User
839+
840+type UserAPI = "users" :> Get '[JSON] [User]
841+
842+users :: [User]
843+users =
844+ [ User "Isaac Newton" 372 "isaac@newton.co.uk" (fromGregorian 1683 3 1)
845+ , User "Albert Einstein" 136 "ae@mc2.org" (fromGregorian 1905 12 1)
846+ ]
847+
848+userAPI :: Proxy UserAPI
849+userAPI = Proxy
850+
851+server :: Server UserAPI
852+server = return users
853+
854+app :: Application
855+app = serve userAPI server
856+$ curl http://localhost:8081/code/tutorial.hs
857+import Network.Wai
858+import Network.Wai.Handler.Warp
859+import System.Environment
860+
861+import qualified T1
862+import qualified T2
863+import qualified T3
864+import qualified T4
865+import qualified T5
866+import qualified T6
867+import qualified T7
868+import qualified T9
869+import qualified T10
870+
871+app :: String -> (Application -> IO ()) -> IO ()
872+app n f = case n of
873+ "1" -> f T1.app
874+ "2" -> f T2.app
875+ "3" -> f T3.app
876+ "4" -> f T4.app
877+ "5" -> f T5.app
878+ "6" -> f T6.app
879+ "7" -> f T7.app
880+ "8" -> f T3.app
881+ "9" -> T9.writeJSFiles >> f T9.app
882+ "10" -> f T10.app
883+ _ -> usage
884+
885+main :: IO ()
886+main = do
887+ args <- getArgs
888+ case args of
889+ [n] -> app n (run 8081)
890+ _ -> usage
891+
892+usage :: IO ()
893+usage = do
894+ putStrLn "Usage:\t tutorial N"
895+ putStrLn "\t\twhere N is the number of the example you want to run."
896+
897+$ curl http://localhost:8081/foo
898+not found
899+```
900+
901+Nested APIs
902+===========
903+
904+Let's see how you can define APIs in a modular way, while avoiding repetition. Consider this simple example:
905+
906+> type UserAPI3 = -- view the user with given userid, in JSON
907+> Capture "userid" Int :> Get '[JSON] User
908+>
909+> :<|> -- delete the user with given userid. empty response
910+> Capture "userid" Int :> Delete '[] ()
911+
912+We can instead factor out the `userid`:
913+
914+> type UserAPI4 = Capture "userid" Int :>
915+> ( Get '[JSON] User
916+> :<|> Delete '[] ()
917+> )
918+
919+However, you have to be aware that this has an effect on the type of the corresponding `Server`:
920+
921+``` haskell
922+Server UserAPI3 = (Int -> EitherT ServantErr IO User)
923+ :<|> (Int -> EitherT ServantErr IO ())
924+
925+Server UserAPI4 = Int -> ( EitherT ServantErr IO User
926+ :<|> EitherT ServantErr IO ()
927+ )
928+```
929+
930+In the first case, each handler receives the *userid* argument. In the latter,
931+the whole `Server` takes the *userid* and has handlers that are just computations in `EitherT`, with no arguments. In other words:
932+
933+> server8 :: Server UserAPI3
934+> server8 = getUser :<|> deleteUser
935+>
936+> where getUser :: Int -> EitherT ServantErr IO User
937+> getUser _userid = error "..."
938+>
939+> deleteUser :: Int -> EitherT ServantErr IO ()
940+> deleteUser _userid = error "..."
941+>
942+> -- notice how getUser and deleteUser
943+> -- have a different type! no argument anymore,
944+> -- the argument directly goes to the whole Server
945+> server9 :: Server UserAPI4
946+> server9 userid = getUser userid :<|> deleteUser userid
947+>
948+> where getUser :: Int -> EitherT ServantErr IO User
949+> getUser = error "..."
950+>
951+> deleteUser :: Int -> EitherT ServantErr IO ()
952+> deleteUser = error "..."
953+
954+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`.
955+
956+> -- we just factor out the "users" path fragment
957+> type API1 = "users" :>
958+> ( Get '[JSON] [User] -- user listing
959+> :<|> Capture "userid" Int :> Get '[JSON] User -- view a particular user
960+> )
961+>
962+> -- we factor out the Request Body
963+> type API2 = ReqBody '[JSON] User :>
964+> ( Get '[JSON] User -- just display the same user back, don't register it
965+> :<|> Post '[JSON] () -- register the user. empty response
966+> )
967+>
968+> -- we factor out a Header
969+> type API3 = Header "Authorization" Token :>
970+> ( Get '[JSON] SecretData -- get some secret data, if authorized
971+> :<|> ReqBody '[JSON] SecretData :> Post '[] () -- add some secret data, if authorized
972+> )
973+>
974+> newtype Token = Token ByteString
975+> newtype SecretData = SecretData ByteString
976+
977+This approach lets you define APIs modularly and assemble them all into one big API type only at the end.
978+
979+> type UsersAPI =
980+> Get '[JSON] [User] -- list users
981+> :<|> ReqBody '[JSON] User :> Post '[] () -- add a user
982+> :<|> Capture "userid" Int :>
983+> ( Get '[JSON] User -- view a user
984+> :<|> ReqBody '[JSON] User :> Put '[] () -- update a user
985+> :<|> Delete '[] () -- delete a user
986+> )
987+>
988+> usersServer :: Server UsersAPI
989+> usersServer = getUsers :<|> newUser :<|> userOperations
990+>
991+> where getUsers :: EitherT ServantErr IO [User]
992+> getUsers = error "..."
993+>
994+> newUser :: User -> EitherT ServantErr IO ()
995+> newUser = error "..."
996+>
997+> userOperations userid =
998+> viewUser userid :<|> updateUser userid :<|> deleteUser userid
999+>
1000+> where
1001+> viewUser :: Int -> EitherT ServantErr IO User
1002+> viewUser = error "..."
1003+>
1004+> updateUser :: Int -> User -> EitherT ServantErr IO ()
1005+> updateUser = error "..."
1006+>
1007+> deleteUser :: Int -> EitherT ServantErr IO ()
1008+> deleteUser = error "..."
1009+
1010+> type ProductsAPI =
1011+> Get '[JSON] [Product] -- list products
1012+> :<|> ReqBody '[JSON] Product :> Post '[] () -- add a product
1013+> :<|> Capture "productid" Int :>
1014+> ( Get '[JSON] Product -- view a product
1015+> :<|> ReqBody '[JSON] Product :> Put '[] () -- update a product
1016+> :<|> Delete '[] () -- delete a product
1017+> )
1018+>
1019+> data Product = Product { productId :: Int }
1020+>
1021+> productsServer :: Server ProductsAPI
1022+> productsServer = getProducts :<|> newProduct :<|> productOperations
1023+>
1024+> where getProducts :: EitherT ServantErr IO [Product]
1025+> getProducts = error "..."
1026+>
1027+> newProduct :: Product -> EitherT ServantErr IO ()
1028+> newProduct = error "..."
1029+>
1030+> productOperations productid =
1031+> viewProduct productid :<|> updateProduct productid :<|> deleteProduct productid
1032+>
1033+> where
1034+> viewProduct :: Int -> EitherT ServantErr IO Product
1035+> viewProduct = error "..."
1036+>
1037+> updateProduct :: Int -> Product -> EitherT ServantErr IO ()
1038+> updateProduct = error "..."
1039+>
1040+> deleteProduct :: Int -> EitherT ServantErr IO ()
1041+> deleteProduct = error "..."
1042+
1043+> type CombinedAPI = "users" :> UsersAPI
1044+> :<|> "products" :> ProductsAPI
1045+>
1046+> server10 :: Server CombinedAPI
1047+> server10 = usersServer :<|> productsServer
1048+
1049+Finally, we can realize the user and product APIs are quite similar and abstract that away:
1050+
1051+> -- API for values of type 'a'
1052+> -- indexed by values of type 'i'
1053+> type APIFor a i =
1054+> Get '[JSON] [a] -- list 'a's
1055+> :<|> ReqBody '[JSON] a :> Post '[] () -- add an 'a'
1056+> :<|> Capture "id" i :>
1057+> ( Get '[JSON] a -- view an 'a' given its "identifier" of type 'i'
1058+> :<|> ReqBody '[JSON] a :> Put '[] () -- update an 'a'
1059+> :<|> Delete '[] () -- delete an 'a'
1060+> )
1061+>
1062+> -- Build the appropriate 'Server'
1063+> -- given the handlers of the right type.
1064+> serverFor :: EitherT ServantErr IO [a] -- handler for listing of 'a's
1065+> -> (a -> EitherT ServantErr IO ()) -- handler for adding an 'a'
1066+> -> (i -> EitherT ServantErr IO a) -- handler for viewing an 'a' given its identifier of type 'i'
1067+> -> (i -> a -> EitherT ServantErr IO ()) -- updating an 'a' with given id
1068+> -> (i -> EitherT ServantErr IO ()) -- deleting an 'a' given its id
1069+> -> Server (APIFor a i)
1070+> serverFor = error "..."
1071+> -- implementation left as an exercise. contact us on IRC
1072+> -- or the mailing list if you get stuck!
1073+
1074+Using another monad for your handlers
1075+=====================================
1076+
1077+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.
1078+
1079+``` haskell
1080+type Server api = ServerT api (EitherT ServantErr IO)
1081+```
1082+
1083+`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`.
1084+
1085+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?
1086+
1087+Natural transformations
1088+-----------------------
1089+
1090+If we have a function that gets us from an `m a` to an `n a`, for any `a`, what
1091+do we have?
1092+
1093+``` haskell
1094+newtype m :~> n = Nat { unNat :: forall a. m a -> n a}
1095+
1096+-- For example
1097+-- listToMaybeNat ::`[] :~> Maybe`
1098+-- listToMaybeNat = Nat listToMaybe -- from Data.Maybe
1099+```
1100+(`Nat` comes from "natural transformation", in case you're wondering.)
1101+
1102+So if you want to write handlers using another monad/type than `EitherT
1103+ServantErr IO`, say the `Reader String` monad, the first thing you have to
1104+prepare is a function:
1105+
1106+``` haskell
1107+readerToEither :: Reader String :~> EitherT ServantErr IO
1108+```
1109+
1110+Let's start with `readerToEither'`. We obviously have to run the `Reader`
1111+computation by supplying it with a `String`, like `"hi"`. We get an `a` out
1112+from that and can then just `return` it into `EitherT`. We can then just wrap
1113+that function with the `Nat` constructor to make it have the fancier type.
1114+
1115+> readerToEither' :: forall a. Reader String a -> EitherT ServantErr IO a
1116+> readerToEither' r = return (runReader r "hi")
1117+>
1118+> readerToEither :: Reader String :~> EitherT ServantErr IO
1119+> readerToEither = Nat readerToEither'
1120+
1121+We can write some simple webservice with the handlers running in `Reader String`.
1122+
1123+> type ReaderAPI = "a" :> Get '[JSON] Int
1124+> :<|> "b" :> Get '[JSON] String
1125+>
1126+> readerAPI :: Proxy ReaderAPI
1127+> readerAPI = Proxy
1128+>
1129+> readerServerT :: ServerT ReaderAPI (Reader String)
1130+> readerServerT = a :<|> b
1131+>
1132+> where a :: Reader String Int
1133+> a = return 1797
1134+>
1135+> b :: Reader String String
1136+> b = ask
1137+
1138+We unfortunately can't use `readerServerT` as an argument of `serve`, because
1139+`serve` wants a `Server ReaderAPI`, i.e., with handlers running in `EitherT
1140+ServantErr IO`. But there's a simple solution to this.
1141+
1142+Enter `enter`
1143+-------------
1144+
1145+That's right. We have just written `readerToEither`, which is exactly what we
1146+would need to apply to the results of all handlers to make the handlers have the
1147+right type for `serve`. Being cumbersome to do by hand, we provide a function
1148+`enter` which takes a natural transformation between two parametrized types `m`
1149+and `n` and a `ServerT someapi m`, and returns a `ServerT someapi n`.
1150+
1151+In our case, we can wrap up our little webservice by using `enter readerToEither` on our handlers.
1152+
1153+> readerServer :: Server ReaderAPI
1154+> readerServer = enter readerToEither readerServerT
1155+>
1156+> app4 :: Application
1157+> app4 = serve readerAPI readerServer
1158+
1159+And we can indeed see this webservice in action by running `dist/build/tutorial/tutorial 7`.
1160+
1161+``` bash
1162+$ curl http://localhost:8081/a
1163+1797
1164+$ curl http://localhost:8081/b
1165+"hi"
1166+```
1167+
1168+Conclusion
1169+==========
1170+
1171+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*.
1172+
1173+<div style="text-align: center;">
1174+ <p><a href="/tutorial/api-type.html">Previous page: A web API as a type</a></p>
1175+ <p><a href="/tutorial/client.html">Next page: Deriving Haskell functions to query an API</a></p>
1176+</div>