Expose content type in response.

This commit is contained in:
Timo von Holtz 2015-02-17 10:32:15 +11:00
parent 7a1eac4e86
commit db2c5a42b2
4 changed files with 16 additions and 10 deletions

View file

@ -71,6 +71,7 @@ test-suite spec
, deepseq , deepseq
, either , either
, hspec == 2.* , hspec == 2.*
, http-media
, http-types , http-types
, network >= 2.6 , network >= 2.6
, QuickCheck >= 2.7 , QuickCheck >= 2.7

View file

@ -412,7 +412,7 @@ instance (KnownSymbol sym, HasClient sublayout)
-- | Pick a 'Method' and specify where the server you want to query is. You get -- | Pick a 'Method' and specify where the server you want to query is. You get
-- back the status code and the response body as a 'ByteString'. -- back the status code and the response body as a 'ByteString'.
instance HasClient Raw where instance HasClient Raw where
type Client Raw = H.Method -> BaseUrl -> EitherT String IO (Int, ByteString) type Client Raw = H.Method -> BaseUrl -> EitherT String IO (Int, ByteString, MediaType)
clientWithRoute :: Proxy Raw -> Req -> Client Raw clientWithRoute :: Proxy Raw -> Req -> Client Raw
clientWithRoute Proxy req httpMethod host = clientWithRoute Proxy req httpMethod host =

View file

@ -14,7 +14,6 @@ import Data.Aeson.Parser
import Data.Aeson.Types import Data.Aeson.Types
import Data.Attoparsec.ByteString import Data.Attoparsec.ByteString
import Data.ByteString.Lazy hiding (pack) import Data.ByteString.Lazy hiding (pack)
import qualified Data.ByteString.Char8 as BS
import Data.String import Data.String
import Data.String.Conversions import Data.String.Conversions
import Data.Text import Data.Text
@ -85,7 +84,7 @@ reqToRequest req (BaseUrl reqScheme reqHost reqPort) =
setrqb r = case (reqBody req) of setrqb r = case (reqBody req) of
Nothing -> r Nothing -> r
Just (b,t) -> r { requestBody = RequestBodyLBS b Just (b,t) -> r { requestBody = RequestBodyLBS b
, requestHeaders = [(hContentType, BS.pack . show $ t)] } , requestHeaders = [(hContentType, cs . show $ t)] }
setQS = setQueryString $ queryTextToQuery (qs req) setQS = setQueryString $ queryTextToQuery (qs req)
setheaders r = r { requestHeaders = requestHeaders r setheaders r = r { requestHeaders = requestHeaders r
++ Prelude.map toProperHeader (headers req) } ++ Prelude.map toProperHeader (headers req) }
@ -110,7 +109,7 @@ displayHttpRequest :: Method -> String
displayHttpRequest httpmethod = "HTTP " ++ cs httpmethod ++ " request" displayHttpRequest httpmethod = "HTTP " ++ cs httpmethod ++ " request"
performRequest :: Method -> Req -> (Int -> Bool) -> BaseUrl -> EitherT String IO (Int, ByteString) performRequest :: Method -> Req -> (Int -> Bool) -> BaseUrl -> EitherT String IO (Int, ByteString, MediaType)
performRequest reqMethod req isWantedStatus reqHost = do performRequest reqMethod req isWantedStatus reqHost = do
partialRequest <- liftIO $ reqToRequest req reqHost partialRequest <- liftIO $ reqToRequest req reqHost
@ -129,7 +128,12 @@ performRequest reqMethod req isWantedStatus reqHost = do
let status = Client.responseStatus response let status = Client.responseStatus response
unless (isWantedStatus (statusCode status)) $ unless (isWantedStatus (statusCode status)) $
left (displayHttpRequest reqMethod ++ " failed with status: " ++ showStatus status) left (displayHttpRequest reqMethod ++ " failed with status: " ++ showStatus status)
return $ (statusCode status, Client.responseBody response) ct <- case lookup "Content-Type" $ Client.responseHeaders response of
Nothing -> pure $ "application"//"octet-stream"
Just t -> case parseAccept t of
Nothing -> left $ "invalid Content-Type header: " <> cs t
Just t' -> pure t'
return $ (statusCode status, Client.responseBody response, ct)
where where
showStatus (Status code message) = showStatus (Status code message) =
show code ++ " - " ++ cs message show code ++ " - " ++ cs message
@ -138,7 +142,7 @@ performRequest reqMethod req isWantedStatus reqHost = do
performRequestJSON :: FromJSON result => performRequestJSON :: FromJSON result =>
Method -> Req -> Int -> BaseUrl -> EitherT String IO result Method -> Req -> Int -> BaseUrl -> EitherT String IO result
performRequestJSON reqMethod req wantedStatus reqHost = do performRequestJSON reqMethod req wantedStatus reqHost = do
(_status, respBody) <- performRequest reqMethod req (== wantedStatus) reqHost (_status, respBody, _) <- performRequest reqMethod req (== wantedStatus) reqHost
either either
(\ message -> left (displayHttpRequest reqMethod ++ " returned invalid json: " ++ message)) (\ message -> left (displayHttpRequest reqMethod ++ " returned invalid json: " ++ message))
return return

View file

@ -17,6 +17,7 @@ import Data.Foldable (forM_)
import Data.Proxy import Data.Proxy
import Data.Typeable import Data.Typeable
import GHC.Generics import GHC.Generics
import Network.HTTP.Media
import Network.HTTP.Types import Network.HTTP.Types
import Network.Socket import Network.Socket
import Network.Wai import Network.Wai
@ -101,8 +102,8 @@ getQueryFlag :: Bool -> BaseUrl -> EitherT String IO Bool
getMatrixParam :: Maybe String -> BaseUrl -> EitherT String IO Person getMatrixParam :: Maybe String -> BaseUrl -> EitherT String IO Person
getMatrixParams :: [String] -> BaseUrl -> EitherT String IO [Person] getMatrixParams :: [String] -> BaseUrl -> EitherT String IO [Person]
getMatrixFlag :: Bool -> BaseUrl -> EitherT String IO Bool getMatrixFlag :: Bool -> BaseUrl -> EitherT String IO Bool
getRawSuccess :: Method -> BaseUrl -> EitherT String IO (Int, ByteString) getRawSuccess :: Method -> BaseUrl -> EitherT String IO (Int, ByteString, MediaType)
getRawFailure :: Method -> BaseUrl -> EitherT String IO (Int, ByteString) getRawFailure :: Method -> BaseUrl -> EitherT String IO (Int, ByteString, MediaType)
getMultiple :: String -> Maybe Int -> Bool -> [(String, [Rational])] getMultiple :: String -> Maybe Int -> Bool -> [(String, [Rational])]
-> BaseUrl -> BaseUrl
-> EitherT String IO (String, Maybe Int, Bool, [(String, [Rational])]) -> EitherT String IO (String, Maybe Int, Bool, [(String, [Rational])])
@ -167,10 +168,10 @@ spec = do
runEitherT (getMatrixFlag flag host) `shouldReturn` Right flag runEitherT (getMatrixFlag flag host) `shouldReturn` Right flag
it "Servant.API.Raw on success" $ withServer $ \ host -> do it "Servant.API.Raw on success" $ withServer $ \ host -> do
runEitherT (getRawSuccess methodGet host) `shouldReturn` Right (200, "rawSuccess") runEitherT (getRawSuccess methodGet host) `shouldReturn` Right (200, "rawSuccess", "application"//"octet-stream")
it "Servant.API.Raw on failure" $ withServer $ \ host -> do it "Servant.API.Raw on failure" $ withServer $ \ host -> do
runEitherT (getRawFailure methodGet host) `shouldReturn` Right (400, "rawFailure") runEitherT (getRawFailure methodGet host) `shouldReturn` Right (400, "rawFailure", "application"//"octet-stream")
modifyMaxSuccess (const 20) $ do modifyMaxSuccess (const 20) $ do
it "works for a combination of Capture, QueryParam, QueryFlag and ReqBody" $ it "works for a combination of Capture, QueryParam, QueryFlag and ReqBody" $