git.iko.soy/typeable/http-api-data
on master help sign in
Make parseHeader total (instead of failing when decoding)
6ec0d6cDario Bertini
Web/HttpApiData/Internal.hs+5−3
@@ -14,6 +14,8 @@ import Control.Applicative
14import Data.Traversable (Traversable(traverse))
14import Data.Traversable (Traversable(traverse))
15#endif
15#endif
16import Control.Arrow ((&&&))
16import Control.Arrow ((&&&))
17+import Control.Monad ((<=<))
18+import Data.Either.Combinators (mapLeft)
17
19
18import Data.Monoid
20import Data.Monoid
19import Data.ByteString (ByteString)
21import Data.ByteString (ByteString)
@@ -23,7 +25,7 @@ import Data.Int
23import Data.Word
25import Data.Word
24
26
25import Data.Text (Text)
27import Data.Text (Text)
26−import Data.Text.Encoding (encodeUtf8, decodeUtf8)
28+import Data.Text.Encoding (encodeUtf8, decodeUtf8')
27import Data.Text.Read (signed, decimal, rational, Reader)
29import Data.Text.Read (signed, decimal, rational, Reader)
28import qualified Data.Text as T
30import qualified Data.Text as T
29import qualified Data.Text.Lazy as L
31import qualified Data.Text.Lazy as L
@@ -73,7 +75,7 @@ class FromHttpApiData a where
73
75
74 -- | Parse HTTP header value.
76 -- | Parse HTTP header value.
75 parseHeader :: ByteString -> Either Text a
77 parseHeader :: ByteString -> Either Text a
76− parseHeader = parseUrlPiece . decodeUtf8
78+ parseHeader = parseUrlPiece <=< (mapLeft (T.pack . show) . decodeUtf8')
77
79
78 -- | Parse query param value.
80 -- | Parse query param value.
79 parseQueryParam :: Text -> Either Text a
81 parseQueryParam :: Text -> Either Text a
@@ -331,7 +333,7 @@ parseBoundedQueryParam = parseBoundedEnumOfI toQueryParam
331-- Uses @'toHeader'@ to get possible values.
333-- Uses @'toHeader'@ to get possible values.
332parseBoundedHeader :: (ToHttpApiData a, Bounded a, Enum a) => ByteString -> Either Text a
334parseBoundedHeader :: (ToHttpApiData a, Bounded a, Enum a) => ByteString -> Either Text a
333parseBoundedHeader bs = case lookupBoundedEnumOf toHeader bs of
335parseBoundedHeader bs = case lookupBoundedEnumOf toHeader bs of
334− Nothing -> defaultParseError (decodeUtf8 bs)
336+ Nothing -> defaultParseError $ T.pack $ show bs
335 Just x -> return x
337 Just x -> return x
336
338
337-- | Parse URL piece using @'Read'@ instance.
339-- | Parse URL piece using @'Read'@ instance.
http-api-data.cabal+2
@@ -26,6 +26,7 @@ library
26 , bytestring
26 , bytestring
27 , time
27 , time
28 , time-locale-compat >=0.1.1.0 && <0.2
28 , time-locale-compat >=0.1.1.0 && <0.2
29+ , either
29 if flag(use-text-show)
30 if flag(use-text-show)
30 cpp-options: -DUSE_TEXT_SHOW
31 cpp-options: -DUSE_TEXT_SHOW
31 build-depends: text-show >= 2
32 build-depends: text-show >= 2
@@ -46,6 +47,7 @@ test-suite spec
46 , http-api-data
47 , http-api-data
47 , text
48 , text
48 , time
49 , time
50+ , bytestring
49
51
50test-suite doctest
52test-suite doctest
51 build-depends: base, doctest, Glob
53 build-depends: base, doctest, Glob
test/Spec.hs+4
@@ -10,6 +10,7 @@ import Data.Word
10import Data.Time
10import Data.Time
11import qualified Data.Text as T
11import qualified Data.Text as T
12import qualified Data.Text.Lazy as L
12import qualified Data.Text.Lazy as L
13+import qualified Data.ByteString as BS
13import Data.Version
14import Data.Version
14
15
15import Test.Hspec
16import Test.Hspec
@@ -126,3 +127,6 @@ spec = do
126 parseUrlPieceMaybe (T.pack "256") `shouldBe` (Nothing :: Maybe Int8)
127 parseUrlPieceMaybe (T.pack "256") `shouldBe` (Nothing :: Maybe Int8)
127 parseUrlPieceMaybe (T.pack "-10") `shouldBe` (Nothing :: Maybe Word)
128 parseUrlPieceMaybe (T.pack "-10") `shouldBe` (Nothing :: Maybe Word)
128
129
130+ it "invalid utf8 is handled" $ do
131+ parseHeaderMaybe (BS.pack [128]) `shouldBe` (Nothing :: Maybe T.Text)
132+