Fix cabal file, stack.yaml, and sources.txt
This commit is contained in:
parent
45d034f137
commit
b1791022dc
8 changed files with 41 additions and 45 deletions
|
@ -1,7 +1,4 @@
|
||||||
---
|
# A web API as a type
|
||||||
title: A web API as a type
|
|
||||||
toc: true
|
|
||||||
---
|
|
||||||
|
|
||||||
The source for this tutorial section is a literate haskell file, so first we
|
The source for this tutorial section is a literate haskell file, so first we
|
||||||
need to have some language extensions and imports:
|
need to have some language extensions and imports:
|
||||||
|
@ -25,8 +22,7 @@ Consider the following informal specification of an API:
|
||||||
|
|
||||||
You *should* be able to formalize that. And then use the formalized version to
|
You *should* be able to formalize that. And then use the formalized version to
|
||||||
get you much of the way towards writing a web app. And all the way towards
|
get you much of the way towards writing a web app. And all the way towards
|
||||||
getting some client libraries, and documentation (and in the future, who knows
|
getting some client libraries, and documentation, and more.
|
||||||
- tests, HATEOAS, ...).
|
|
||||||
|
|
||||||
How would we describe it with servant? As mentioned earlier, an endpoint
|
How would we describe it with servant? As mentioned earlier, an endpoint
|
||||||
description is a good old Haskell **type**:
|
description is a good old Haskell **type**:
|
||||||
|
@ -45,8 +41,8 @@ data User = User {
|
||||||
Let's break that down:
|
Let's break that down:
|
||||||
|
|
||||||
- `"users"` says that our endpoint will be accessible under `/users`;
|
- `"users"` says that our endpoint will be accessible under `/users`;
|
||||||
- `QueryParam "sortby" SortBy`, where `SortBy` is defined by `data SortBy = Age
|
- `QueryParam "sortby" SortBy`, where `SortBy` is defined by `data SortBy = Age | Name`,
|
||||||
| Name`, says that the endpoint has a query string parameter named `sortby`
|
says that the endpoint has a query string parameter named `sortby`
|
||||||
whose value will be extracted as a value of type `SortBy`.
|
whose value will be extracted as a value of type `SortBy`.
|
||||||
- `Get '[JSON] [User]` says that the endpoint will be accessible through HTTP
|
- `Get '[JSON] [User]` says that the endpoint will be accessible through HTTP
|
||||||
GET requests, returning a list of users encoded as JSON. You will see
|
GET requests, returning a list of users encoded as JSON. You will see
|
||||||
|
@ -54,7 +50,7 @@ later how you can make use of this to make your data available under different
|
||||||
formats, the choice being made depending on the [Accept
|
formats, the choice being made depending on the [Accept
|
||||||
header](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html) specified in
|
header](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html) specified in
|
||||||
the client's request.
|
the client's request.
|
||||||
- the `:>` operator that separates the various "combinators" just lets you
|
- The `:>` operator that separates the various "combinators" just lets you
|
||||||
sequence static path fragments, URL captures and other combinators. The
|
sequence static path fragments, URL captures and other combinators. The
|
||||||
ordering only matters for static path fragments and URL captures. `"users" :>
|
ordering only matters for static path fragments and URL captures. `"users" :>
|
||||||
"list-all" :> Get '[JSON] [User]`, equivalent to `/users/list-all`, is
|
"list-all" :> Get '[JSON] [User]`, equivalent to `/users/list-all`, is
|
||||||
|
@ -74,11 +70,10 @@ type UserAPI2 = "users" :> "list-all" :> Get '[JSON] [User]
|
||||||
always write your own when you need it. Here's a quick overview of all the
|
always write your own when you need it. Here's a quick overview of all the
|
||||||
combinators that servant comes with.
|
combinators that servant comes with.
|
||||||
|
|
||||||
Combinators
|
## Combinators
|
||||||
===========
|
|
||||||
|
### Static strings
|
||||||
|
|
||||||
Static strings
|
|
||||||
--------------
|
|
||||||
|
|
||||||
As you've already seen, you can use type-level strings (enabled with the
|
As you've already seen, you can use type-level strings (enabled with the
|
||||||
`DataKinds` language extension) for static path fragments. Chaining
|
`DataKinds` language extension) for static path fragments. Chaining
|
||||||
|
@ -90,8 +85,8 @@ type UserAPI3 = "users" :> "list-all" :> "now" :> Get '[JSON] [User]
|
||||||
-- /users/list-all/now
|
-- /users/list-all/now
|
||||||
```
|
```
|
||||||
|
|
||||||
`Delete`, `Get`, `Patch`, `Post` and `Put`
|
### `Delete`, `Get`, `Patch`, `Post` and `Put`
|
||||||
------------------------------------------
|
|
||||||
|
|
||||||
These 5 combinators are very similar except that they each describe a
|
These 5 combinators are very similar except that they each describe a
|
||||||
different HTTP method. This is how they're declared
|
different HTTP method. This is how they're declared
|
||||||
|
@ -112,8 +107,8 @@ type UserAPI4 = "users" :> Get '[JSON] [User]
|
||||||
:<|> "admins" :> Get '[JSON] [User]
|
:<|> "admins" :> Get '[JSON] [User]
|
||||||
```
|
```
|
||||||
|
|
||||||
`Capture`
|
### `Capture`
|
||||||
---------
|
|
||||||
|
|
||||||
URL captures are parts of the URL that are variable and whose actual value is
|
URL captures are parts of the URL that are variable and whose actual value is
|
||||||
captured and passed to the request handlers. In many web frameworks, you'll see
|
captured 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
|
||||||
-- equivalent to 'DELETE /user/:userid'
|
-- equivalent to 'DELETE /user/:userid'
|
||||||
```
|
```
|
||||||
|
|
||||||
`QueryParam`, `QueryParams`, `QueryFlag`, `MatrixParam`, `MatrixParams` and `MatrixFlag`
|
### `QueryParam`, `QueryParams`, `QueryFlag`, `MatrixParam`, `MatrixParams` and `MatrixFlag`
|
||||||
----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
`QueryParam`, `QueryParams` and `QueryFlag` are about query string
|
`QueryParam`, `QueryParams` and `QueryFlag` are about query string
|
||||||
parameters, i.e., those parameters that come after the question mark
|
parameters, i.e., those parameters that come after the question mark
|
||||||
|
@ -202,8 +196,7 @@ type UserAPI6 = "users" :> QueryParam "sortby" SortBy :> Get '[JSON] [User]
|
||||||
Again, your handlers don't have to deserialize these things (into, for example,
|
Again, your handlers don't have to deserialize these things (into, for example,
|
||||||
a `SortBy`). *servant* takes care of it.
|
a `SortBy`). *servant* takes care of it.
|
||||||
|
|
||||||
`ReqBody`
|
### `ReqBody`
|
||||||
---------
|
|
||||||
|
|
||||||
Each HTTP request can carry some additional data that the server can use in its
|
Each HTTP request can carry some additional data that the server can use in its
|
||||||
*body*, and this data can be encoded in any format -- as long as the server
|
*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
|
||||||
-- - returns a User encoded in JSON
|
-- - returns a User encoded in JSON
|
||||||
```
|
```
|
||||||
|
|
||||||
Request `Header`s
|
### Request `Header`s
|
||||||
-----------------
|
|
||||||
|
|
||||||
Request headers are used for various purposes, from caching to carrying
|
Request headers are used for various purposes, from caching to carrying
|
||||||
auth-related data. They consist of a header name and an associated value. An
|
auth-related data. They consist of a header name and an associated value. An
|
||||||
|
@ -263,8 +256,7 @@ the client to send the request.
|
||||||
type UserAPI8 = "users" :> Header "User-Agent" Text :> Get '[JSON] [User]
|
type UserAPI8 = "users" :> Header "User-Agent" Text :> Get '[JSON] [User]
|
||||||
```
|
```
|
||||||
|
|
||||||
Content types
|
### Content types
|
||||||
-------------
|
|
||||||
|
|
||||||
So far, whenever we have used a combinator that carries a list of content
|
So far, whenever we have used a combinator that carries a list of content
|
||||||
types, we've always specified `'[JSON]`. However, *servant* lets you use several
|
types, 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
|
||||||
We will further explain how these content types and your data types can play
|
We will further explain how these content types and your data types can play
|
||||||
together in the [section about serving an API](/tutorial/server.html).
|
together in the [section about serving an API](/tutorial/server.html).
|
||||||
|
|
||||||
Response `Headers`
|
### Response `Headers`
|
||||||
------------------
|
|
||||||
|
|
||||||
Just like an HTTP request, the response generated by a webserver can carry
|
Just like an HTTP request, the response generated by a webserver can carry
|
||||||
headers too. *servant* provides a `Headers` combinator that carries a list of
|
headers too. *servant* provides a `Headers` combinator that carries a list of
|
||||||
|
@ -305,8 +296,7 @@ response, you could write it as below:
|
||||||
type UserAPI10 = "users" :> Get '[JSON] (Headers '[Header "User-Count" Integer] [User])
|
type UserAPI10 = "users" :> Get '[JSON] (Headers '[Header "User-Count" Integer] [User])
|
||||||
```
|
```
|
||||||
|
|
||||||
Interoperability with other WAI `Application`s: `Raw`
|
### Interoperability with other WAI `Application`s: `Raw`
|
||||||
-----------------------------------------------------
|
|
||||||
|
|
||||||
Finally, we also include a combinator named `Raw` that can be used for two reasons:
|
Finally, we also include a combinator named `Raw` that can be used for two reasons:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
name: tutorial
|
name: tutorial
|
||||||
version: 0.1.0.0
|
version: 0.5
|
||||||
synopsis: The servant tutorial
|
synopsis: The servant tutorial
|
||||||
-- description:
|
-- description:
|
||||||
homepage: http://haskell-servant.github.io/
|
homepage: http://haskell-servant.github.io/
|
||||||
|
@ -14,9 +14,16 @@ build-type: Simple
|
||||||
cabal-version: >=1.10
|
cabal-version: >=1.10
|
||||||
|
|
||||||
library
|
library
|
||||||
exposed-modules: api-type.lhs
|
exposed-modules: ApiType
|
||||||
|
, Client
|
||||||
|
, Docs
|
||||||
|
, Javascript
|
||||||
|
, Server
|
||||||
-- other-modules:
|
-- other-modules:
|
||||||
-- other-extensions:
|
-- other-extensions:
|
||||||
build-depends: base >=4.8 && <4.9
|
build-depends: base >=4.8 && <4.9
|
||||||
|
, text
|
||||||
|
, servant
|
||||||
-- hs-source-dirs:
|
-- hs-source-dirs:
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
ghc-options: -Wall -Werror -c -pgmL markdown-unlit
|
||||||
|
|
|
@ -5,7 +5,6 @@ servant-docs
|
||||||
servant-foreign
|
servant-foreign
|
||||||
servant-js
|
servant-js
|
||||||
servant-server
|
servant-server
|
||||||
servant-examples
|
|
||||||
servant-blaze
|
servant-blaze
|
||||||
servant-lucid
|
servant-lucid
|
||||||
servant-mock
|
servant-mock
|
||||||
|
|
|
@ -7,12 +7,12 @@ packages:
|
||||||
- servant-cassava/
|
- servant-cassava/
|
||||||
- servant-client/
|
- servant-client/
|
||||||
- servant-docs/
|
- servant-docs/
|
||||||
- servant-examples/
|
|
||||||
- servant-foreign/
|
- servant-foreign/
|
||||||
- servant-js/
|
- servant-js/
|
||||||
- servant-lucid/
|
- servant-lucid/
|
||||||
- servant-mock/
|
- servant-mock/
|
||||||
- servant-server/
|
- servant-server/
|
||||||
|
- doc/tutorial
|
||||||
extra-deps:
|
extra-deps:
|
||||||
- engine-io-wai-1.0.2
|
- engine-io-wai-1.0.2
|
||||||
- control-monad-omega-0.3.1
|
- control-monad-omega-0.3.1
|
||||||
|
|
Loading…
Reference in a new issue