@@ -26,7 +26,7 @@ import Servant.Server
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)):
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(..),
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.
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:
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
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.
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.
@@ -97,9 +97,9 @@ apiDocs :: API
97apiDocs = docs exampleAPI
97apiDocs = docs exampleAPI
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.
102−*servant*'s markdown pretty printer is a function named `markdown`.
102+**servant**'s markdown pretty printer is a function named `markdown`.
104``` haskell ignore
104``` haskell ignore
105markdown :: API -> String
105markdown :: API -> String
@@ -107,97 +107,97 @@ markdown :: API -> String
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`.
110−``` text
110+````````` text
111− ## Welcome
111+## Welcome
113− This is our super webservice's API.
113+This is our super webservice's API.
117− ## GET /hello
117+## GET /hello
119− #### GET Parameters:
119+#### GET Parameters:
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.
126− #### Response:
126+#### Response:
128− - Status code 200
128+- Status code 200
129− - Headers: []
129+- Headers: []
131− - Supported content types are:
131+- Supported content types are:
133− - `application/json`
133+ - `application/json`
135− - When a value is provided for 'name'
135+- When a value is provided for 'name'
137− ```javascript
137+ ```javascript
138− {"msg":"Hello, Alp"}
138+ {"msg":"Hello, Alp"}
141− - When 'name' is not specified
141+- When 'name' is not specified
143− ```javascript
143+ ```javascript
144− {"msg":"Hello, anonymous coward"}
144+ {"msg":"Hello, anonymous coward"}
147− ## POST /marketing
147+## POST /marketing
149− #### Request:
149+#### Request:
151− - Supported content types are:
151+- Supported content types are:
153− - `application/json`
153+ - `application/json`
155− - Example: `application/json`
155+- Example: `application/json`
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"}
161− #### Response:
161+#### Response:
163− - Status code 201
163+- Status code 201
164− - Headers: []
164+- Headers: []
166− - Supported content types are:
166+- Supported content types are:
168− - `application/json`
168+ - `application/json`
170− - Response body as below.
170+- Response body as below.
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"}
176− ## GET /position/:x/:y
176+## GET /position/:x/:y
178− #### Captures:
178+#### Captures:
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
183− #### Response:
183+#### Response:
185− - Status code 200
185+- Status code 200
186− - Headers: []
186+- Headers: []
188− - Supported content types are:
188+- Supported content types are:
190− - `application/json`
190+ - `application/json`
192− - Response body as below.
192+- Response body as below.
194− ```javascript
194+ ```javascript
195− {"x":3,"y":14}
195+ {"x":3,"y":14}
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.
202``` haskell
202``` haskell
203docsBS :: ByteString
203docsBS :: ByteString
@@ -231,4 +231,4 @@ app :: Application
231app = serve api server
231app = serve api server
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.