servant-server 0.13.0.1 → 0.14
raw patch · 6 files changed
+174/−110 lines, 6 filesdep −attoparsecdep −parsecdep −splitdep ~QuickCheckdep ~aesondep ~base-compatPVP ok
version bump matches the API change (PVP)
Dependencies removed: attoparsec, parsec, split, system-filepath
Dependency ranges changed: QuickCheck, aeson, base-compat, doctest, exceptions, hspec, hspec-wai, http-api-data, http-media, http-types, monad-control, network, resourcet, safe, semigroups, servant, temporary, transformers-compat, warp
API changes (from Hackage documentation)
- Servant.Server.Internal: instance forall k1 ctype a (method :: k1) framing (f :: * -> *) (context :: [*]). (Servant.API.ContentTypes.MimeRender ctype a, Servant.API.Verbs.ReflectMethod method, Servant.API.Stream.FramingRender framing ctype, Servant.API.Stream.ToStreamGenerator f a) => Servant.Server.Internal.HasServer (Servant.API.Stream.Stream method framing ctype (f a)) context
- Servant.Server.Internal: instance forall k1 ctype a (method :: k1) framing (f :: * -> *) (h :: [*]) (context :: [*]). (Servant.API.ContentTypes.MimeRender ctype a, Servant.API.Verbs.ReflectMethod method, Servant.API.Stream.FramingRender framing ctype, Servant.API.Stream.ToStreamGenerator f a, Servant.API.ResponseHeaders.GetHeaders (Servant.API.ResponseHeaders.Headers h (f a))) => Servant.Server.Internal.HasServer (Servant.API.Stream.Stream method framing ctype (Servant.API.ResponseHeaders.Headers h (f a))) context
+ Servant.Server.Internal: instance forall k1 ctype a (method :: k1) (status :: GHC.Types.Nat) framing b (context :: [*]). (Servant.API.ContentTypes.MimeRender ctype a, Servant.API.Verbs.ReflectMethod method, GHC.TypeNats.KnownNat status, Servant.API.Stream.FramingRender framing ctype, Servant.API.Stream.ToStreamGenerator b a) => Servant.Server.Internal.HasServer (Servant.API.Stream.Stream method status framing ctype b) context
+ Servant.Server.Internal: instance forall k1 ctype a (method :: k1) (status :: GHC.Types.Nat) framing b (h :: [*]) (context :: [*]). (Servant.API.ContentTypes.MimeRender ctype a, Servant.API.Verbs.ReflectMethod method, GHC.TypeNats.KnownNat status, Servant.API.Stream.FramingRender framing ctype, Servant.API.Stream.ToStreamGenerator b a, Servant.API.ResponseHeaders.GetHeaders (Servant.API.ResponseHeaders.Headers h b)) => Servant.Server.Internal.HasServer (Servant.API.Stream.Stream method status framing ctype (Servant.API.ResponseHeaders.Headers h b)) context
- Servant.Server.Internal: streamRouter :: (MimeRender ctype a, FramingRender framing ctype, ToStreamGenerator f a) => (b -> ([(HeaderName, ByteString)], f a)) -> Method -> Proxy framing -> Proxy ctype -> Delayed env (Handler b) -> Router env
+ Servant.Server.Internal: streamRouter :: (MimeRender ctype a, FramingRender framing ctype, ToStreamGenerator b a) => (c -> ([(HeaderName, ByteString)], b)) -> Method -> Status -> Proxy framing -> Proxy ctype -> Delayed env (Handler c) -> Router env
- Servant.Utils.StaticFiles: serveDirectory :: FilePath -> Server Raw
+ Servant.Utils.StaticFiles: serveDirectory :: FilePath -> ServerT Raw m
- Servant.Utils.StaticFiles: serveDirectoryEmbedded :: [(FilePath, ByteString)] -> Server Raw
+ Servant.Utils.StaticFiles: serveDirectoryEmbedded :: [(FilePath, ByteString)] -> ServerT Raw m
- Servant.Utils.StaticFiles: serveDirectoryFileServer :: FilePath -> Server Raw
+ Servant.Utils.StaticFiles: serveDirectoryFileServer :: FilePath -> ServerT Raw m
- Servant.Utils.StaticFiles: serveDirectoryWebApp :: FilePath -> Server Raw
+ Servant.Utils.StaticFiles: serveDirectoryWebApp :: FilePath -> ServerT Raw m
- Servant.Utils.StaticFiles: serveDirectoryWebAppLookup :: ETagLookup -> FilePath -> Server Raw
+ Servant.Utils.StaticFiles: serveDirectoryWebAppLookup :: ETagLookup -> FilePath -> ServerT Raw m
- Servant.Utils.StaticFiles: serveDirectoryWith :: StaticSettings -> Server Raw
+ Servant.Utils.StaticFiles: serveDirectoryWith :: StaticSettings -> ServerT Raw m
Files
- CHANGELOG.md +46/−0
- servant-server.cabal +30/−38
- src/Servant/Server/Internal.hs +20/−17
- src/Servant/Utils/StaticFiles.hs +7/−7
- test/Servant/Server/ErrorSpec.hs +11/−2
- test/Servant/ServerSpec.hs +60/−46
CHANGELOG.md view
@@ -1,6 +1,52 @@ [The latest version of this document is on GitHub.](https://github.com/haskell-servant/servant/blob/master/servant-server/CHANGELOG.md) [Changelog for `servant` package contains significant entries for all core packages.](https://github.com/haskell-servant/servant/blob/master/servant/CHANGELOG.md) +0.14+----++- `Stream` takes a status code argument++ ```diff+ -Stream method framing ctype a+ +Stream method status framing ctype a+ ```++ ([#966](https://github.com/haskell-servant/servant/pull/966)+ [#972](https://github.com/haskell-servant/servant/pull/972))++- `ToStreamGenerator` definition changed, so it's possible to write an instance+ for conduits.++ ```diff+ -class ToStreamGenerator f a where+ - toStreamGenerator :: f a -> StreamGenerator a+ +class ToStreamGenerator a b | a -> b where+ + toStreamGenerator :: a -> StreamGenerator b+ ```++ ([#959](https://github.com/haskell-servant/servant/pull/959))++- Added `NoFraming` streaming strategy+ ([#959](https://github.com/haskell-servant/servant/pull/959))++- *servant-server* File serving in polymorphic monad.+ i.e. Generalised types of `serveDirectoryFileServer` etc functions in+ `Servant.Utils.StaticFiles`+ ([#953](https://github.com/haskell-servant/servant/pull/953))++- *servant-server* `ReqBody` content type check is recoverable.+ This allows writing APIs like:++ ```haskell+ 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](https://github.com/haskell-servant/servant/pull/937))++ 0.13.0.1 --------
servant-server.cabal view
@@ -1,5 +1,5 @@ name: servant-server-version: 0.13.0.1+version: 0.14 synopsis: A family of combinators for defining webservices APIs and serving them description: A family of combinators for defining webservices APIs and serving them@@ -22,11 +22,11 @@ build-type: Custom cabal-version: >=1.10 tested-with:- GHC==7.8.4,- GHC==7.10.3,- GHC==8.0.2,- GHC==8.2.2,- GHC==8.4.1+ GHC==7.8.4+ GHC==7.10.3+ GHC==8.0.2+ GHC==8.2.2+ GHC==8.4.3 extra-source-files: include/*.h CHANGELOG.md@@ -40,7 +40,7 @@ setup-depends: base >= 4 && <5, Cabal,- cabal-doctest >= 1.0.1 && <1.1+ cabal-doctest >= 1.0.6 && <1.1 library exposed-modules:@@ -71,37 +71,31 @@ if !impl(ghc >= 8.0) build-depends:- semigroups >= 0.18.3 && < 0.19+ semigroups >= 0.18.4 && < 0.19 -- Servant dependencies build-depends:- servant == 0.13.*+ servant == 0.14.* -- Other dependencies: Lower bound around what is in the latest Stackage LTS. -- Here can be exceptions if we really need features from the newer versions. build-depends:- aeson >= 1.2.3.0 && < 1.4- , base-compat >= 0.9.3 && < 0.11- , attoparsec >= 0.13.2.0 && < 0.14+ base-compat >= 0.10.1 && < 0.11 , base64-bytestring >= 1.0.0.1 && < 1.1- , exceptions >= 0.8.3 && < 0.11- , http-api-data >= 0.3.7.1 && < 0.4- , http-media >= 0.7.0 && < 0.8- , http-types >= 0.12 && < 0.13+ , exceptions >= 0.10.0 && < 0.11+ , http-api-data >= 0.3.8.1 && < 0.4+ , http-media >= 0.7.1.2 && < 0.8+ , http-types >= 0.12.1 && < 0.13 , network-uri >= 2.6.1.0 && < 2.7- , monad-control >= 1.0.0.4 && < 1.1- , network >= 2.6.3.2 && < 2.7- , safe >= 0.3.15 && < 0.4- , split >= 0.2.3.2 && < 0.3+ , monad-control >= 1.0.2.3 && < 1.1+ , network >= 2.6.3.5 && < 2.8 , string-conversions >= 0.4.0.1 && < 0.5- , system-filepath >= 0.4 && < 0.5- , resourcet >= 1.1.9 && < 1.3+ , resourcet >= 1.1.11 && < 1.3 , tagged >= 0.8.5 && < 0.9 , transformers-base >= 0.4.4 && < 0.5- , transformers-compat >= 0.5.1 && < 0.7+ , transformers-compat >= 0.6.2 && < 0.7 , wai >= 3.2.1.1 && < 3.3 , wai-app-static >= 3.1.6.1 && < 3.2- , warp >= 3.2.13 && < 3.3 , word8 >= 0.1.3 && < 0.2 hs-source-dirs: src@@ -120,11 +114,13 @@ base , servant , servant-server- , aeson- , warp , wai , text + build-depends:+ aeson >= 1.3.1.1 && < 1.5+ , warp >= 3.2.13 && < 3.3+ test-suite spec type: exitcode-stdio-1.0 ghc-options: -Wall@@ -148,13 +144,10 @@ build-depends: base , base-compat- , aeson , base64-bytestring , bytestring- , exceptions , http-types , mtl- , network , resourcet , safe , servant@@ -164,27 +157,26 @@ , transformers , transformers-compat , wai- , warp -- Additonal dependencies build-depends:- directory >= 1.2.1.0 && < 1.4- , hspec >= 2.4.4 && < 2.6- , hspec-wai >= 0.9 && < 0.10+ aeson >= 1.3.1.1 && < 1.5+ , directory >= 1.2.1.0 && < 1.4+ , hspec >= 2.5.1 && < 2.6+ , hspec-wai >= 0.9.0 && < 0.10+ , QuickCheck >= 2.11.3 && < 2.12 , should-not-typecheck >= 2.1.0 && < 2.2- , parsec >= 3.1.11 && < 3.2- , QuickCheck >= 2.10.1 && < 2.12+ , temporary >= 1.3 && < 1.4 , wai-extra >= 3.0.21.0 && < 3.1- , temporary >= 1.2.0.3 && < 1.4 build-tool-depends:- hspec-discover:hspec-discover >=2.4.4 && <2.6+ hspec-discover:hspec-discover >= 2.5.1 && <2.6 test-suite doctests build-depends: base , servant-server- , doctest >= 0.13.0 && <0.16+ , doctest >= 0.15.0 && <0.16 type: exitcode-stdio-1.0 main-is: test/doctests.hs buildable: True
src/Servant/Server/Internal.hs view
@@ -283,37 +283,40 @@ instance OVERLAPPABLE_- ( MimeRender ctype a, ReflectMethod method,- FramingRender framing ctype, ToStreamGenerator f a- ) => HasServer (Stream method framing ctype (f a)) context where+ ( MimeRender ctype a, ReflectMethod method, KnownNat status,+ FramingRender framing ctype, ToStreamGenerator b a+ ) => HasServer (Stream method status framing ctype b) context where - type ServerT (Stream method framing ctype (f a)) m = m (f a)+ type ServerT (Stream method status framing ctype b) m = m b hoistServerWithContext _ _ nt s = nt s - route Proxy _ = streamRouter ([],) method (Proxy :: Proxy framing) (Proxy :: Proxy ctype)+ route Proxy _ = streamRouter ([],) method status (Proxy :: Proxy framing) (Proxy :: Proxy ctype) where method = reflectMethod (Proxy :: Proxy method)+ status = toEnum . fromInteger $ natVal (Proxy :: Proxy status) instance OVERLAPPING_- ( MimeRender ctype a, ReflectMethod method,- FramingRender framing ctype, ToStreamGenerator f a,- GetHeaders (Headers h (f a))- ) => HasServer (Stream method framing ctype (Headers h (f a))) context where+ ( MimeRender ctype a, ReflectMethod method, KnownNat status,+ FramingRender framing ctype, ToStreamGenerator b a,+ GetHeaders (Headers h b)+ ) => HasServer (Stream method status framing ctype (Headers h b)) context where - type ServerT (Stream method framing ctype (Headers h (f a))) m = m (Headers h (f a))+ type ServerT (Stream method status framing ctype (Headers h b)) m = m (Headers h b) hoistServerWithContext _ _ nt s = nt s - route Proxy _ = streamRouter (\x -> (getHeaders x, getResponse x)) method (Proxy :: Proxy framing) (Proxy :: Proxy ctype)+ route Proxy _ = streamRouter (\x -> (getHeaders x, getResponse x)) method status (Proxy :: Proxy framing) (Proxy :: Proxy ctype) where method = reflectMethod (Proxy :: Proxy method)+ status = toEnum . fromInteger $ natVal (Proxy :: Proxy status) -streamRouter :: (MimeRender ctype a, FramingRender framing ctype, ToStreamGenerator f a) =>- (b -> ([(HeaderName, B.ByteString)], f a))+streamRouter :: (MimeRender ctype a, FramingRender framing ctype, ToStreamGenerator b a) =>+ (c -> ([(HeaderName, B.ByteString)], b)) -> Method+ -> Status -> Proxy framing -> Proxy ctype- -> Delayed env (Handler b)+ -> Delayed env (Handler c) -> Router env-streamRouter splitHeaders method framingproxy ctypeproxy action = leafRouter $ \env request respond ->+streamRouter splitHeaders method status framingproxy ctypeproxy action = leafRouter $ \env request respond -> let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request cmediatype = NHM.matchAccept [contentType ctypeproxy] accH accCheck = when (isNothing cmediatype) $ delayedFail err406@@ -323,7 +326,7 @@ ) env request respond $ \ output -> let (headers, fa) = splitHeaders output k = getStreamGenerator . toStreamGenerator $ fa in- Route $ responseStream status200 (contentHeader : headers) $ \write flush -> do+ Route $ responseStream status (contentHeader : headers) $ \write flush -> do write . BB.lazyByteString $ header framingproxy ctypeproxy case boundary framingproxy ctypeproxy of BoundaryStrategyBracket f ->@@ -604,7 +607,7 @@ let contentTypeH = fromMaybe "application/octet-stream" $ lookup hContentType $ requestHeaders request case canHandleCTypeH (Proxy :: Proxy list) (cs contentTypeH) :: Maybe (BL.ByteString -> Either String a) of- Nothing -> delayedFailFatal err415+ Nothing -> delayedFail err415 Just f -> return f -- Body check, we get a body parsing functions as the first argument.
src/Servant/Utils/StaticFiles.hs view
@@ -18,7 +18,7 @@ import Data.ByteString (ByteString) import Network.Wai.Application.Static import Servant.API.Raw (Raw)-import Servant.Server (Server, Tagged (..))+import Servant.Server (ServerT, Tagged (..)) import System.FilePath (addTrailingPathSeparator) #if !MIN_VERSION_wai_app_static(3,1,0) import Filesystem.Path.CurrentOS (decodeString)@@ -47,33 +47,33 @@ -- in order. -- -- Corresponds to the `defaultWebAppSettings` `StaticSettings` value.-serveDirectoryWebApp :: FilePath -> Server Raw+serveDirectoryWebApp :: FilePath -> ServerT Raw m serveDirectoryWebApp = serveDirectoryWith . defaultWebAppSettings . fixPath -- | Same as 'serveDirectoryWebApp', but uses `defaultFileServerSettings`.-serveDirectoryFileServer :: FilePath -> Server Raw+serveDirectoryFileServer :: FilePath -> ServerT Raw m serveDirectoryFileServer = serveDirectoryWith . defaultFileServerSettings . fixPath -- | Same as 'serveDirectoryWebApp', but uses 'webAppSettingsWithLookup'.-serveDirectoryWebAppLookup :: ETagLookup -> FilePath -> Server Raw+serveDirectoryWebAppLookup :: ETagLookup -> FilePath -> ServerT Raw m serveDirectoryWebAppLookup etag = serveDirectoryWith . flip webAppSettingsWithLookup etag . fixPath -- | Uses 'embeddedSettings'.-serveDirectoryEmbedded :: [(FilePath, ByteString)] -> Server Raw+serveDirectoryEmbedded :: [(FilePath, ByteString)] -> ServerT Raw m serveDirectoryEmbedded files = serveDirectoryWith (embeddedSettings files) -- | Alias for 'staticApp'. Lets you serve a directory -- with arbitrary 'StaticSettings'. Useful when you want -- particular settings not covered by the four other -- variants. This is the most flexible method.-serveDirectoryWith :: StaticSettings -> Server Raw+serveDirectoryWith :: StaticSettings -> ServerT Raw m serveDirectoryWith = Tagged . staticApp -- | Same as 'serveDirectoryFileServer'. It used to be the only -- file serving function in servant pre-0.10 and will be kept -- around for a few versions, but is deprecated.-serveDirectory :: FilePath -> Server Raw+serveDirectory :: FilePath -> ServerT Raw m serveDirectory = serveDirectoryFileServer {-# DEPRECATED serveDirectory "Use serveDirectoryFileServer instead" #-}
test/Servant/Server/ErrorSpec.hs view
@@ -247,6 +247,8 @@ :<|> "path3" :> ReqBody '[JSON] Int :> Post '[PlainText] Int -- 3 :<|> "path4" :> (ReqBody '[PlainText] Int :> Post '[PlainText] Int -- 4 :<|> ReqBody '[PlainText] Int :> Post '[JSON] Int) -- 5+ :<|> "path5" :> (ReqBody '[JSON] Int :> Post '[PlainText] Int -- 6+ :<|> ReqBody '[PlainText] Int :> Post '[PlainText] Int) -- 7 errorChoiceApi :: Proxy ErrorChoiceApi errorChoiceApi = Proxy@@ -256,8 +258,8 @@ :<|> return 1 :<|> return 2 :<|> (\_ -> return 3)- :<|> (\_ -> return 4)- :<|> (\_ -> return 5)+ :<|> ((\_ -> return 4) :<|> (\_ -> return 5))+ :<|> ((\_ -> return 6) :<|> (\_ -> return 7)) errorChoiceSpec :: Spec@@ -278,6 +280,13 @@ request methodPost "path4" [(hContentType, "text/plain;charset=utf-8"), (hAccept, "blah")] "5" `shouldRespondWith` 406+ it "should respond with 415 only if none of the subservers supports the request's content type" $ do+ request methodPost "path5" [(hContentType, "text/plain;charset=utf-8")] "1"+ `shouldRespondWith` 200+ request methodPost "path5" [(hContentType, "application/json")] "1"+ `shouldRespondWith` 200+ request methodPost "path5" [(hContentType, "application/not-supported")] ""+ `shouldRespondWith` 415 -- }}}
test/Servant/ServerSpec.hs view
@@ -17,57 +17,62 @@ module Servant.ServerSpec where -import Control.Monad (forM_, when, unless)-import Control.Monad.Error.Class (MonadError (..))-import Data.Aeson (FromJSON, ToJSON, decode', encode)-import qualified Data.ByteString.Base64 as Base64-import Data.Char (toUpper)+import Control.Monad+ (forM_, unless, when)+import Control.Monad.Error.Class+ (MonadError (..))+import Data.Aeson+ (FromJSON, ToJSON, decode', encode)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Base64 as Base64+import Data.Char+ (toUpper) import Data.Monoid-import Data.Proxy (Proxy (Proxy))-import Data.String (fromString)-import Data.String.Conversions (cs)-import qualified Data.Text as T-import GHC.Generics (Generic)-import Network.HTTP.Types (Status (..), hAccept, hContentType,- methodDelete, methodGet,- methodHead, methodPatch,- methodPost, methodPut, ok200,- imATeapot418,- parseQuery)-import Network.Wai (Application, Request, requestHeaders, pathInfo,- queryString, rawQueryString,- responseLBS)-import Network.Wai.Test (defaultRequest, request,- runSession, simpleBody,- simpleHeaders, simpleStatus)-import Servant.API ((:<|>) (..), (:>), AuthProtect,- BasicAuth, BasicAuthData(BasicAuthData),- Capture, CaptureAll, Delete, Get, Header,- Headers, HttpVersion,- IsSecure (..), JSON,- NoContent (..), Patch, PlainText,- Post, Put, EmptyAPI,- QueryFlag, QueryParam, QueryParams,- Raw, RemoteHost, ReqBody,- StdMethod (..), Verb, addHeader)+import Data.Proxy+ (Proxy (Proxy))+import Data.String+ (fromString)+import Data.String.Conversions+ (cs)+import qualified Data.Text as T+import GHC.Generics+ (Generic)+import Network.HTTP.Types+ (Status (..), hAccept, hContentType, imATeapot418,+ methodDelete, methodGet, methodHead, methodPatch, methodPost,+ methodPut, ok200, parseQuery)+import Network.Wai+ (Application, Request, pathInfo, queryString, rawQueryString,+ requestHeaders, responseLBS)+import Network.Wai.Test+ (defaultRequest, request, runSession, simpleBody,+ simpleHeaders, simpleStatus)+import Servant.API+ ((:<|>) (..), (:>), AuthProtect, BasicAuth,+ BasicAuthData (BasicAuthData), Capture, CaptureAll, Delete,+ EmptyAPI, Get, Header, Headers, HttpVersion, IsSecure (..),+ JSON, NoContent (..), NoFraming, OctetStream, Patch,+ PlainText, Post, Put, QueryFlag, QueryParam, QueryParams, Raw,+ RemoteHost, ReqBody, StdMethod (..), Stream,+ StreamGenerator (..), Verb, addHeader) import Servant.API.Internal.Test.ComprehensiveAPI-import Servant.Server (Server, Handler, Tagged (..), err401, err403,- err404, serve, serveWithContext,- Context((:.), EmptyContext), emptyServer)-import Test.Hspec (Spec, context, describe, it,- shouldBe, shouldContain)-import qualified Test.Hspec.Wai as THW-import Test.Hspec.Wai (get, liftIO, matchHeaders,- matchStatus, shouldRespondWith,- with, (<:>))+import Servant.Server+ (Context ((:.), EmptyContext), Handler, Server, Tagged (..),+ emptyServer, err401, err403, err404, serve, serveWithContext)+import Test.Hspec+ (Spec, context, describe, it, shouldBe, shouldContain)+import Test.Hspec.Wai+ (get, liftIO, matchHeaders, matchStatus, shouldRespondWith,+ with, (<:>))+import qualified Test.Hspec.Wai as THW -import Servant.Server.Internal.BasicAuth (BasicAuthCheck(BasicAuthCheck),- BasicAuthResult(Authorized,Unauthorized)) import Servant.Server.Experimental.Auth- (AuthHandler, AuthServerData,- mkAuthHandler)+ (AuthHandler, AuthServerData, mkAuthHandler)+import Servant.Server.Internal.BasicAuth+ (BasicAuthCheck (BasicAuthCheck),+ BasicAuthResult (Authorized, Unauthorized)) import Servant.Server.Internal.Context- (NamedContext(..))+ (NamedContext (..)) -- * comprehensive api test @@ -83,6 +88,7 @@ spec = do verbSpec captureSpec+ captureAllSpec queryParamSpec reqBodySpec headerSpec@@ -105,6 +111,7 @@ :<|> "accept" :> ( Verb method status '[JSON] Person :<|> Verb method status '[PlainText] String )+ :<|> "stream" :> Stream method status NoFraming OctetStream (StreamGenerator BS.ByteString) verbSpec :: Spec verbSpec = describe "Servant.API.Verb" $ do@@ -114,6 +121,8 @@ :<|> return (addHeader 5 alice) :<|> return (addHeader 10 NoContent) :<|> (return alice :<|> return "B")+ :<|> return (StreamGenerator $ \f _ -> f "bytestring")+ get200 = Proxy :: Proxy (VerbApi 'GET 200) post210 = Proxy :: Proxy (VerbApi 'POST 210) put203 = Proxy :: Proxy (VerbApi 'PUT 203)@@ -178,6 +187,11 @@ response <- THW.request method "" [] "" liftIO $ simpleHeaders response `shouldContain` [("Content-Type", "application/json;charset=utf-8")]++ it "works for Stream as for Result" $ do+ response <- THW.request method "/stream" [] ""+ liftIO $ statusCode (simpleStatus response) `shouldBe` status+ liftIO $ simpleBody response `shouldBe` "bytestring" test "GET 200" get200 methodGet 200 test "POST 210" post210 methodPost 210