Fix typos and grammar (#1304)

* Fix typos and grammar

* Remove redundant words, fix articles

* More language fixes

* More typo fixes and resolve TODO about missing links
This commit is contained in:
Jan Hrcek 2020-06-06 06:43:51 +02:00 committed by GitHub
parent 67cb564aef
commit b9d8fbcdc1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 83 additions and 80 deletions

View file

@ -103,7 +103,7 @@ the `news` label if you make a new package so we can know about it!
## Release policy ## Release policy
We are currently moving to a more aggresive release policy, so that you can get We are currently moving to a more aggressive release policy, so that you can get
what you contribute from Hackage fairly soon. However, note that prior to major what you contribute from Hackage fairly soon. However, note that prior to major
releases it may take some time in between releases. releases it may take some time in between releases.

View file

@ -32,7 +32,7 @@ See `CONTRIBUTING.md`
- It's a good idea to separate these steps, as tests often pass, if they compile :) - It's a good idea to separate these steps, as tests often pass, if they compile :)
- See `cabal.project` to selectively `allow-newer` - See `cabal.project` to selectively `allow-newer`
- If some packages are broken, on your discretisation there are two options: - If some packages are broken, on your discretisation there are two options:
- Fix them and make PRs: it's good idea to test against older `servant` version too. - Fix them and make PRs: it's a good idea to test against older `servant` version too.
- Temporarily comment out broken package - Temporarily comment out broken package
- If you make a commit for `servant-universe`, you can use it as submodule in private projects to test even more - If you make a commit for `servant-universe`, you can use it as submodule in private projects to test even more
- When ripples are cleared out: - When ripples are cleared out:
@ -60,7 +60,7 @@ constraints:
troublemaker <13.37 && > 13.37 troublemaker <13.37 && > 13.37
``` ```
## TechEmpower framework bechmarks ## TechEmpower framework benchmarks
We develop and maintain the servant TFB entry in https://github.com/haskell-servant/FrameworkBenchmarks/ We develop and maintain the servant TFB entry in https://github.com/haskell-servant/FrameworkBenchmarks/

View file

@ -8,7 +8,10 @@ In other words, without streaming libraries.
- Some basic usage doesn't require usage of streaming libraries, - Some basic usage doesn't require usage of streaming libraries,
like `conduit`, `pipes`, `machines` or `streaming`. like `conduit`, `pipes`, `machines` or `streaming`.
We have bindings for them though. We have bindings for them though.
- This is similar example file, which is bundled with each of the packages (TODO: links) - Similar example is bundled with each of our streaming library interop packages (see
[servant-pipes](https://github.com/haskell-servant/servant/blob/master/servant-pipes/example/Main.hs),
[servant-conduit](https://github.com/haskell-servant/servant/blob/master/servant-conduit/example/Main.hs) and
[servant-machines](https://github.com/haskell-servant/servant/blob/master/servant-machines/example/Main.hs))
- `SourceT` doesn't have *Prelude* with handy combinators, so we have to write - `SourceT` doesn't have *Prelude* with handy combinators, so we have to write
things ourselves. (Note to self: `mapM` and `foldM` would be handy to have). things ourselves. (Note to self: `mapM` and `foldM` would be handy to have).

View file

@ -1,7 +1,7 @@
# Generating mock curl calls # Generating mock curl calls
In this example we will generate curl requests with mock post data from a servant API. In this example we will generate curl requests with mock post data from a servant API.
This may be usefull for testing and development purposes. This may be useful for testing and development purposes.
Especially post requests with a request body are tedious to send manually. Especially post requests with a request body are tedious to send manually.
Also, we will learn how to use the servant-foreign library to generate stuff from servant APIs. Also, we will learn how to use the servant-foreign library to generate stuff from servant APIs.

View file

@ -2,7 +2,7 @@
This doc will walk through a single-module implementation of a servant API connecting to a MySQL database. It will also include some basic CRUD operations. This doc will walk through a single-module implementation of a servant API connecting to a MySQL database. It will also include some basic CRUD operations.
Once you can wrap your head around this implemenation, understanding more complex features like resource pools would be beneficial next steps. Once you can wrap your head around this implementation, understanding more complex features like resource pools would be beneficial next steps.
The only *prerequisite* is that you have a MySQL database open on port 3306 of your machine. Docker is an easy way to manage this. The only *prerequisite* is that you have a MySQL database open on port 3306 of your machine. Docker is an easy way to manage this.

View file

@ -90,8 +90,8 @@ startServer = run 8080 (serve api upload)
Finally, a main function that brings up our server and Finally, a main function that brings up our server and
sends some test request with `http-client` (and not sends some test request with `http-client` (and not
servant-client this time, has servant-multipart does not servant-client this time, as servant-multipart does not
yet have support for client generation. yet have support for client generation).
``` haskell ``` haskell
main :: IO () main :: IO ()

View file

@ -43,13 +43,13 @@ api :: Proxy (ToServantApi Routes)
api = genericApi (Proxy :: Proxy Routes) api = genericApi (Proxy :: Proxy Routes)
``` ```
It's recommented to use `genericApi` function, as then you'll get It's recommended to use `genericApi` function, as then you'll get
better error message, for example if you forget to `derive Generic`. better error message, for example if you forget to `derive Generic`.
## Links ## Links
The clear advantage of record-based generics approach, is that The clear advantage of record-based generics approach, is that
we can get safe links very conviently. We don't need to define endpoint types, we can get safe links very conveniently. We don't need to define endpoint types,
as field accessors work as proxies: as field accessors work as proxies:
```haskell ```haskell
@ -67,7 +67,7 @@ routesLinks = allFieldLinks
## Client ## Client
Even more power starts to show when we generate a record of client functions. Even more power starts to show when we generate a record of client functions.
Here we use `genericClientHoist` function, which let us simultaneously Here we use `genericClientHoist` function, which lets us simultaneously
hoist the monad, in this case from `ClientM` to `IO`. hoist the monad, in this case from `ClientM` to `IO`.
```haskell ```haskell

View file

@ -254,7 +254,7 @@ loginHandler cookieSettings jwtSettings form = do
liftIO $ pushLogStrLn logset $ toLogStr logMsg liftIO $ pushLogStrLn logset $ toLogStr logMsg
throwError err401 throwError err401
Just applyCookies -> do Just applyCookies -> do
let successMsg = logMsg{message = "AdminUser succesfully authenticated!"} let successMsg = logMsg{message = "AdminUser successfully authenticated!"}
liftIO $ pushLogStrLn logset $ toLogStr successMsg liftIO $ pushLogStrLn logset $ toLogStr successMsg
pure $ applyCookies successMsg pure $ applyCookies successMsg
loginHandler _ _ _ = throwError err401 loginHandler _ _ _ = throwError err401

View file

@ -8,7 +8,7 @@ some login token would be saved in the user agent local storage.
Workflow: Workflow:
1. user is presentend with a login button, 1. user is presented with a login button,
2. when the user click on the button it is redirected to the OIDC 2. when the user click on the button it is redirected to the OIDC
provider, provider,
3. the user login in the OIDC provider, 3. the user login in the OIDC provider,
@ -222,8 +222,8 @@ The `AuthInfo` is about the infos we can grab from OIDC provider.
To be more precise, the user should come with a `code` (a token) and To be more precise, the user should come with a `code` (a token) and
POSTing that code to the correct OIDC provider endpoint should return a JSON POSTing that code to the correct OIDC provider endpoint should return a JSON
object. One of the field should be named `id_token` which should be a object. One of the field should be named `id_token` which should be a
JWT containing all the informations we need. Depending on the scopes we JWT containing all the information we need. Depending on the scopes we
asked we might get more informations. asked we might get more information.
``` haskell ``` haskell
-- | @AuthInfo@ -- | @AuthInfo@
@ -248,13 +248,13 @@ instance JSON.ToJSON AuthInfo where
type LoginHandler = AuthInfo -> IO (Either Text User) type LoginHandler = AuthInfo -> IO (Either Text User)
``` ```
The `handleLoggedIn` is that part that will retrieve the informations from The `handleLoggedIn` is that part that will retrieve the information from
the user once he is redirected from the OIDC Provider after login. the user once he is redirected from the OIDC Provider after login.
If the user is redirected to the `redirect_uri` but with an `error` query If the user is redirected to the `redirect_uri` but with an `error` query
parameter then it means something goes wrong. parameter then it means something goes wrong.
If there is no error query param but a `code` query param it means the user If there is no error query param but a `code` query param it means the user
sucessfully logged in. From there we need to make a request to the token successfully logged in. From there we need to make a request to the token
endpoint of the OIDC provider. Its a POST that should contains the code endpoint of the OIDC provider. Its a POST that should contains the code
as well as the client id & secret. as well as the client id & secret.
This is the role of the `requestTokens` to make this HTTP POST. This is the role of the `requestTokens` to make this HTTP POST.
@ -332,7 +332,7 @@ data Customer = Customer {
Here is the code that display the homepage. Here is the code that display the homepage.
It should contain a link to the the `/login` URL. It should contain a link to the the `/login` URL.
When the user will click on this link it will be redirected to Google login page When the user will click on this link it will be redirected to Google login page
with some generated informations. with some generated information.
The page also display the content of the local storage. The page also display the content of the local storage.
And in particular the items `api-key` and `user-id`. And in particular the items `api-key` and `user-id`.
@ -366,7 +366,7 @@ instance ToMarkup Homepage where
We need some helpers to generate random string for generating state and API Keys. We need some helpers to generate random string for generating state and API Keys.
``` haskell ``` haskell
-- | generate a random Bystestring, not necessarily extremely good randomness -- | generate a random ByteString, not necessarily extremely good randomness
-- still the password will be long enough to be very difficult to crack -- still the password will be long enough to be very difficult to crack
genRandomBS :: IO ByteString genRandomBS :: IO ByteString
genRandomBS = do genRandomBS = do

View file

@ -18,7 +18,7 @@ For example: `Range: createdAt 2017-01-15T23:14:67.000Z; offset 5; order desc` i
the client is willing to retrieve the next batch of document in descending order that were the client is willing to retrieve the next batch of document in descending order that were
created after the fifteenth of January, skipping the first 5. created after the fifteenth of January, skipping the first 5.
As a response, the server may return the list of corresponding document, and augment the As a response, the server may return the list of corresponding documents, and augment the
response with 3 headers: response with 3 headers:
- `Accept-Ranges`: A comma-separated list of fields upon which a range can be defined - `Accept-Ranges`: A comma-separated list of fields upon which a range can be defined
@ -127,7 +127,7 @@ defaultRange =
getDefaultRange (Proxy @Color) getDefaultRange (Proxy @Color)
``` ```
Note that `getFieldValue :: Proxy "name" -> Color -> String` is the minimal complete definintion Note that `getFieldValue :: Proxy "name" -> Color -> String` is the minimal complete definition
of the class. Yet, you can define `getRangeOptions` to provide different parsing options (see of the class. Yet, you can define `getRangeOptions` to provide different parsing options (see
the last section of this guide). In the meantime, we've also defined a `defaultRange` as it will the last section of this guide). In the meantime, we've also defined a `defaultRange` as it will
come in handy when defining our handler. come in handy when defining our handler.
@ -148,7 +148,7 @@ type MyHeaders =
``` ```
`PageHeaders` is a type alias provided by the library to declare the necessary response headers `PageHeaders` is a type alias provided by the library to declare the necessary response headers
we mentionned in introduction. Expanding the alias boils down to the following: we mentioned in introduction. Expanding the alias boils down to the following:
``` haskell ``` haskell
-- type MyHeaders = -- type MyHeaders =
@ -165,7 +165,7 @@ not, _servant-pagination_ provides an easy way to lift a collection of resources
#### Server #### Server
Time to connect the last bits by defining the server implementation of our colorful API. The `Ranges` Time to connect the last bits by defining the server implementation of our colorful API. The `Ranges`
type we've defined above (tight to the `Range` HTTP header) indicates the server to parse any `Range` type we've defined above (tied to the `Range` HTTP header) indicates the server to parse any `Range`
header, looking for the format defined in introduction with fields and target types we have just declared. header, looking for the format defined in introduction with fields and target types we have just declared.
If no such header is provided, we will end up receiving `Nothing`. Otherwise, it will be possible If no such header is provided, we will end up receiving `Nothing`. Otherwise, it will be possible
to _extract_ a `Range` from our `Ranges`. to _extract_ a `Range` from our `Ranges`.
@ -192,7 +192,7 @@ the format we defined, where `<field>` here can only be `name` and `<value>` mus
- `Range: <field> [<value>][; offset <o>][; limit <l>][; order <asc|desc>]` - `Range: <field> [<value>][; offset <o>][; limit <l>][; order <asc|desc>]`
Beside the target field, everything is pretty much optional in the `Range` HTTP header. Missing parts Beside the target field, everything is pretty much optional in the `Range` HTTP header. Missing parts
are deducted from the `RangeOptions` that are part of the `HasPagination` instance. Therefore, all are deduced from the `RangeOptions` that are part of the `HasPagination` instance. Therefore, all
following examples are valid requests to send to our server: following examples are valid requests to send to our server:
- 1 - `curl http://localhost:1442/colors -vH 'Range: name'` - 1 - `curl http://localhost:1442/colors -vH 'Range: name'`
@ -219,7 +219,7 @@ The previous ranges reads as follows:
Note that in the simple above scenario, there's no ambiguity with `extractRange` and `returnRange` Note that in the simple above scenario, there's no ambiguity with `extractRange` and `returnRange`
because there's only one possible `Range` defined on our resource. Yet, as you've most probably because there's only one possible `Range` defined on our resource. Yet, as you've most probably
noticed, the `Ranges` combinator accepts a list of fields, each of which must declare a `HasPagination` noticed, the `Ranges` combinator accepts a list of fields, each of which must declare a `HasPagination`
instance. Doing so will make the other helper functions more ambiguous and type annotation are instance. Doing so will make the other helper functions more ambiguous and type annotations are
highly likely to be needed. highly likely to be needed.
@ -235,8 +235,8 @@ instance HasPagination Color "hex" where
#### Parsing Options #### Parsing Options
By default, `servant-pagination` provides an implementation of `getRangeOptions` for each By default, `servant-pagination` provides an implementation of `getRangeOptions` for each
`HasPagination` instance. However, this can be overwritten when defining the instance to provide `HasPagination` instance. However, this can be overridden when defining the instance to provide
your own options. This options come into play when a `Range` header is received and isn't fully your own options. These options come into play when a `Range` header is received and isn't fully
specified (`limit`, `offset`, `order` are all optional) to provide default fallback values for those. specified (`limit`, `offset`, `order` are all optional) to provide default fallback values for those.
For instance, let's say we wanted to change the default limit to `5` in a new range on For instance, let's say we wanted to change the default limit to `5` in a new range on

View file

@ -79,7 +79,7 @@ It does three things. First it initializes the service which will communicate wi
- the Sentry `DSN`, which is obtained when creating a new project on Sentry - the Sentry `DSN`, which is obtained when creating a new project on Sentry
- a default way to update sentry fields, where we use the identity function - a default way to update sentry fields, where we use the identity function
- an event trasport, which generally would be `sendRecord`, an HTTPS capable trasport which uses http-conduit - an event transport, which generally would be `sendRecord`, an HTTPS capable transport which uses http-conduit
- a fallback handler, which we choose to be `silentFallback` since later we are logging to the console anyway. - a fallback handler, which we choose to be `silentFallback` since later we are logging to the console anyway.
In the second step it actually sends our message to Sentry with the `register` function. Its arguments are: In the second step it actually sends our message to Sentry with the `register` function. Its arguments are:

View file

@ -144,7 +144,7 @@ simpleAPIServer
:: m [a] :: m [a]
-> (i -> m a) -> (i -> m a)
-> (a -> m NoContent) -> (a -> m NoContent)
-> Server (SimpleAPI name a i) m -> ServerT (SimpleAPI name a i) m
simpleAPIServer listAs getA postA = simpleAPIServer listAs getA postA =
listAs :<|> getA :<|> postA listAs :<|> getA :<|> postA

View file

@ -1,6 +1,6 @@
# Using a custom monad # Using a custom monad
In this section we will create and API for a book shelf without any backing DB storage. In this section we will create an API for a book shelf without any backing DB storage.
We will keep state in memory and share it between requests using `Reader` monad and `STM`. We will keep state in memory and share it between requests using `Reader` monad and `STM`.
We start with a pretty standard set of imports and definition of the model: We start with a pretty standard set of imports and definition of the model:

View file

@ -141,7 +141,7 @@ and calling the continuation. We should get a `Pure` value.
Pure n -> Pure n ->
putStrLn $ "Expected 1764, got " ++ show n putStrLn $ "Expected 1764, got " ++ show n
_ -> _ ->
putStrLn "ERROR: didn't got a response" putStrLn "ERROR: didn't get a response"
``` ```
So that's it. Using `Free` we can evaluate servant clients step-by-step, and So that's it. Using `Free` we can evaluate servant clients step-by-step, and

View file

@ -108,7 +108,7 @@ API with "private." Additionally, the private parts of our API use the
realm for this authentication is `"foo-realm"`). realm for this authentication is `"foo-realm"`).
Unfortunately we're not done. When someone makes a request to our `"private"` Unfortunately we're not done. When someone makes a request to our `"private"`
API, we're going to need to provide to servant the logic for validifying API, we're going to need to provide to servant the logic for validating
usernames and passwords. This adds a certain conceptual wrinkle in servant's usernames and passwords. This adds a certain conceptual wrinkle in servant's
design that we'll briefly discuss. If you want the **TL;DR**: we supply a lookup design that we'll briefly discuss. If you want the **TL;DR**: we supply a lookup
function to servant's new `Context` primitive. function to servant's new `Context` primitive.
@ -260,7 +260,7 @@ this.
Let's implement a trivial authentication scheme. We will protect our API by Let's implement a trivial authentication scheme. We will protect our API by
looking for a cookie named `"servant-auth-cookie"`. This cookie's value will looking for a cookie named `"servant-auth-cookie"`. This cookie's value will
contain a key from which we can lookup a `Account`. contain a key from which we can lookup an `Account`.
```haskell ```haskell
-- | An account type that we "fetch from the database" after -- | An account type that we "fetch from the database" after
@ -274,7 +274,7 @@ database = fromList [ ("key1", Account "Anne Briggs")
, ("key3", Account "Ghédalia Tazartès") , ("key3", Account "Ghédalia Tazartès")
] ]
-- | A method that, when given a password, will return a Account. -- | A method that, when given a password, will return an Account.
-- This is our bespoke (and bad) authentication logic. -- This is our bespoke (and bad) authentication logic.
lookupAccount :: ByteString -> Handler Account lookupAccount :: ByteString -> Handler Account
lookupAccount key = case Map.lookup key database of lookupAccount key = case Map.lookup key database of
@ -346,7 +346,7 @@ genAuthServerContext = authHandler :. EmptyContext
-- | Our API, where we provide all the author-supplied handlers for each end -- | Our API, where we provide all the author-supplied handlers for each end
-- point. Note that 'privateDataFunc' is a function that takes 'Account' as an -- point. Note that 'privateDataFunc' is a function that takes 'Account' as an
-- argument. We dont' worry about the authentication instrumentation here, -- argument. We don't worry about the authentication instrumentation here,
-- that is taken care of by supplying context -- that is taken care of by supplying context
genAuthServer :: Server AuthGenAPI genAuthServer :: Server AuthGenAPI
genAuthServer = genAuthServer =
@ -385,11 +385,11 @@ Creating a generalized, ad-hoc authentication scheme was fairly straight
forward: forward:
1. use the `AuthProtect` combinator to protect your API. 1. use the `AuthProtect` combinator to protect your API.
2. choose a application-specific data type used by your server when 2. choose an application-specific data type used by your server when
authentication is successful (in our case this was `Account`). authentication is successful (in our case this was `Account`).
3. Create a value of `AuthHandler Request Account` which encapsulates the 3. Create a value of `AuthHandler Request Account` which encapsulates the
authentication logic (`Request -> Handler Account`). This function authentication logic (`Request -> Handler Account`). This function
will be executed everytime a request matches a protected route. will be executed every time a request matches a protected route.
4. Provide an instance of the `AuthServerData` type family, specifying your 4. Provide an instance of the `AuthServerData` type family, specifying your
application-specific data type returned when authentication is successful (in application-specific data type returned when authentication is successful (in
our case this was `Account`). our case this was `Account`).

View file

@ -161,7 +161,7 @@ The types of the arguments for the functions are the same as for (server-side) r
## Changing the monad the client functions live in ## Changing the monad the client functions live in
Just like `hoistServer` allows us to change the monad in which request handlers Just like `hoistServer` allows us to change the monad in which request handlers
of a web application live in, we also have `hoistClient` for changing the monad of a web application live, we also have `hoistClient` for changing the monad
in which _client functions_ live. Consider the following trivial API: in which _client functions_ live. Consider the following trivial API:
``` haskell ``` haskell
@ -173,7 +173,7 @@ hoistClientAPI = Proxy
We already know how to derive client functions for this API, and as we have We already know how to derive client functions for this API, and as we have
seen above they all return results in the `ClientM` monad when using `servant-client`. seen above they all return results in the `ClientM` monad when using `servant-client`.
However, `ClientM` rarely (or never) is the actual monad we need to use the client However, `ClientM` is rarely (or never) the actual monad we need to use the client
functions in. Sometimes we need to run them in IO, sometimes in a custom monad functions in. Sometimes we need to run them in IO, sometimes in a custom monad
stack. `hoistClient` is a very simple solution to the problem of "changing" the monad stack. `hoistClient` is a very simple solution to the problem of "changing" the monad
the clients run in. the clients run in.

View file

@ -77,7 +77,7 @@ instance ToSample HelloMessage where
[ ("When a value is provided for 'name'", HelloMessage "Hello, Alp") [ ("When a value is provided for 'name'", HelloMessage "Hello, Alp")
, ("When 'name' is not specified", HelloMessage "Hello, anonymous coward") , ("When 'name' is not specified", HelloMessage "Hello, anonymous coward")
] ]
-- mutliple examples to display this time -- multiple examples to display this time
ci :: ClientInfo ci :: ClientInfo
ci = ClientInfo "Alp" "alp@foo.com" 26 ["haskell", "mathematics"] ci = ClientInfo "Alp" "alp@foo.com" 26 ["haskell", "mathematics"]
@ -108,7 +108,7 @@ apiDocs = docs exampleAPI
markdown :: API -> String markdown :: API -> String
``` ```
That lets us see what our API docs look down in markdown, by looking at `markdown apiDocs`. That lets us see what our API docs look like in markdown, by looking at `markdown apiDocs`.
````````` text ````````` text
## GET /hello ## GET /hello

View file

@ -228,13 +228,13 @@ data CommonGeneratorOptions = CommonGeneratorOptions
{ {
-- | function generating function names -- | function generating function names
functionNameBuilder :: FunctionName -> Text functionNameBuilder :: FunctionName -> Text
-- | name used when a user want to send the request body (to let you redefine it) -- | name used when a user wants to send the request body (to let you redefine it)
, requestBody :: Text , requestBody :: Text
-- | name of the callback parameter when the request was successful -- | name of the callback parameter when the request was successful
, successCallback :: Text , successCallback :: Text
-- | name of the callback parameter when the request reported an error -- | name of the callback parameter when the request reported an error
, errorCallback :: Text , errorCallback :: Text
-- | namespace on which we define the js function (empty mean local var) -- | namespace on which we define the js function (empty means local var)
, moduleName :: Text , moduleName :: Text
-- | a prefix that should be prepended to the URL in the generated JS -- | a prefix that should be prepended to the URL in the generated JS
, urlPrefix :: Text , urlPrefix :: Text

View file

@ -183,7 +183,7 @@ users2 = [isaac, albert]
Now, just like we separate the various endpoints in `UserAPI` with `:<|>`, we Now, just like we separate the various endpoints in `UserAPI` with `:<|>`, we
are going to separate the handlers with `:<|>` too! They must be provided in are going to separate the handlers with `:<|>` too! They must be provided in
the same order as in in the API type. the same order as in the API type.
``` haskell ``` haskell
server2 :: Server UserAPI2 server2 :: Server UserAPI2
@ -716,7 +716,7 @@ $ curl --verbose http://localhost:8081/myfile.txt
> >
< HTTP/1.1 404 Not Found < HTTP/1.1 404 Not Found
[snip] [snip]
myfile.txt just isnt there, please leave this server alone. myfile.txt just isn't there, please leave this server alone.
$ echo Hello > myfile.txt $ echo Hello > myfile.txt
@ -818,7 +818,7 @@ If it doesn't exist, the handler will fail with a `404` status code.
`serveDirectoryWebApp` uses some standard settings that fit the use case of `serveDirectoryWebApp` uses some standard settings that fit the use case of
serving static files for most web apps. You can find out about the other serving static files for most web apps. You can find out about the other
options in the documentation of the `Servant.Utils.StaticFiles` module. options in the documentation of the `Servant.Server.StaticFiles` module.
## Nested APIs ## Nested APIs
@ -1135,7 +1135,7 @@ true
### An arrow is a reader too. ### An arrow is a reader too.
In previous versions of `servant` we had an `enter` to do what `hoistServer` In previous versions of `servant` we had an `enter` to do what `hoistServer`
does now. `enter` had a ambitious design goals, but was problematic in practice. does now. `enter` had an ambitious design goals, but was problematic in practice.
One problematic situation was when the source monad was `(->) r`, yet it's One problematic situation was when the source monad was `(->) r`, yet it's
handy in practice, because `(->) r` is isomorphic to `Reader r`. handy in practice, because `(->) r` is isomorphic to `Reader r`.
@ -1166,7 +1166,7 @@ back a *stream* of results, served one at a time. Stream endpoints only provide
a single content type, and also specify what framing strategy is used to a single content type, and also specify what framing strategy is used to
delineate the results. To serve these results, we need to give back a stream delineate the results. To serve these results, we need to give back a stream
producer. Adapters can be written to *Pipes*, *Conduit* and the like, or producer. Adapters can be written to *Pipes*, *Conduit* and the like, or
written directly as `SourceIO`s. SourceIO builts upon servant's own `SourceT` written directly as `SourceIO`s. SourceIO builds upon servant's own `SourceT`
stream type (it's simpler than *Pipes* or *Conduit*). stream type (it's simpler than *Pipes* or *Conduit*).
The API of a streaming endpoint needs to explicitly specify which sort of The API of a streaming endpoint needs to explicitly specify which sort of
generator it produces. Note that the generator itself is returned by a generator it produces. Note that the generator itself is returned by a

View file

@ -205,7 +205,7 @@
- *servant-client-core* Add `hoistClient` to `HasClient`. - *servant-client-core* Add `hoistClient` to `HasClient`.
Just like `hoistServer` allows us to change the monad in which request handlers Just like `hoistServer` allows us to change the monad in which request handlers
of a web application live in, we also have `hoistClient` for changing the monad of a web application live, we also have `hoistClient` for changing the monad
in which *client functions* live. in which *client functions* live.
Read [tutorial section for more information](https://docs.servant.dev/en/release-0.14/tutorial/Client.html#changing-the-monad-the-client-functions-live-in). Read [tutorial section for more information](https://docs.servant.dev/en/release-0.14/tutorial/Client.html#changing-the-monad-the-client-functions-live-in).
([#936](https://github.com/haskell-servant/servant/pull/936)) ([#936](https://github.com/haskell-servant/servant/pull/936))

View file

@ -104,7 +104,7 @@ test-suite spec
, base-compat , base-compat
, servant-client-core , servant-client-core
-- Additonal dependencies -- Additional dependencies
build-depends: build-depends:
deepseq >= 1.4.2.0 && < 1.5 deepseq >= 1.4.2.0 && < 1.5
, hspec >= 2.6.0 && < 2.8 , hspec >= 2.6.0 && < 2.8

View file

@ -198,7 +198,7 @@
- *servant-client-core* Add `hoistClient` to `HasClient`. - *servant-client-core* Add `hoistClient` to `HasClient`.
Just like `hoistServer` allows us to change the monad in which request handlers Just like `hoistServer` allows us to change the monad in which request handlers
of a web application live in, we also have `hoistClient` for changing the monad of a web application live, we also have `hoistClient` for changing the monad
in which *client functions* live. in which *client functions* live.
Read [tutorial section for more information](https://docs.servant.dev/en/release-0.14/tutorial/Client.html#changing-the-monad-the-client-functions-live-in). Read [tutorial section for more information](https://docs.servant.dev/en/release-0.14/tutorial/Client.html#changing-the-monad-the-client-functions-live-in).
([#936](https://github.com/haskell-servant/servant/pull/936)) ([#936](https://github.com/haskell-servant/servant/pull/936))

View file

@ -120,7 +120,7 @@ test-suite spec
, wai , wai
, warp , warp
-- Additonal dependencies -- Additional dependencies
build-depends: build-depends:
entropy >= 0.4.1.3 && < 0.5 entropy >= 0.4.1.3 && < 0.5
, hspec >= 2.6.0 && < 2.8 , hspec >= 2.6.0 && < 2.8

View file

@ -130,7 +130,7 @@ withClientM cm env k =
-- streaming response types ('SourceT', 'Conduit', pipes 'Proxy' or 'Machine'). -- streaming response types ('SourceT', 'Conduit', pipes 'Proxy' or 'Machine').
-- For those you have to use 'withClientM'. -- For those you have to use 'withClientM'.
-- --
-- /Note:/ we 'force' the result, so the likehood of accidentally leaking a -- /Note:/ we 'force' the result, so the likelihood of accidentally leaking a
-- connection is smaller. Use with care. -- connection is smaller. Use with care.
-- --
runClientM :: NFData a => ClientM a -> ClientEnv -> IO (Either ClientError a) runClientM :: NFData a => ClientM a -> ClientEnv -> IO (Either ClientError a)

View file

@ -57,7 +57,7 @@ You'll also note that multiple intros are possible.
This is some text This is some text
### Second secton ### Second section
And some more And some more

View file

@ -105,7 +105,7 @@ test-suite spec
, servant-docs , servant-docs
, string-conversions , string-conversions
-- Additonal dependencies -- Additional dependencies
build-depends: build-depends:
tasty >= 1.1.0.4 && < 1.3, tasty >= 1.1.0.4 && < 1.3,
tasty-golden >= 2.3.2 && < 2.4, tasty-golden >= 2.3.2 && < 2.4,

View file

@ -396,7 +396,7 @@ docsWithOptions p = docsFor p (defEndpoint, defAction)
-- > extraInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $ -- > extraInfo (Proxy :: Proxy ("greet" :> Capture "greetid" Text :> Delete)) $
-- > defAction & headers <>~ ["unicorns"] -- > defAction & headers <>~ ["unicorns"]
-- > & notes <>~ [ DocNote "Title" ["This is some text"] -- > & notes <>~ [ DocNote "Title" ["This is some text"]
-- > , DocNote "Second secton" ["And some more"] -- > , DocNote "Second section" ["And some more"]
-- > ] -- > ]
extraInfo :: (IsIn endpoint api, HasLink endpoint, HasDocs endpoint) extraInfo :: (IsIn endpoint api, HasLink endpoint, HasDocs endpoint)

View file

@ -77,7 +77,7 @@ test-suite spec
, servant , servant
, servant-foreign , servant-foreign
-- Additonal dependencies -- Additional dependencies
build-depends: build-depends:
hspec >= 2.6.0 && <2.8 hspec >= 2.6.0 && <2.8

View file

@ -114,7 +114,7 @@ listFromAPISpec = describe "listFromAPI" $ do
shouldBe putReq $ defReq shouldBe putReq $ defReq
{ _reqUrl = Url { _reqUrl = Url
[ Segment $ Static "test" ] [ Segment $ Static "test" ]
-- Shoud this be |intX| or |listX of intX| ? -- Should this be |intX| or |listX of intX| ?
[ QueryArg (Arg "params" "listX of intX") List ] [ QueryArg (Arg "params" "listX of intX") List ]
, _reqMethod = "PUT" , _reqMethod = "PUT"
, _reqHeaders = [] , _reqHeaders = []

View file

@ -114,7 +114,7 @@ test-suite spec
, wai , wai
, warp , warp
-- Additonal dependencies -- Additional dependencies
build-depends: build-depends:
entropy >= 0.4.1.3 && < 0.5 entropy >= 0.4.1.3 && < 0.5
, hspec >= 2.6.0 && < 2.8 , hspec >= 2.6.0 && < 2.8

View file

@ -77,7 +77,7 @@ _ = client comprehensiveAPIWithoutStreaming
spec :: Spec spec :: Spec
spec = describe "Servant.HttpStreams" $ do spec = describe "Servant.HttpStreams" $ do
sucessSpec successSpec
failSpec failSpec
wrappedApiSpec wrappedApiSpec
basicAuthSpec basicAuthSpec
@ -262,8 +262,8 @@ runClientUnsafe x burl = withClientEnvIO burl (runClientMUnsafe x)
where where
runClientMUnsafe x env = withClientM x env return runClientMUnsafe x env = withClientM x env return
sucessSpec :: Spec successSpec :: Spec
sucessSpec = beforeAll (startWaiApp server) $ afterAll endWaiApp $ do successSpec = beforeAll (startWaiApp server) $ afterAll endWaiApp $ do
it "Servant.API.Get root" $ \(_, baseUrl) -> do it "Servant.API.Get root" $ \(_, baseUrl) -> do
left show <$> runClient getRoot baseUrl `shouldReturn` Right carol left show <$> runClient getRoot baseUrl `shouldReturn` Right carol

View file

@ -35,7 +35,7 @@
Some APIs need query parameters rewriting, e.g. in order to support Some APIs need query parameters rewriting, e.g. in order to support
for multiple casing (camel, snake, etc) or something to that effect. for multiple casing (camel, snake, etc) or something to that effect.
This could be easily achieved by using WAI Middleware and modyfing This could be easily achieved by using WAI Middleware and modifying
request's `Query`. But QueryParam, QueryParams and QueryFlag use request's `Query`. But QueryParam, QueryParams and QueryFlag use
`rawQueryString`. By using `queryString` rather then `rawQueryString` `rawQueryString`. By using `queryString` rather then `rawQueryString`
we can enable such rewritings. we can enable such rewritings.
@ -44,7 +44,7 @@
We used `build-type: Custom`, but it's problematic e.g. We used `build-type: Custom`, but it's problematic e.g.
for cross-compiling. The benefit is small, as the doctests for cross-compiling. The benefit is small, as the doctests
can be run other ways too (though not so conviniently). can be run other ways too (though not so conveniently).
0.16.2 0.16.2
------ ------

View file

@ -1,2 +1,2 @@
- `greet.hs` shows how to write a simple webservice, run it, query it with automatically-derived haskell functions and print the (generated) markdown documentation for the API. - `greet.hs` shows how to write a simple webservice, run it, query it with automatically-derived haskell functions and print the (generated) markdown documentation for the API.
- `greet.md` contains the aforementionned generated documentation. - `greet.md` contains the aforementioned generated documentation.

View file

@ -155,7 +155,7 @@ test-suite spec
, transformers-compat , transformers-compat
, wai , wai
-- Additonal dependencies -- Additional dependencies
build-depends: build-depends:
aeson >= 1.4.1.0 && < 1.5 aeson >= 1.4.1.0 && < 1.5
, directory >= 1.3.0.0 && < 1.4 , directory >= 1.3.0.0 && < 1.4

View file

@ -808,7 +808,7 @@ instance (HasContextEntry context (NamedContext name subContext), HasServer subA
instance TypeError (HasServerArrowKindError arr) => HasServer ((arr :: k -> l) :> api) context instance TypeError (HasServerArrowKindError arr) => HasServer ((arr :: k -> l) :> api) context
where where
type ServerT (arr :> api) m = TypeError (HasServerArrowKindError arr) type ServerT (arr :> api) m = TypeError (HasServerArrowKindError arr)
-- it doens't really matter what sub route we peak -- it doesn't really matter what sub route we peak
route _ _ _ = error "servant-server panic: impossible happened in HasServer (arr :> api)" route _ _ _ = error "servant-server panic: impossible happened in HasServer (arr :> api)"
hoistServerWithContext _ _ _ = id hoistServerWithContext _ _ _ = id

View file

@ -32,7 +32,7 @@ import Servant.Server.Internal.ServerError
-- * Basic Auth -- * Basic Auth
-- | servant-server's current implementation of basic authentication is not -- | servant-server's current implementation of basic authentication is not
-- immune to certian kinds of timing attacks. Decoding payloads does not take -- immune to certain kinds of timing attacks. Decoding payloads does not take
-- a fixed amount of time. -- a fixed amount of time.
-- | The result of authentication/authorization -- | The result of authentication/authorization

View file

@ -20,7 +20,7 @@ import GHC.TypeLits
-- --
-- If you are using combinators that require a non-empty 'Context' you have to -- If you are using combinators that require a non-empty 'Context' you have to
-- use 'Servant.Server.serveWithContext' and pass it a 'Context' that contains all -- use 'Servant.Server.serveWithContext' and pass it a 'Context' that contains all
-- the values your combinators need. A 'Context' is essentially a heterogenous -- the values your combinators need. A 'Context' is essentially a heterogeneous
-- list and accessing the elements is being done by type (see 'getContextEntry'). -- list and accessing the elements is being done by type (see 'getContextEntry').
-- The parameter of the type 'Context' is a type-level list reflecting the types -- The parameter of the type 'Context' is a type-level list reflecting the types
-- of the contained context entries. To create a 'Context' with entries, use the -- of the contained context entries. To create a 'Context' with entries, use the

View file

@ -268,5 +268,5 @@ runAction action env req respond k = runResourceT $
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Due to GHC issue <https://ghc.haskell.org/trac/ghc/ticket/2595 2595>, we cannot Due to GHC issue <https://ghc.haskell.org/trac/ghc/ticket/2595 2595>, we cannot
do the more succint thing - just update the records we actually change. do the more succinct thing - just update the records we actually change.
-} -}

View file

@ -24,7 +24,7 @@ import Servant.Server.Internal.ServerError
-- | Computations used in a 'Delayed' can depend on the -- | Computations used in a 'Delayed' can depend on the
-- incoming 'Request', may perform 'IO', and result in a -- incoming 'Request', may perform 'IO', and result in a
-- 'RouteResult', meaning they can either suceed, fail -- 'RouteResult', meaning they can either succeed, fail
-- (with the possibility to recover), or fail fatally. -- (with the possibility to recover), or fail fatally.
-- --
newtype DelayedIO a = DelayedIO { runDelayedIO' :: ReaderT Request (ResourceT (RouteResultT IO)) a } newtype DelayedIO a = DelayedIO { runDelayedIO' :: ReaderT Request (ResourceT (RouteResultT IO)) a }

View file

@ -41,7 +41,7 @@
Some APIs need query parameters rewriting, e.g. in order to support Some APIs need query parameters rewriting, e.g. in order to support
for multiple casing (camel, snake, etc) or something to that effect. for multiple casing (camel, snake, etc) or something to that effect.
This could be easily achieved by using WAI Middleware and modyfing This could be easily achieved by using WAI Middleware and modifying
request's `Query`. But QueryParam, QueryParams and QueryFlag use request's `Query`. But QueryParam, QueryParams and QueryFlag use
`rawQueryString`. By using `queryString` rather then `rawQueryString` `rawQueryString`. By using `queryString` rather then `rawQueryString`
we can enable such rewritings. we can enable such rewritings.
@ -50,7 +50,7 @@
We used `build-type: Custom`, but it's problematic e.g. We used `build-type: Custom`, but it's problematic e.g.
for cross-compiling. The benefit is small, as the doctests for cross-compiling. The benefit is small, as the doctests
can be run other ways too (though not so conviniently). can be run other ways too (though not so conveniently).
- *servant* Remove deprecated modules [1268#](https://github.com/haskell-servant/servant/pull/1268) - *servant* Remove deprecated modules [1268#](https://github.com/haskell-servant/servant/pull/1268)
@ -405,7 +405,7 @@
- *servant-client-core* Add `hoistClient` to `HasClient`. - *servant-client-core* Add `hoistClient` to `HasClient`.
Just like `hoistServer` allows us to change the monad in which request handlers Just like `hoistServer` allows us to change the monad in which request handlers
of a web application live in, we also have `hoistClient` for changing the monad of a web application live, we also have `hoistClient` for changing the monad
in which *client functions* live. in which *client functions* live.
Read [tutorial section for more information](https://docs.servant.dev/en/release-0.14/tutorial/Client.html#changing-the-monad-the-client-functions-live-in). Read [tutorial section for more information](https://docs.servant.dev/en/release-0.14/tutorial/Client.html#changing-the-monad-the-client-functions-live-in).
([#936](https://github.com/haskell-servant/servant/pull/936)) ([#936](https://github.com/haskell-servant/servant/pull/936))
@ -612,7 +612,7 @@
`enter` isn't exported from `Servant` module anymore. You can change `enter` isn't exported from `Servant` module anymore. You can change
`enter` to `hoistServer` in a straight forward way. `enter` to `hoistServer` in a straight forward way.
Unwrap natural transformation and add a api type `Proxy`: Unwrap natural transformation and add an api type `Proxy`:
```diff ```diff
-server = enter (NT nt) impl -server = enter (NT nt) impl

View file

@ -157,7 +157,7 @@ test-suite spec
, text , text
, transformers , transformers
-- Additonal dependencies -- Additional dependencies
build-depends: build-depends:
hspec >= 2.6.0 && < 2.8 hspec >= 2.6.0 && < 2.8
, QuickCheck >= 2.12.6.1 && < 2.15 , QuickCheck >= 2.12.6.1 && < 2.15

View file

@ -95,7 +95,7 @@ type family HeaderValMap (f :: * -> *) (xs :: [*]) where
class BuildHeadersTo hs where class BuildHeadersTo hs where
buildHeadersTo :: [HTTP.Header] -> HList hs buildHeadersTo :: [HTTP.Header] -> HList hs
-- ^ Note: if there are multiple occurences of a header in the argument, -- ^ Note: if there are multiple occurrences of a header in the argument,
-- the values are interspersed with commas before deserialization (see -- the values are interspersed with commas before deserialization (see
-- <http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 RFC2616 Sec 4.2>) -- <http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 RFC2616 Sec 4.2>)

View file

@ -54,7 +54,7 @@
-- >>> toUrlPiece $ safeLink api without -- >>> toUrlPiece $ safeLink api without
-- "bye" -- "bye"
-- --
-- If you would like create a helper for generating links only within that API, -- If you would like to create a helper for generating links only within that API,
-- you can partially apply safeLink if you specify a correct type signature -- you can partially apply safeLink if you specify a correct type signature
-- like so: -- like so:
-- --
@ -65,7 +65,7 @@
-- >>> apiLink = safeLink api -- >>> apiLink = safeLink api
-- >>> :} -- >>> :}
-- --
-- `safeLink'` allows to make specialise the output: -- `safeLink'` allows you to specialise the output:
-- --
-- >>> safeLink' toUrlPiece api without -- >>> safeLink' toUrlPiece api without
-- "bye" -- "bye"
@ -563,7 +563,7 @@ instance HasLink sub => HasLink (AuthProtect tag :> sub) where
type MkLink (AuthProtect tag :> sub) a = MkLink sub a type MkLink (AuthProtect tag :> sub) a = MkLink sub a
toLink = simpleToLink (Proxy :: Proxy sub) toLink = simpleToLink (Proxy :: Proxy sub)
-- | Helper for implemneting 'toLink' for combinators not affecting link -- | Helper for implementing 'toLink' for combinators not affecting link
-- structure. -- structure.
simpleToLink simpleToLink
:: forall sub a combinator. :: forall sub a combinator.