@@ -24,8 +24,8 @@ You *should* be able to formalize that. And then use the formalized version to
2424get you much of the way towards writing a web app. And all the way towards
2525getting some client libraries, and documentation, and more.
2626
27−How would we describe it with servant? As mentioned earlier, an endpoint
28−description is a good old Haskell **type**:
27+How would we describe it with **servant**? An endpoint description is a good old
28+Haskell **type**:
2929
3030``` haskell
3131type UserAPI = "users" :> QueryParam "sortby" SortBy :> Get '[JSON] [User]
@@ -66,15 +66,14 @@ type UserAPI2 = "users" :> "list-all" :> Get '[JSON] [User]
6666 :<|> "list-all" :> "users" :> Get '[JSON] [User]
6767```
6868
69−*servant* provides a fair amount of combinators out-of-the-box, but you can
70−always write your own when you need it. Here's a quick overview of all the
71−combinators that servant comes with.
69+**servant** provides a fair amount of combinators out-of-the-box, but you can
70+always write your own when you need it. Here's a quick overview of the most
71+often needed the combinators that **servant** comes with.
7272
7373## Combinators
7474
7575### Static strings
7676
77−
7877As you've already seen, you can use type-level strings (enabled with the
7978`DataKinds` language extension) for static path fragments. Chaining
8079them amounts to `/`-separating them in a URL.
@@ -87,7 +86,6 @@ type UserAPI3 = "users" :> "list-all" :> "now" :> Get '[JSON] [User]
8786
8887### `Delete`, `Get`, `Patch`, `Post` and `Put`
8988
90−
9189The `Get` combinator is defined in terms of the more general `Verb`:
9290``` haskell ignore
9391data Verb method (statusCode :: Nat) (contentType :: [*]) a
@@ -120,15 +118,14 @@ type UserAPI4 = "users" :> Get '[JSON] [User]
120118
121119### `Capture`
122120
123−
124−URL captures are parts of the URL that are variable and whose actual value is
121+URL captures are segments of the path of a URL that are variable and whose actual value is
125122captured and passed to the request handlers. In many web frameworks, you'll see
126123it written as in `/users/:userid`, with that leading `:` denoting that `userid`
127124is just some kind of variable name or placeholder. For instance, if `userid` is
128125supposed to range over all integers greater or equal to 1, our endpoint will
129126match requests made to `/users/1`, `/users/143` and so on.
130127
131−The `Capture` combinator in servant takes a (type-level) string representing
128+The `Capture` combinator in **servant** takes a (type-level) string representing
132129the "name of the variable" and a type, which indicates the type we want to
133130decode the "captured value" to.
134131
@@ -155,17 +152,16 @@ type UserAPI5 = "user" :> Capture "userid" Integer :> Get '[JSON] User
155152
156153In the second case, `DeleteNoContent` specifies a 204 response code,
157154`JSON` specifies the content types on which the handler will match,
158−and `NoContent` is a Haskell type isomorphic to `()` used to represent
159−a trivial piece of information.
155+and `NoContent` says that the response will always be empty.
160156
161157### `QueryParam`, `QueryParams`, `QueryFlag`
162158
163−`QueryParam`, `QueryParams` and `QueryFlag` are about query string
164−parameters, i.e., those parameters that come after the question mark
159+`QueryParam`, `QueryParams` and `QueryFlag` are about parameters in the query string,
160+i.e., those parameters that come after the question mark
165161(`?`) in URLs, like `sortby` in `/users?sortby=age`, whose value is
166162set to `age`. `QueryParams` lets you specify that the query parameter
167163is actually a list of values, which can be specified using
168−`?param[]=value1¶m[]=value2`. This represents a list of values
164+`?param=value1¶m=value2`. This represents a list of values
169165composed of `value1` and `value2`. `QueryFlag` lets you specify a
170166boolean-like query parameter where a client isn't forced to specify a
171167value. The absence or presence of the parameter's name in the query
@@ -190,7 +186,7 @@ type UserAPI6 = "users" :> QueryParam "sortby" SortBy :> Get '[JSON] [User]
190186```
191187
192188Again, your handlers don't have to deserialize these things (into, for example,
193−a `SortBy`). *servant* takes care of it.
189+a `SortBy`). **servant** takes care of it.
194190
195191### `ReqBody`
196192
@@ -201,9 +197,9 @@ users: instead of passing each field of the user as a separate query string
201197parameter or something dirty like that, we can group all the data into a JSON
202198object. This has the advantage of supporting nested objects.
203199
204−*servant*'s `ReqBody` combinator takes a list of content types in which the
200+**servant**'s `ReqBody` combinator takes a list of content types in which the
205201data encoded in the request body can be represented and the type of that data.
206−And, as you might have guessed, you don't have to check the content-type
202+And, as you might have guessed, you don't have to check the content type
207203header, and do the deserialization yourself. We do it for you. And return `Bad
208204Request` or `Unsupported Content Type` as appropriate.
209205
@@ -231,12 +227,11 @@ type UserAPI7 = "users" :> ReqBody '[JSON] User :> Post '[JSON] User
231227
232228### Request `Header`s
233229
234−
235230Request headers are used for various purposes, from caching to carrying
236231auth-related data. They consist of a header name and an associated value. An
237232example would be `Accept: application/json`.
238233
239−The `Header` combinator in servant takes a type-level string for the header
234+The `Header` combinator in **servant** takes a type-level string for the header
240235name and the type to which we want to decode the header's value (from some
241236textual representation), as illustrated below:
242237
@@ -255,10 +250,10 @@ type UserAPI8 = "users" :> Header "User-Agent" Text :> Get '[JSON] [User]
255250### Content types
256251
257252So far, whenever we have used a combinator that carries a list of content
258−types, we've always specified `'[JSON]`. However, *servant* lets you use several
253+types, we've always specified `'[JSON]`. However, **servant** lets you use several
259254content types, and also lets you define your own content types.
260255
261−Four content-types are provided out-of-the-box by the core *servant* package:
256+Four content types are provided out-of-the-box by the core **servant** package:
262257`JSON`, `PlainText`, `FormUrlEncoded` and `OctetStream`. If for some obscure
263258reason you wanted one of your endpoints to make your user data available under
264259those 4 formats, you would write the API type as below:
@@ -267,18 +262,18 @@ those 4 formats, you would write the API type as below:
267262type UserAPI9 = "users" :> Get '[JSON, PlainText, FormUrlEncoded, OctetStream] [User]
268263```
269264
270−We also provide an HTML content-type, but since there's no single library
271−that everyone uses, we decided to release 2 packages, *servant-lucid* and
272−*servant-blaze*, to provide HTML encoding of your data.
265+(There are other packages that provide other content types. For example
266+**servant-lucid** and **servant-blaze** allow to generate html pages (using
267+**lucid** and **blaze-html**) and both come with a content type for html.)
273268
274269We will further explain how these content types and your data types can play
275−together in the [section about serving an API](/tutorial/server.html).
270+together in the [section about serving an API](Server.html).
276271
277272### Response `Headers`
278273
279274Just like an HTTP request, the response generated by a webserver can carry
280−headers too. *servant* provides a `Headers` combinator that carries a list of
281−`Header` and can be used by simply wrapping the "return type" of an endpoint
275+headers too. **servant** provides a `Headers` combinator that carries a list of
276+`Header` types and can be used by simply wrapping the "return type" of an endpoint
282277with it.
283278
284279``` haskell ignore
@@ -292,11 +287,12 @@ response, you could write it as below:
292287type UserAPI10 = "users" :> Get '[JSON] (Headers '[Header "User-Count" Integer] [User])
293288```
294289
295−### Interoperability with other WAI `Application`s: `Raw`
296−
297−Finally, we also include a combinator named `Raw` that can be used for two reasons:
290+### Interoperability with `wai`: `Raw`
298291
299−- You want to serve static files from a given directory. In that case you can just say:
292+Finally, we also include a combinator named `Raw` that provides an escape hatch
293+to the underlying low-level web library `wai`. It can be used when
294+you want to plug a [wai `Application`](http://hackage.haskell.org/package/wai)
295+into your webservice:
300296
301297``` haskell
302298type UserAPI11 = "users" :> Get '[JSON] [User]
@@ -309,11 +305,7 @@ type UserAPI11 = "users" :> Get '[JSON] [User]
309305 -- at the right path
310306```
311307
312−- You more generally want to plug a [WAI `Application`](http://hackage.haskell.org/package/wai)
313−into your webservice. Static file serving is a specific example of that. The API type would look the
314−same as above though. (You can even combine *servant* with other web frameworks
315−this way!)
316−
317−<div style="text-align: center;">
318− <a href="/tutorial/server.html">Next page: Serving an API</a>
319−</div>
308+One example for this is if you want to serve a directory of static files along
309+with the rest of your API. But you can plug in everything that is an
310+`Application`, e.g. a whole web application written in any of the web
311+frameworks that support `wai`.