diff --git a/servant/src/Servant/API/ContentTypes.hs b/servant/src/Servant/API/ContentTypes.hs index 2cad8579..a9966d24 100644 --- a/servant/src/Servant/API/ContentTypes.hs +++ b/servant/src/Servant/API/ContentTypes.hs @@ -66,30 +66,31 @@ module Servant.API.ContentTypes ) where #if !MIN_VERSION_base(4,8,0) -import Control.Applicative ((<*)) +import Control.Applicative ((*>), (<*)) #endif -import Control.Arrow (left) +import Control.Arrow (left) import Control.Monad -import Data.Aeson (FromJSON, ToJSON, encode, - parseJSON) -import Data.Aeson.Parser (value) -import Data.Aeson.Types (parseEither) +import Data.Aeson (FromJSON, ToJSON, encode, + parseJSON) +import Data.Aeson.Parser (value) +import Data.Aeson.Types (parseEither) import Data.Attoparsec.ByteString.Char8 (endOfInput, parseOnly, skipSpace, ()) -import qualified Data.ByteString as BS -import Data.ByteString.Lazy (ByteString, fromStrict, toStrict) -import qualified Data.ByteString.Lazy as B +import qualified Data.ByteString as BS +import Data.ByteString.Lazy (ByteString, fromStrict, + toStrict) +import qualified Data.ByteString.Lazy as B import Data.Monoid -import Data.String.Conversions (cs) -import qualified Data.Text as TextS -import qualified Data.Text.Encoding as TextS -import qualified Data.Text.Lazy as TextL -import qualified Data.Text.Lazy.Encoding as TextL +import Data.String.Conversions (cs) +import qualified Data.Text as TextS +import qualified Data.Text.Encoding as TextS +import qualified Data.Text.Lazy as TextL +import qualified Data.Text.Lazy.Encoding as TextL import Data.Typeable -import GHC.Exts (Constraint) -import qualified Network.HTTP.Media as M -import Network.URI (escapeURIString, isUnreserved, - unEscapeString) +import GHC.Exts (Constraint) +import qualified Network.HTTP.Media as M +import Network.URI (escapeURIString, + isUnreserved, unEscapeString) -- * Provided content types data JSON deriving Typeable @@ -304,10 +305,10 @@ eitherDecodeLenient :: FromJSON a => ByteString -> Either String a eitherDecodeLenient input = parseOnly parser (cs input) >>= parseEither parseJSON where - parser = - Data.Aeson.Parser.value - <* skipSpace - <* (endOfInput "trailing junk after valid JSON") + parser = skipSpace + *> Data.Aeson.Parser.value + <* skipSpace + <* (endOfInput "trailing junk after valid JSON") -- | `eitherDecode` instance FromJSON a => MimeUnrender JSON a where diff --git a/servant/test/Servant/API/ContentTypesSpec.hs b/servant/test/Servant/API/ContentTypesSpec.hs index aaf935ed..0f4a075a 100644 --- a/servant/test/Servant/API/ContentTypesSpec.hs +++ b/servant/test/Servant/API/ContentTypesSpec.hs @@ -8,15 +8,15 @@ module Servant.API.ContentTypesSpec where #if !MIN_VERSION_base(4,8,0) import Control.Applicative +import Data.Monoid #endif import Control.Arrow -import Data.Either import Data.Aeson import Data.Aeson.Parser (jstring) import Data.Attoparsec.ByteString (parseOnly) +import Data.Either import Data.Function (on) import Data.Proxy - import Data.ByteString.Char8 (ByteString, append, pack) import qualified Data.ByteString.Lazy as BSL import Data.List (maximumBy) @@ -26,7 +26,6 @@ import Data.String.Conversions (cs) import qualified Data.Text as TextS import qualified Data.Text.Lazy as TextL import GHC.Generics -import Data.Monoid import Network.URL (exportParams, importParams) import Test.Hspec import Test.QuickCheck @@ -43,6 +42,9 @@ spec = describe "Servant.API.ContentTypes" $ do it "handles whitespace at end of input" $ do mimeUnrender p "[1] " `shouldBe` Right [1 :: Int] + it "handles whitespace at beginning of input" $ do + mimeUnrender p " [1] " `shouldBe` Right [1 :: Int] + it "does not like junk at end of input" $ do mimeUnrender p "[1] this probably shouldn't work" `shouldSatisfy` (isLeft :: Either a [Int] -> Bool)