A family of combinators for defining webservices APIs and serving them . You can learn about the basics in the tutorial. . CHANGELOG

Changes

The latest version of this document is on GitHub.

Package versions follow the Package Versioning Policy: in A.B.C, bumps to either A or B represent major versions.

0.20.2

  • Full query string helpers #1604

    This PR introduces DeepQuery, a route combinator that implements a pattern commonly known as deep objects. It builds upon the convention of using [] for a list of parameters: books?filter[search]=value&filter[author][name]=value. The corresponding type would be DeepQuery "filter" BookQuery :> Get '[JSON] [Book].

  • Add IsIn instance for NamedRoutes #1707

  • Renamed AtLeastOneFragment type class to AtMostOneFragment #1727

    The previously named AtLeastOneFragment type class defined in the Servant.API.TypeLevel module has been renamed to AtMostOneFragment, since the previous name was misleading.

  • Use Header' in response headers. #1697

    Use Header' instead of Header in response, so it’s possible to provide Description, for example:

    type PaginationTotalCountHeader =
      Header'
        '[ Description "Indicates to the client total count of items in collection"
         , Optional
         , Strict
         ]
        "Total-Count"
        Int
    

    Note: if you want to add header with description you should use addHeader' or noHeader' which accepts Header' with all modifiers.

0.20.1

  • Support aeson-2.2 #1695

0.20

  • Headers support in UVerb responses #1570 #1571

  • Generalize type of Servant.Types.SourceT.source to any foldable #1593

  • Make Mime(Un)Render PlainText String instances encode/decode UTF-8 #1645

  • Add HasStatus instance for Headers (that defers StatusOf to underlying value) #1649

  • Make fromSourceIO run in IO #1661

    Some streaming abstractions, like io-streams, require stateful initialization. Since all actual call sites of fromSourceIO are in a context where IO actions can be executed, these streaming sources can be accomodated by having letting fromSourceIO run in IO.

    To migrate your existing FromSourceIO instance, simply put a pure/return in front of it.

  • Fix the handling of multiple headers with the same name. #1666

0.19.1

Compatibility with GHC 9.4, see PR #1592.

0.19

Significant changes

  • Drop support for GHC < 8.6.

  • Support GHC 9.0 (GHC 9.2 should work as well, but isn’t fully tested yet).

  • Support Aeson 2 (#1475), which fixes a DOS vulnerability related to hash collisions.

  • Add NamedRoutes combinator, making support for records first-class in Servant (#1388).

    Users can now directly mark part as an API as defined by a record, instead of using (:<|>) to combine routes. Concretely, the anonymous:

    type API = 
      "version" :> Get '[JSON] String :<|>
      "products" :> Get '[JSON] [Product]
    

    can be replaced with the explicitly-named:

    type API = NamedRoutes NamedAPI
    data NamedAPI mode = NamedAPI
      { version :: mode :- "version" :> Get '[JSON] String
      , products :: mode :- "products" :> Get '[JSON] [Product]
      }
    

    NamedRoutes builds upon servant-generic, but improves usability by freeing users from the need to perform toServant / fromServant conversions manually. Serving NamedRoutes NamedAPI is now done directly by providing a record of handlers, and servant generates clients directly as records as well. In particular, it makes it much more practical to work with nested hierarchies of named routes.

    Two convenience functions, (//) and (/:), have been added to make the usage of named route hierarchies more pleasant:

    rootClient :: RootApi (AsClientT ClientM)
    rootClient = client (Proxy @API)
    
    helloClient :: String -> ClientM String
    helloClient name = rootClient // hello /: name
    
    endpointClient :: ClientM Person
    endpointClient = rootClient // subApi /: "foobar123" // endpoint
    
    type Api = NamedRoutes RootApi
    
    data RootApi mode = RootApi
      { subApi :: mode :- Capture "token" String :> NamedRoutes SubApi
      , hello :: mode :- Capture "name" String :> Get '[JSON] String
      , …
      } deriving Generic
    
    data SubApi mode = SubApi
      { endpoint :: mode :- Get '[JSON] Person
      , …
      } deriving Generic
    
  • Add custom type errors for partially applied combinators (#1289, #1486).

    For example, forgetting to document the expected type for a query parameter, as in:

    type API = QueryParam "param" :> Get '[JSON] NoContent
    

    will raise to the following error when trying to serve the API:

      • There is no instance for HasServer (QueryParam'
                                              '[Optional, Strict] "param" :> ...)
        QueryParam' '[Optional, Strict] "1" expects 1 more arguments
    

    As a consequence of this change, unsaturated types are now forbidden before (:>).

  • Add a HeadNoContent verb (#1502).

  • servant-client / servant-client-core / servant-http-streams: Fix erroneous behavior, where only 2XX status codes would be considered successful, irrelevant of the status parameter specified by the verb combinator. (#1469)

  • servant-client / servant-client-core: Fix Show instance for Servant.Client.Core.Request.

  • servant-client / servant-client-core: Allow passing arbitrary binary data in Query parameters. (#1432).

  • servant-docs: Generate sample cURL requests (#1401).

    Breaking change: requires sample header values to be supplied with headers.

Other changes

  • Various bit rotten cookbooks have been updated and re-introduced on docs.servant.dev.

  • Various version bumps.

0.18.3

Significant changes

  • Add response header support to UVerb (#1420).
  • Use Capture Description if available (#1423).

Other changes

  • Support GHC-9.0.1.
  • Bump bytestring, attoparsec, hspec and singleton-bool dependencies.

0.18.2

Significant changes

  • Introduce Fragment combinator.
  • Fix MimeRender and MimeUnrender instances for WithStatus.

0.18.1

Significant changes

  • Union verbs

Other changes

  • Bump “tested-with” ghc versions
  • Allow newer dependencies

0.18

Significant changes

  • Support for ghc8.8 (#1318, #1326, #1327)

  • Configurable error messages for automatic errors thrown by servant, like “no route” or “could not parse json body” (#1312, #1326, #1327)

Other changes

  • Witness that a type-level natural number corresponds to a HTTP status code (#1310)

  • Improve haddocs (#1279)

  • Dependency management (#1269, #1293, #1286, #1287)

0.17

Significant changes

  • Add NoContentVerb #1028 #1219 #1228

    The NoContent API endpoints should now use NoContentVerb combinator. The API type changes are usually of the kind

    - :<|> PostNoContent '[JSON] NoContent
    + :<|> PostNoContent
    

    i.e. one doesn’t need to specify the content-type anymore. There is no content.

  • Capture can be Lenient #1155 #1156

    You can specify a lenient capture as

    :<|> "capture-lenient"  :> Capture' '[Lenient] "foo" Int :> GET
    

    which will make the capture always succeed. Handlers will be of the type Either String CapturedType, where Left err represents the possible parse failure.

  • servant-client Added a function to create Client.Request in ClientEnv #1213 #1255

    The new member makeClientRequest of ClientEnv is used to create http-client Request from servant-client-core Request. This functionality can be used for example to set dynamic timeouts for each request.

  • servant-server use queryString to parse QueryParam, QueryParams and QueryFlag #1249 #1262

    Some APIs need query parameters rewriting, e.g. in order to support for multiple casing (camel, snake, etc) or something to that effect.

    This could be easily achieved by using WAI Middleware and modifying request’s Query. But QueryParam, QueryParams and QueryFlag use rawQueryString. By using queryString rather then rawQueryString we can enable such rewritings.

  • servant servant-server Make packages build-type: Simple #1263

    We used build-type: Custom, but it’s problematic e.g. for cross-compiling. The benefit is small, as the doctests can be run other ways too (though not so conveniently).

  • servant Remove deprecated modules 1268#

    • Servant.Utils.Links is Servant.Links
    • Servant.API.Internal.Test.ComprehensiveAPI is Servant.Test.ComprehensiveAPI

Other changes

  • servant-client servant-client-core servant-http-streams Fix Verb with headers checking content type differently #1200 #1204

    For Verbs with response Headers, the implementation didn’t check for the content-type of the response. Now it does.

  • servant-docs Merge documentation from duplicate routes #1240 #1241

    Servant supports defining the same route multiple times with different content-types and result-types, but servant-docs was only documenting the first of copy of such duplicated routes. It now combines the documentation from all the copies.

    Unfortunately, it is not yet possible for the documentation to specify multiple status codes.

  • Add sponsorship button #1190

    Well-Typed is a consultancy which could help you with servant issues (See consultancies section on http://www.servant.dev/).

  • Try changelog-d for changelog management #1230

    Check the CONTRIBUTING.md for details

  • CI and testing tweaks. #1154 #1157 #1182 #1214 #1229 #1233 #1242 #1247 #1250 #1258

    We are experiencing some bitrotting of cookbook recipe dependencies, therefore some of them aren’t build as part of our CI anymore.

  • New cookbook recipes #1088 #1171 #1198

  • servant-jsaddle Progress on servant-jsaddle #1216

  • servant-docs Prevent race-conditions in testing #1194

  • servant-client servant-http-streams HasClient instance for Stream with Headers #1170 #1197

  • servant Remove unused extensions from cabal file #1201

  • servant-client Redact the authorization header in Show and exceptions #1238

  • Dependency upgrades #1173 #1181 #1183 #1188 #1224 #1245 #1257

  • Documentation updates #1162 #1174 #1175 #1234 #1244 #1247

0.16.2

  • singleton-bool-0.1.5 (SBool is re-exported)
    • Add discreteBool :: Dec (a :~: b) (GHC-7.8+)
    • Add Show, Eq, Ord SBool b instances.
  • dependencies update

0.16.1

  • Add Semigroup and Monoid SourceT instances #1158 #1159
  • Use http-api-data-0.4.1 #1181
  • Allow newer dependencies

0.16.0.1

  • Make tests work with http-media-0.8

0.16

Significant changes

  • Rename ServantError to ClientError, ServantErr to ServerError #1131

  • servant-client-core Rearrange modules. No more Internal modules, whole API is versioned. #1130

  • servant-http-streams New package #1117

  • servant-client-core RequestBody is now

    = RequestBodyLBS LBS.ByteString
    | RequestBodyBS BS.ByteString
    | RequestBodySource (SourceIO LBS.ByteString)
    

    i.e. no more replicates http-clients API. #1117

  • servant-client-core Keep structured exceptions in ConnectionError constructor of ClientError #1115

    -| ConnectionError Text
    +| ConnectionError SomeException
    
  • servant-client-core Preserve failing request in FailureResponse constructor of ClientError #1114

    -FailureResponse Response
    +-- | The server returned an error response including the
    +-- failing request. 'requestPath' includes the 'BaseUrl' and the
    +-- path of the request.
    +FailureResponse (RequestF () (BaseUrl, BS.ByteString)) Response
    
  • servant-client Fix (implement) StreamBody instance #1110

Other changes

  • servant-client Update CookieJar with intermediate request/responses (redirects) #1104

  • servant-server Reorder HTTP failure code priorities #1103

  • servant-server Re-organise internal modules #1139

  • Allow network-3.0 #1107

  • Add NFData NoContent instance #1090

  • Documentation updates #1127 #1124 #1098

  • CI updates #1123 #1121 #1119

0.15

Significant changes

  • Streaming refactoring. #991 #1076 #1077

    The streaming functionality (Servant.API.Stream) is refactored to use servant’s own SourceIO type (see Servant.Types.SourceT documentation), which replaces both StreamGenerator and ResultStream types.

    New conversion type-classes are ToSourceIO and FromSourceIO (replacing ToStreamGenerator and BuildFromStream). There are instances for conduit, pipes and machines in new packages: servant-conduit servant-pipes and servant-machines respectively.

    Writing new framing strategies is simpler. Check existing strategies for examples.

    This change shouldn’t affect you, if you don’t use streaming endpoints.

  • servant-client Separate streaming client. #1066

    We now have two http-client based clients, in Servant.Client and Servant.Client.Streaming.

    Their API is the same, except for

    • Servant.Client cannot request Stream endpoints.
    • Servant.Client is run by direct runClientM :: ClientM a -> ClientEnv -> IO (Either ServantError a)
    • Servant.Client.Streaming can request Stream endpoints.
    • Servant.Client.Streaming is used by CPSised withClientM :: ClientM a -> ClientEnv -> (Either ServantError a -> IO b) -> IO b

    To access Stream endpoints use Servant.Client.Streaming with withClientM; otherwise you can continue using Servant.Client with runClientM. You can use both too, ClientEnv and BaseUrl types are same for both.

    Note: Servant.Client.Streaming doesn’t stream non-Stream endpoints. Requesting ordinary Verb endpoints (e.g. Get) will block until the whole response is received.

    There is Servant.Client.Streaming.runClientM function, but it has restricted type. NFData a constraint prevents using it with SourceT, Conduit etc. response types.

    runClientM :: NFData a => ClientM a -> ClientEnv -> IO (Either ServantError a)
    

    This change shouldn’t affect you, if you don’t use streaming endpoints.

  • servant-client-core Related to the previous: streamingResponse is removed from RunClient. We have a new type-class:

    class RunClient m =>  RunStreamingClient m where
        withStreamingRequest :: Request -> (StreamingResponse -> IO a) ->  m a
    
  • Drop support for GHC older than 8.0 #1008 #1009

  • servant ComprehensiveAPI is a part of public API in Servant.Test.ComprehensiveAPI module. This API type is used to verify that libraries implement all core combinators. Now we won’t change this type between major versions. (This has been true for some time already). #1070

  • servant Remove Servant.Utils.Enter module (deprecated in servant-0.12 in favour of hoistServer) #996

  • servant-foreign Add support so HasForeign can be implemented for MultipartForm from servant-multipart #1035

Other changes

0.14.1

  • Merge in (and slightly refactor) servant-generic (by Patrick Chilton) into servant (Servant.API.Generic), servant-client-code (Servant.Client.Generic) and servant-server (Servant.Server.Generic).

  • Deprecate Servant.Utils.Links, use Servant.Links. #998

  • servant-server Deprecate Servant.Utils.StaticUtils, use Servant.Server.StaticUtils.

0.14

Significant changes

  • Stream takes a status code argument

    -Stream method        framing ctype a
    +Stream method status framing ctype a
    

    (#966 #972)

  • ToStreamGenerator definition changed, so it’s possible to write an instance for conduits.

    -class ToStreamGenerator f a where
    -   toStreamGenerator :: f a -> StreamGenerator a
    +class ToStreamGenerator a b | a -> b where
    +   toStreamGenerator :: a -> StreamGenerator b
    

    (#959)

  • Added NoFraming streaming strategy (#959)

  • servant-client-core Free Client implementation. Useful for testing HasClient instances. (#920)

  • servant-client-core Add hoistClient to HasClient. Just like hoistServer allows us to change the monad in which request handlers of a web application live, we also have hoistClient for changing the monad in which client functions live. Read tutorial section for more information. (#936)

    iF you have own combinators, you’ll need to define a new method of HasClient class, for example:

    type Client m (MyCombinator :> api) = MyValue :> Client m api
    hoistClientMonad pm _ nt cl = hoistClientMonad pm (Proxy :: Proxy api) nt . cl
    
  • servant Add safeLink' :: (Link -> a) -> ... -> MkLink endpoint a, which allows to create helpers returning something else than Link. (#968)

  • servant-server File serving in polymorphic monad. i.e. Generalised types of serveDirectoryFileServer etc functions in Servant.Utils.StaticFiles (#953)

  • servant-server ReqBody content type check is recoverable. This allows writing APIs like:

          ReqBody '[JSON] Int      :> Post '[PlainText] Int
    :<|>  ReqBody '[PlainText] Int :> Post '[PlainText] Int
    

    which is useful when handlers are subtly different, for example may do less work. (#937)

  • servant-client Add more constructors to RequestBody, including RequestBodyStream. Note: we are looking for http-library agnostic API, so the might change again soon. Tell us which constructors are useful for you! (#913)

Other changes

Note

(VIM) Regular-expression to link PR numbers: s/\v#(\d+)/[#\1](