git.iko.soy/typeable/servant
on master help sign in
tutorial: read through Docs.lhs
8e4ab06Sönke Hahn
doc/tutorial/Docs.lhs+60−60
@@ -26,7 +26,7 @@ import Servant.Server
26```
26```
27
27
28And we'll import some things from one of our earlier modules
28And we'll import some things from one of our earlier modules
29−([Serving an API](/tutorial/server.html)):
29+([Serving an API](Server.html)):
30
30
31``` haskell
31``` haskell
32import Server (Email(..), ClientInfo(..), Position(..), HelloMessage(..),
32import Server (Email(..), ClientInfo(..), Position(..), HelloMessage(..),
@@ -35,7 +35,7 @@ import Server (Email(..), ClientInfo(..), Position(..), HelloMessage(..),
35
35
36Like client function generation, documentation generation amounts to inspecting the API type and extracting all the data we need to then present it in some format to users of your API.
36Like client function generation, documentation generation amounts to inspecting the API type and extracting all the data we need to then present it in some format to users of your API.
37
37
38−This time however, we have to assist *servant*. While it is able to deduce a lot of things about our API, it can't magically come up with descriptions of the various pieces of our APIs that are human-friendly and explain what's going on "at the business-logic level". A good example to study for documentation generation is our webservice with the `/position`, `/hello` and `/marketing` endpoints from earlier:
38+This time however, we have to assist **servant**. While it is able to deduce a lot of things about our API, it can't magically come up with descriptions of the various pieces of our APIs that are human-friendly and explain what's going on "at the business-logic level". A good example to study for documentation generation is our webservice with the `/position`, `/hello` and `/marketing` endpoints from earlier:
39
39
40``` haskell
40``` haskell
41type ExampleAPI = "position" :> Capture "x" Int :> Capture "y" Int :> Get '[JSON] Position
41type ExampleAPI = "position" :> Capture "x" Int :> Capture "y" Int :> Get '[JSON] Position
@@ -46,7 +46,7 @@ exampleAPI :: Proxy ExampleAPI
46exampleAPI = Proxy
46exampleAPI = Proxy
47```
47```
48
48
49−While *servant* can see e.g. that there are 3 endpoints and that the response bodies will be in JSON, it doesn't know what influence the captures, parameters, request bodies and other combinators have on the webservice. This is where some manual work is required.
49+While **servant** can see e.g. that there are 3 endpoints and that the response bodies will be in JSON, it doesn't know what influence the captures, parameters, request bodies and other combinators have on the webservice. This is where some manual work is required.
50
50
51For every capture, request body, response body, query param, we have to give some explanations about how it influences the response, what values are possible and the likes. Here's how it looks like for the parameters we have above.
51For every capture, request body, response body, query param, we have to give some explanations about how it influences the response, what values are possible and the likes. Here's how it looks like for the parameters we have above.
52
52
@@ -97,9 +97,9 @@ apiDocs :: API
97apiDocs = docs exampleAPI
97apiDocs = docs exampleAPI
98```
98```
99
99
100−`API` is a type provided by *servant-docs* that stores all the information one needs about a web API in order to generate documentation in some format. Out of the box, *servant-docs* only provides a pretty documentation printer that outputs [Markdown](http://en.wikipedia.org/wiki/Markdown), but the [servant-pandoc](http://hackage.haskell.org/package/servant-pandoc) package can be used to target many useful formats.
100+`API` is a type provided by **servant-docs** that stores all the information one needs about a web API in order to generate documentation in some format. Out of the box, **servant-docs** only provides a pretty documentation printer that outputs [Markdown](http://en.wikipedia.org/wiki/Markdown), but the [**servant-pandoc**](http://hackage.haskell.org/package/servant-pandoc) package can be used to target many useful formats.
101
101
102−*servant*'s markdown pretty printer is a function named `markdown`.
102+**servant**'s markdown pretty printer is a function named `markdown`.
103
103
104``` haskell ignore
104``` haskell ignore
105markdown :: API -> String
105markdown :: API -> String
@@ -107,97 +107,97 @@ markdown :: API -> String
107
107
108That lets us see what our API docs look down in markdown, by looking at `markdown apiDocs`.
108That lets us see what our API docs look down in markdown, by looking at `markdown apiDocs`.
109
109
110−``` text
110+````````` text
111− ## Welcome
111+## Welcome
112
112
113− This is our super webservice's API.
113+This is our super webservice's API.
114
114
115− Enjoy!
115+Enjoy!
116
116
117− ## GET /hello
117+## GET /hello
118
118
119− #### GET Parameters:
119+#### GET Parameters:
120
120
121− - name
121+- name
122− - **Values**: *Alp, John Doe, ...*
122+ - **Values**: *Alp, John Doe, ...*
123− - **Description**: Name of the person to say hello to.
123+ - **Description**: Name of the person to say hello to.
124
124
125
125
126− #### Response:
126+#### Response:
127
127
128− - Status code 200
128+- Status code 200
129− - Headers: []
129+- Headers: []
130
130
131− - Supported content types are:
131+- Supported content types are:
132
132
133− - `application/json`
133+ - `application/json`
134
134
135− - When a value is provided for 'name'
135+- When a value is provided for 'name'
136
136
137− ```javascript
137+ ```javascript
138− {"msg":"Hello, Alp"}
138+ {"msg":"Hello, Alp"}
139− ```
139+ ```
140
140
141− - When 'name' is not specified
141+- When 'name' is not specified
142
142
143− ```javascript
143+ ```javascript
144− {"msg":"Hello, anonymous coward"}
144+ {"msg":"Hello, anonymous coward"}
145− ```
145+ ```
146
146
147− ## POST /marketing
147+## POST /marketing
148
148
149− #### Request:
149+#### Request:
150
150
151− - Supported content types are:
151+- Supported content types are:
152
152
153− - `application/json`
153+ - `application/json`
154
154
155− - Example: `application/json`
155+- Example: `application/json`
156
156
157− ```javascript
157+ ```javascript
158− {"email":"alp@foo.com","interested_in":["haskell","mathematics"],"age":26,"name":"Alp"}
158+ {"email":"alp@foo.com","interested_in":["haskell","mathematics"],"age":26,"name":"Alp"}
159− ```
159+ ```
160
160
161− #### Response:
161+#### Response:
162
162
163− - Status code 201
163+- Status code 201
164− - Headers: []
164+- Headers: []
165
165
166− - Supported content types are:
166+- Supported content types are:
167
167
168− - `application/json`
168+ - `application/json`
169
169
170− - Response body as below.
170+- Response body as below.
171
171
172− ```javascript
172+ ```javascript
173− {"subject":"Hey Alp, we miss you!","body":"Hi Alp,\n\nSince you've recently turned 26, have you checked out our latest haskell, mathematics products? Give us a visit!","to":"alp@foo.com","from":"great@company.com"}
173+ {"subject":"Hey Alp, we miss you!","body":"Hi Alp,\n\nSince you've recently turned 26, have you checked out our latest haskell, mathematics products? Give us a visit!","to":"alp@foo.com","from":"great@company.com"}
174− ```
174+ ```
175
175
176− ## GET /position/:x/:y
176+## GET /position/:x/:y
177
177
178− #### Captures:
178+#### Captures:
179
179
180− - *x*: (integer) position on the x axis
180+- *x*: (integer) position on the x axis
181− - *y*: (integer) position on the y axis
181+- *y*: (integer) position on the y axis
182
182
183− #### Response:
183+#### Response:
184
184
185− - Status code 200
185+- Status code 200
186− - Headers: []
186+- Headers: []
187
187
188− - Supported content types are:
188+- Supported content types are:
189
189
190− - `application/json`
190+ - `application/json`
191
191
192− - Response body as below.
192+- Response body as below.
193
193
194− ```javascript
194+ ```javascript
195− {"x":3,"y":14}
195+ {"x":3,"y":14}
196− ```
196+ ```
197
197
198−```
198+`````````
199
199
200−However, we can also add one or more introduction sections to the document. We just need to tweak the way we generate `apiDocs`. We will also convert the content to a lazy `ByteString` since this is what *wai* expects for `Raw` endpoints.
200+However, we can also add one or more introduction sections to the document. We just need to tweak the way we generate `apiDocs`. We will also convert the content to a lazy `ByteString` since this is what **wai** expects for `Raw` endpoints.
201
201
202``` haskell
202``` haskell
203docsBS :: ByteString
203docsBS :: ByteString
@@ -231,4 +231,4 @@ app :: Application
231app = serve api server
231app = serve api server
232```
232```
233
233
234−And if you spin up this server with `dist/build/tutorial/tutorial 10` and go to anywhere else than `/position`, `/hello` and `/marketing`, you will see the API docs in markdown. This is because `serveDocs` is attempted if the 3 other endpoints don't match and systematically succeeds since its definition is to just return some fixed bytestring with the `text/plain` content type.
234+And if you spin up this server and request anything else than `/position`, `/hello` and `/marketing`, you will see the API docs in markdown. This is because `serveDocs` is attempted if the 3 other endpoints don't match and systematically succeeds since its definition is to just return some fixed bytestring with the `text/plain` content type.