on master help sign in
Don't ignore the content-type in ReqBody
40a941eTimo von Holtz
servant-client.cabal−1
@@ -50,7 +50,6 @@ library
50 , network-uri >= 2.6
50 , network-uri >= 2.6
51 , safe
51 , safe
52 , servant >= 0.2.2
52 , servant >= 0.2.2
53− , servant-server
54 , string-conversions
53 , string-conversions
55 , text
54 , text
56 , transformers
55 , transformers
src/Servant/Client.hs+5−4
@@ -26,8 +26,8 @@ import GHC.TypeLits
26import Network.HTTP.Media
26import Network.HTTP.Media
27import qualified Network.HTTP.Types as H
27import qualified Network.HTTP.Types as H
28import Servant.API
28import Servant.API
29+import Servant.API.ContentTypes
29import Servant.Common.BaseUrl
30import Servant.Common.BaseUrl
30−import Servant.Server.ContentTypes
31import Servant.Common.Req
31import Servant.Common.Req
32import Servant.Common.Text
32import Servant.Common.Text
33
33
@@ -438,15 +438,16 @@ instance HasClient Raw where
438-- > addBook :: Book -> BaseUrl -> EitherT String IO Book
438-- > addBook :: Book -> BaseUrl -> EitherT String IO Book
439-- > addBook = client myApi
439-- > addBook = client myApi
440-- > -- then you can just use "addBook" to query that endpoint
440-- > -- then you can just use "addBook" to query that endpoint
441−instance (ToJSON a, HasClient sublayout)
441+instance (MimeRender ct a, HasClient sublayout)
442 => HasClient (ReqBody (ct ': cts) a :> sublayout) where
442 => HasClient (ReqBody (ct ': cts) a :> sublayout) where
443
443
444 type Client (ReqBody (ct ': cts) a :> sublayout) =
444 type Client (ReqBody (ct ': cts) a :> sublayout) =
445 a -> Client sublayout
445 a -> Client sublayout
446
446
447 clientWithRoute Proxy req body =
447 clientWithRoute Proxy req body =
448− clientWithRoute (Proxy :: Proxy sublayout) $
448+ clientWithRoute (Proxy :: Proxy sublayout) $ do
449− setRQBody (encode body) ("application" // "json" /: ("charset", "utf-8")) req
449+ let ctProxy = Proxy :: Proxy ct
450+ setRQBody (toByteString ctProxy body) (contentType ctProxy) req
450
451
451-- | Make the querying function append @path@ to the request path.
452-- | Make the querying function append @path@ to the request path.
452instance (KnownSymbol path, HasClient sublayout) => HasClient (path :> sublayout) where
453instance (KnownSymbol path, HasClient sublayout) => HasClient (path :> sublayout) where
src/Servant/Common/Req.hs+3−10
@@ -24,9 +24,9 @@ import Network.HTTP.Client.TLS
24import Network.HTTP.Media
24import Network.HTTP.Media
25import Network.HTTP.Types
25import Network.HTTP.Types
26import Network.URI
26import Network.URI
27+import Servant.API.ContentTypes
27import Servant.Common.BaseUrl
28import Servant.Common.BaseUrl
28import Servant.Common.Text
29import Servant.Common.Text
29−import Servant.Server.ContentTypes
30import System.IO.Unsafe
30import System.IO.Unsafe
31
31
32import qualified Network.HTTP.Client as Client
32import qualified Network.HTTP.Client as Client
@@ -152,8 +152,8 @@ performRequestCT ct reqMethod req wantedStatus reqHost = do
152 performRequest reqMethod (req { reqAccept = [acceptCT] }) (== wantedStatus) reqHost
152 performRequest reqMethod (req { reqAccept = [acceptCT] }) (== wantedStatus) reqHost
153 unless (matches respCT (acceptCT)) $
153 unless (matches respCT (acceptCT)) $
154 left $ "requested Content-Type " <> show acceptCT <> ", but got " <> show respCT
154 left $ "requested Content-Type " <> show acceptCT <> ", but got " <> show respCT
155− maybe
155+ either
156− (left (displayHttpRequest reqMethod ++ " returned invalid response of type: " ++ show respCT))
156+ (left . ((displayHttpRequest reqMethod ++ " returned invalid response of type" ++ show respCT) ++))
157 return
157 return
158 (fromByteString ct respBody)
158 (fromByteString ct respBody)
159
159
@@ -164,10 +164,3 @@ catchStatusCodeException action =
164 case e of
164 case e of
165 Client.StatusCodeException status _ _ -> return $ Left status
165 Client.StatusCodeException status _ _ -> return $ Left status
166 exc -> throwIO exc
166 exc -> throwIO exc
167−
168−-- | Like 'Data.Aeson.decode' but allows all JSON values instead of just
169−-- objects and arrays.
170−decodeLenient :: FromJSON a => ByteString -> Either String a
171−decodeLenient input = do
172− v :: Value <- parseOnly (Data.Aeson.Parser.value <* endOfInput) (cs input)
173− parseEither parseJSON v