git.iko.soy/typeable/servant
on master help sign in
Fix cabal file, stack.yaml, and sources.txt
commitf601cbf3b12cf4381f0fa0e3e69cff4ec4259444 authorJulian K. Arni <jkarni@gmail.com> dateWed 27 Jan 2016, 22:46 (11 years ago) parenta7c3880
8 files changed+41−45
doc/tutorial/api-type.lhs → doc/tutorial/ApiType.lhs+31−41 doc/tutorial/client.lhs → doc/tutorial/Client.lhs doc/tutorial/docs.lhs → doc/tutorial/Docs.lhs doc/tutorial/javascript.lhs → doc/tutorial/Javascript.lhs doc/tutorial/server.lhs → doc/tutorial/Server.lhs doc/tutorial/tutorial.cabal+9−2 sources.txt−1 stack.yaml+1−1
doc/tutorial/api-type.lhs → doc/tutorial/ApiType.lhsrenamed+31−41
@@ -1,7 +1,4 @@
1−---
2−title: A web API as a type
3−toc: true
4−---
1+# A web API as a type
52
63The source for this tutorial section is a literate haskell file, so first we
74need to have some language extensions and imports:
@@ -25,8 +22,7 @@ Consider the following informal specification of an API:
2522
2623You *should* be able to formalize that. And then use the formalized version to
2724get you much of the way towards writing a web app. And all the way towards
28−getting some client libraries, and documentation (and in the future, who knows
29−- tests, HATEOAS, ...).
25+getting some client libraries, and documentation, and more.
3026
3127How would we describe it with servant? As mentioned earlier, an endpoint
3228description is a good old Haskell **type**:
@@ -45,22 +41,22 @@ data User = User {
4541Let's break that down:
4642
4743- `"users"` says that our endpoint will be accessible under `/users`;
48−- `QueryParam "sortby" SortBy`, where `SortBy` is defined by `data SortBy = Age
49−| Name`, says that the endpoint has a query string parameter named `sortby`
50−whose value will be extracted as a value of type `SortBy`.
44+- `QueryParam "sortby" SortBy`, where `SortBy` is defined by `data SortBy = Age | Name`,
45+ says that the endpoint has a query string parameter named `sortby`
46+ whose value will be extracted as a value of type `SortBy`.
5147- `Get '[JSON] [User]` says that the endpoint will be accessible through HTTP
52−GET requests, returning a list of users encoded as JSON. You will see
53−later how you can make use of this to make your data available under different
54−formats, the choice being made depending on the [Accept
55−header](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html) specified in
56−the client's request.
57−- the `:>` operator that separates the various "combinators" just lets you
58−sequence static path fragments, URL captures and other combinators. The
59−ordering only matters for static path fragments and URL captures. `"users" :>
60−"list-all" :> Get '[JSON] [User]`, equivalent to `/users/list-all`, is
61−obviously not the same as `"list-all" :> "users" :> Get '[JSON] [User]`, which
62−is equivalent to `/list-all/users`. This means that sometimes `:>` is somehow
63−equivalent to `/`, but sometimes it just lets you chain another combinator.
48+ GET requests, returning a list of users encoded as JSON. You will see
49+ later how you can make use of this to make your data available under different
50+ formats, the choice being made depending on the [Accept
51+ header](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html) specified in
52+ the client's request.
53+- The `:>` operator that separates the various "combinators" just lets you
54+ sequence static path fragments, URL captures and other combinators. The
55+ ordering only matters for static path fragments and URL captures. `"users" :>
56+ "list-all" :> Get '[JSON] [User]`, equivalent to `/users/list-all`, is
57+ obviously not the same as `"list-all" :> "users" :> Get '[JSON] [User]`, which
58+ is equivalent to `/list-all/users`. This means that sometimes `:>` is somehow
59+ equivalent to `/`, but sometimes it just lets you chain another combinator.
6460
6561We can also describe APIs with multiple endpoints by using the `:<|>`
6662combinators. Here's an example:
@@ -74,11 +70,10 @@ type UserAPI2 = "users" :> "list-all" :> Get '[JSON] [User]
7470always write your own when you need it. Here's a quick overview of all the
7571combinators that servant comes with.
7672
77−Combinators
78−===========
73+## Combinators
74+
75+### Static strings
7976
80−Static strings
81−--------------
8277
8378As you've already seen, you can use type-level strings (enabled with the
8479`DataKinds` language extension) for static path fragments. Chaining
@@ -90,8 +85,8 @@ type UserAPI3 = "users" :> "list-all" :> "now" :> Get '[JSON] [User]
9085 -- /users/list-all/now
9186```
9287
93−`Delete`, `Get`, `Patch`, `Post` and `Put`
94−------------------------------------------
88+### `Delete`, `Get`, `Patch`, `Post` and `Put`
89+
9590
9691These 5 combinators are very similar except that they each describe a
9792different HTTP method. This is how they're declared
@@ -112,8 +107,8 @@ type UserAPI4 = "users" :> Get '[JSON] [User]
112107 :<|> "admins" :> Get '[JSON] [User]
113108```
114109
115−`Capture`
116−---------
110+### `Capture`
111+
117112
118113URL captures are parts of the URL that are variable and whose actual value is
119114captured and passed to the request handlers. In many web frameworks, you'll see
@@ -147,8 +142,7 @@ type UserAPI5 = "user" :> Capture "userid" Integer :> Get '[JSON] User
147142 -- equivalent to 'DELETE /user/:userid'
148143```
149144
150−`QueryParam`, `QueryParams`, `QueryFlag`, `MatrixParam`, `MatrixParams` and `MatrixFlag`
151−----------------------------------------------------------------------------------------
145+### `QueryParam`, `QueryParams`, `QueryFlag`, `MatrixParam`, `MatrixParams` and `MatrixFlag`
152146
153147`QueryParam`, `QueryParams` and `QueryFlag` are about query string
154148parameters, i.e., those parameters that come after the question mark
@@ -202,8 +196,7 @@ type UserAPI6 = "users" :> QueryParam "sortby" SortBy :> Get '[JSON] [User]
202196Again, your handlers don't have to deserialize these things (into, for example,
203197a `SortBy`). *servant* takes care of it.
204198
205−`ReqBody`
206−---------
199+### `ReqBody`
207200
208201Each HTTP request can carry some additional data that the server can use in its
209202*body*, and this data can be encoded in any format -- as long as the server
@@ -240,8 +233,8 @@ type UserAPI7 = "users" :> ReqBody '[JSON] User :> Post '[JSON] User
240233 -- - returns a User encoded in JSON
241234```
242235
243−Request `Header`s
244−-----------------
236+### Request `Header`s
237+
245238
246239Request headers are used for various purposes, from caching to carrying
247240auth-related data. They consist of a header name and an associated value. An
@@ -263,8 +256,7 @@ the client to send the request.
263256type UserAPI8 = "users" :> Header "User-Agent" Text :> Get '[JSON] [User]
264257```
265258
266−Content types
267−-------------
259+### Content types
268260
269261So far, whenever we have used a combinator that carries a list of content
270262types, we've always specified `'[JSON]`. However, *servant* lets you use several
@@ -286,8 +278,7 @@ that everyone uses, we decided to release 2 packages, *servant-lucid* and
286278We will further explain how these content types and your data types can play
287279together in the [section about serving an API](/tutorial/server.html).
288280
289−Response `Headers`
290−------------------
281+### Response `Headers`
291282
292283Just like an HTTP request, the response generated by a webserver can carry
293284headers too. *servant* provides a `Headers` combinator that carries a list of
@@ -305,8 +296,7 @@ response, you could write it as below:
305296type UserAPI10 = "users" :> Get '[JSON] (Headers '[Header "User-Count" Integer] [User])
306297```
307298
308−Interoperability with other WAI `Application`s: `Raw`
309−-----------------------------------------------------
299+### Interoperability with other WAI `Application`s: `Raw`
310300
311301Finally, we also include a combinator named `Raw` that can be used for two reasons:
312302
doc/tutorial/client.lhs → doc/tutorial/Client.lhsrenamed

The content is the same.

doc/tutorial/docs.lhs → doc/tutorial/Docs.lhsrenamed

The content is the same.

doc/tutorial/javascript.lhs → doc/tutorial/Javascript.lhsrenamed

The content is the same.

doc/tutorial/server.lhs → doc/tutorial/Server.lhsrenamed

The content is the same.

doc/tutorial/tutorial.cabal+9−2
@@ -1,5 +1,5 @@
11name: tutorial
2−version: 0.1.0.0
2+version: 0.5
33synopsis: The servant tutorial
44-- description:
55homepage: http://haskell-servant.github.io/
@@ -14,9 +14,16 @@ build-type: Simple
1414cabal-version: >=1.10
1515
1616library
17− exposed-modules: api-type.lhs
17+ exposed-modules: ApiType
18+ , Client
19+ , Docs
20+ , Javascript
21+ , Server
1822 -- other-modules:
1923 -- other-extensions:
2024 build-depends: base >=4.8 && <4.9
25+ , text
26+ , servant
2127 -- hs-source-dirs:
2228 default-language: Haskell2010
29+ ghc-options: -Wall -Werror -c -pgmL markdown-unlit
sources.txt−1
@@ -5,7 +5,6 @@ servant-docs
55servant-foreign
66servant-js
77servant-server
8−servant-examples
98servant-blaze
109servant-lucid
1110servant-mock
stack.yaml+1−1
@@ -7,12 +7,12 @@ packages:
77- servant-cassava/
88- servant-client/
99- servant-docs/
10−- servant-examples/
1110- servant-foreign/
1211- servant-js/
1312- servant-lucid/
1413- servant-mock/
1514- servant-server/
15+- doc/tutorial
1616extra-deps:
1717- base-compat-0.9.0
1818- engine-io-wai-1.0.2