Skip to content

Commit 6234eae

Browse files
authored
Merge pull request #615 from phadej/mime-unrender-multiple
Mime unrender multiple
2 parents e8ba670 + 4d4bc8e commit 6234eae

File tree

4 files changed

+31
-6
lines changed

4 files changed

+31
-6
lines changed

servant/servant.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ test-suite spec
111111
base == 4.*
112112
, base-compat
113113
, aeson
114+
, aeson-compat >=0.3.3 && <0.4
114115
, attoparsec
115116
, bytestring
116117
, hspec == 2.*
117-
, http-media
118118
, QuickCheck
119119
, quickcheck-instances
120120
, servant

servant/src/Servant/API/ContentTypes.hs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,16 @@ instance OVERLAPPABLE_
206206
--
207207
class Accept ctype => MimeUnrender ctype a where
208208
mimeUnrender :: Proxy ctype -> ByteString -> Either String a
209+
mimeUnrender p = mimeUnrenderWithType p (contentType p)
210+
211+
-- | Variant which is given the actual 'M.MediaType' provided by the other party.
212+
--
213+
-- In the most cases you don't want to branch based on the 'M.MediaType'.
214+
-- See <https://github.com/haskell-servant/servant/pull/552 pr552> for a motivating example.
215+
mimeUnrenderWithType :: Proxy ctype -> M.MediaType -> ByteString -> Either String a
216+
mimeUnrenderWithType p _ = mimeUnrender p
217+
218+
{-# MINIMAL mimeUnrender | mimeUnrenderWithType #-}
209219

210220
class AllCTUnrender (list :: [*]) a where
211221
handleCTypeH :: Proxy list
@@ -290,10 +300,10 @@ instance ( MimeUnrender ctyp a
290300
, AllMimeUnrender ctyps a
291301
) => AllMimeUnrender (ctyp ': ctyps) a where
292302
allMimeUnrender _ bs =
293-
(map (, x) $ NE.toList $ contentTypes pctyp)
303+
(map mk $ NE.toList $ contentTypes pctyp)
294304
++ allMimeUnrender pctyps bs
295305
where
296-
x = mimeUnrender pctyp bs
306+
mk ct = (ct, mimeUnrenderWithType pctyp ct bs)
297307
pctyp = Proxy :: Proxy ctyp
298308
pctyps = Proxy :: Proxy ctyps
299309

servant/test/Servant/API/ContentTypesSpec.hs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module Servant.API.ContentTypesSpec where
1111
import Prelude ()
1212
import Prelude.Compat
1313

14-
import Data.Aeson
14+
import Data.Aeson.Compat
1515
import Data.ByteString.Char8 (ByteString, append, pack)
1616
import qualified Data.ByteString.Lazy as BSL
1717
import qualified Data.ByteString.Lazy.Char8 as BSL8
@@ -24,9 +24,9 @@ import Data.Proxy
2424
import Data.String (IsString (..))
2525
import Data.String.Conversions (cs)
2626
import qualified Data.Text as TextS
27+
import qualified Data.Text.Encoding as TextSE
2728
import qualified Data.Text.Lazy as TextL
2829
import GHC.Generics
29-
import qualified Network.HTTP.Media as M
3030
import Test.Hspec
3131
import Test.QuickCheck
3232
import Text.Read (readMaybe)
@@ -179,6 +179,15 @@ spec = describe "Servant.API.ContentTypes" $ do
179179
handleCTypeH (Proxy :: Proxy '[JSONorText]) "image/jpeg"
180180
"42" `shouldBe` (Nothing :: Maybe (Either String Int))
181181

182+
it "passes content-type to mimeUnrenderWithType" $ do
183+
let val = "foobar" :: TextS.Text
184+
handleCTypeH (Proxy :: Proxy '[JSONorText]) "application/json"
185+
"\"foobar\"" `shouldBe` Just (Right val)
186+
handleCTypeH (Proxy :: Proxy '[JSONorText]) "text/plain"
187+
"foobar" `shouldBe` Just (Right val)
188+
handleCTypeH (Proxy :: Proxy '[JSONorText]) "image/jpeg"
189+
"foobar" `shouldBe` (Nothing :: Maybe (Either String Int))
190+
182191
#if MIN_VERSION_aeson(0,9,0)
183192
-- aeson >= 0.9 decodes top-level strings
184193
describe "eitherDecodeLenient" $ do
@@ -226,14 +235,19 @@ instance IsString AcceptHeader where
226235
data JSONorText
227236

228237
instance Accept JSONorText where
229-
contentTypes _ = "text" M.// "plain" NE.:| [ "application" M.// "json" ]
238+
contentTypes _ = "text/plain" NE.:| [ "application/json" ]
230239

231240
instance MimeRender JSONorText Int where
232241
mimeRender _ = cs . show
233242

234243
instance MimeUnrender JSONorText Int where
235244
mimeUnrender _ = maybe (Left "") Right . readMaybe . BSL8.unpack
236245

246+
instance MimeUnrender JSONorText TextS.Text where
247+
mimeUnrenderWithType _ mt
248+
| mt == "application/json" = maybe (Left "") Right . decode
249+
| otherwise = Right . TextSE.decodeUtf8 . BSL.toStrict
250+
237251
addToAccept :: Accept a => Proxy a -> ZeroToOne -> AcceptHeader -> AcceptHeader
238252
addToAccept p (ZeroToOne f) (AcceptHeader h) = AcceptHeader (cont h)
239253
where new = cs (show $ contentType p) `append` "; q=" `append` pack (show f)

stack-ghc-7.8.4.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ packages:
66
- servant-foreign/
77
- servant-server/
88
extra-deps:
9+
- aeson-compat-0.3.6
910
- base-compat-0.9.1
1011
- control-monad-omega-0.3.1
1112
- cryptonite-0.6

0 commit comments

Comments
 (0)