on master help sign in
Remove FromFormUrlEncoded and ToFormUrlEncoded.

In favor of FromForm and ToForm from the new version of http-api-data.

commit0870b3b2f55166237a4382481c7fe306f33ba733 authorJulian K. Arni <jkarni@gmail.com> dateThu 1 Sep 2016, 21:24 (10 years ago) parentf44b336
6 files changed+24−94
servant-client/servant-client.cabal+1 servant-client/test/Servant/ClientSpec.hs+8−18 servant/CHANGELOG.md+2−1 servant/src/Servant/API.hs+2−2 servant/src/Servant/API/ContentTypes.hs+11−56 servant/test/Servant/API/ContentTypesSpec.hs−17
servant-client/servant-client.cabal+1
@@ -78,6 +78,7 @@ test-suite spec
7878 , bytestring
7979 , deepseq
8080 , hspec == 2.*
81+ , http-api-data
8182 , http-client
8283 , http-media
8384 , http-types
servant-client/test/Servant/ClientSpec.hs+8−18
@@ -30,7 +30,7 @@ module Servant.ClientSpec where
3030import Control.Applicative ((<$>))
3131#endif
3232import Control.Arrow (left)
33−import Control.Concurrent (forkIO, killThread, ThreadId)
33+import Control.Concurrent (ThreadId, forkIO, killThread)
3434import Control.Exception (bracket)
3535import Control.Monad.Trans.Except (throwE )
3636import Data.Aeson
@@ -39,19 +39,20 @@ import Data.Char (chr, isPrint)
3939import Data.Foldable (forM_)
4040import Data.Monoid hiding (getLast)
4141import Data.Proxy
42−import qualified Data.Text as T
4342import GHC.Generics (Generic)
4443import qualified Network.HTTP.Client as C
4544import Network.HTTP.Media
4645import qualified Network.HTTP.Types as HTTP
4746import Network.Socket
48−import Network.Wai (Request, requestHeaders, responseLBS)
47+import Network.Wai (Request, requestHeaders,
48+ responseLBS)
4949import Network.Wai.Handler.Warp
5050import System.IO.Unsafe (unsafePerformIO)
5151import Test.Hspec
5252import Test.Hspec.QuickCheck
5353import Test.HUnit
5454import Test.QuickCheck
55+import Web.FormUrlEncoded (FromForm, ToForm)
5556
5657import Servant.API
5758import Servant.API.Internal.Test.ComprehensiveAPI
@@ -82,19 +83,8 @@ data Person = Person {
8283instance ToJSON Person
8384instance FromJSON Person
8485
85−instance ToFormUrlEncoded Person where
86− toFormUrlEncoded Person{..} =
87− [("name", T.pack name), ("age", T.pack (show age))]
88−
89−lookupEither :: (Show a, Eq a) => a -> [(a,b)] -> Either String b
90−lookupEither x xs = do
91− maybe (Left $ "could not find key " <> show x) return $ lookup x xs
92−
93−instance FromFormUrlEncoded Person where
94− fromFormUrlEncoded xs = do
95− n <- lookupEither "name" xs
96− a <- lookupEither "age" xs
97− return $ Person (T.unpack n) (read $ T.unpack a)
86+instance ToForm Person where
87+instance FromForm Person where
9888
9989alice :: Person
10090alice = Person "Alice" 42
@@ -131,9 +121,9 @@ getBody :: Person -> SCR.ClientM Person
131121getQueryParam :: Maybe String -> SCR.ClientM Person
132122getQueryParams :: [String] -> SCR.ClientM [Person]
133123getQueryFlag :: Bool -> SCR.ClientM Bool
134−getRawSuccess :: HTTP.Method
124+getRawSuccess :: HTTP.Method
135125 -> SCR.ClientM (Int, BS.ByteString, MediaType, [HTTP.Header], C.Response BS.ByteString)
136−getRawFailure :: HTTP.Method
126+getRawFailure :: HTTP.Method
137127 -> SCR.ClientM (Int, BS.ByteString, MediaType, [HTTP.Header], C.Response BS.ByteString)
138128getMultiple :: String -> Maybe Int -> Bool -> [(String, [Rational])]
139129 -> SCR.ClientM (String, Maybe Int, Bool, [(String, [Rational])])
servant/CHANGELOG.md+2−1
@@ -1,12 +1,13 @@
11next
22----
33* Added Eq, Show, Read, Generic and Ord instances to IsSecure
4+* BACKWARDS INCOMPATIBLE replace use of `ToFromByteString` with `To/FromHttpApiData` for `GetHeaders/BuildHeadersTo`
5+* BACKWARD INCOMPATIBLE: Moved `From/ToFormUrlEncoded` classes, which were renamed to `From/ToForm` to `http-api-data`
46
570.8.1
68----
79
810* Add `CaptureAll` combinator. Captures all of the remaining segments in a URL.
9−* BACKWARDS INCOMPATIBLE replace use of `ToFromByteString` with `To/FromHttpApiData` for `GetHeaders/BuildHeadersTo`
1011
11120.8
1213---
servant/src/Servant/API.hs+2−2
@@ -62,10 +62,10 @@ import Servant.API.Alternative ((:<|>) (..))
6262import Servant.API.BasicAuth (BasicAuth,BasicAuthData(..))
6363import Servant.API.Capture (Capture, CaptureAll)
6464import Servant.API.ContentTypes (Accept (..), FormUrlEncoded,
65− FromFormUrlEncoded (..), JSON,
65+ JSON,
6666 MimeRender (..), NoContent (NoContent),
6767 MimeUnrender (..), OctetStream,
68− PlainText, ToFormUrlEncoded (..))
68+ PlainText)
6969import Servant.API.Experimental.Auth (AuthProtect)
7070import Servant.API.Header (Header (..))
7171import Servant.API.HttpVersion (HttpVersion (..))
servant/src/Servant/API/ContentTypes.hs+11−56
@@ -66,15 +66,14 @@ module Servant.API.ContentTypes
6666 , AllMime(..)
6767 , AllMimeRender(..)
6868 , AllMimeUnrender(..)
69− , FromFormUrlEncoded(..)
70− , ToFormUrlEncoded(..)
7169 , eitherDecodeLenient
7270 , canHandleAcceptH
7371 ) where
7472
7573import Control.Arrow (left)
7674import Control.Monad.Compat
77−import Data.Aeson (FromJSON(..), ToJSON(..), encode)
75+import Data.Aeson (FromJSON (..), ToJSON (..),
76+ encode)
7877import Data.Aeson.Parser (value)
7978import Data.Aeson.Types (parseEither)
8079import Data.Attoparsec.ByteString.Char8 (endOfInput, parseOnly,
@@ -82,10 +81,8 @@ import Data.Attoparsec.ByteString.Char8 (endOfInput, parseOnly,
8281import qualified Data.ByteString as BS
8382import Data.ByteString.Lazy (ByteString, fromStrict,
8483 toStrict)
85−import qualified Data.ByteString.Lazy as B
8684import qualified Data.ByteString.Lazy.Char8 as BC
8785import Data.Maybe (isJust)
88−import Data.Monoid.Compat
8986import Data.String.Conversions (cs)
9087import qualified Data.Text as TextS
9188import qualified Data.Text.Encoding as TextS
@@ -94,8 +91,9 @@ import qualified Data.Text.Lazy.Encoding as TextL
9491import Data.Typeable
9592import GHC.Generics (Generic)
9693import qualified Network.HTTP.Media as M
97−import Network.URI (escapeURIString,
98− isUnreserved, unEscapeString)
94+import Web.FormUrlEncoded (FromForm, ToForm,
95+ urlEncodeAsForm,
96+ urlDecodeAsForm)
9997import Prelude ()
10098import Prelude.Compat
10199
@@ -290,12 +288,12 @@ instance OVERLAPPABLE_
290288 ToJSON a => MimeRender JSON a where
291289 mimeRender _ = encode
292290
293−-- | @encodeFormUrlEncoded . toFormUrlEncoded@
291+-- | @urlEncodeAsForm"
294292-- Note that the @mimeUnrender p (mimeRender p x) == Right x@ law only
295293-- holds if every element of x is non-null (i.e., not @("", "")@)
296294instance OVERLAPPABLE_
297− ToFormUrlEncoded a => MimeRender FormUrlEncoded a where
298− mimeRender _ = encodeFormUrlEncoded . toFormUrlEncoded
295+ ToForm a => MimeRender FormUrlEncoded a where
296+ mimeRender _ = urlEncodeAsForm
299297
300298-- | `TextL.encodeUtf8`
301299instance MimeRender PlainText TextL.Text where
@@ -348,11 +346,11 @@ eitherDecodeLenient input =
348346instance FromJSON a => MimeUnrender JSON a where
349347 mimeUnrender _ = eitherDecodeLenient
350348
351−-- | @decodeFormUrlEncoded >=> fromFormUrlEncoded@
349+-- | @urlDecodeAsForm@
352350-- Note that the @mimeUnrender p (mimeRender p x) == Right x@ law only
353351-- holds if every element of x is non-null (i.e., not @("", "")@)
354−instance FromFormUrlEncoded a => MimeUnrender FormUrlEncoded a where
355− mimeUnrender _ = decodeFormUrlEncoded >=> fromFormUrlEncoded
352+instance FromForm a => MimeUnrender FormUrlEncoded a where
353+ mimeUnrender _ = left TextS.unpack . urlDecodeAsForm
356354
357355-- | @left show . TextL.decodeUtf8'@
358356instance MimeUnrender PlainText TextL.Text where
@@ -375,49 +373,6 @@ instance MimeUnrender OctetStream BS.ByteString where
375373 mimeUnrender _ = Right . toStrict
376374
377375
378−--------------------------------------------------------------------------
379−-- * FormUrlEncoded
380−
381−-- | A type that can be converted to @application/x-www-form-urlencoded@
382−class ToFormUrlEncoded a where
383− toFormUrlEncoded :: a -> [(TextS.Text, TextS.Text)]
384−
385−instance ToFormUrlEncoded [(TextS.Text, TextS.Text)] where
386− toFormUrlEncoded = id
387−
388−-- | A type that can be converted from @application/x-www-form-urlencoded@,
389−-- with the possibility of failure.
390−class FromFormUrlEncoded a where
391− fromFormUrlEncoded :: [(TextS.Text, TextS.Text)] -> Either String a
392−
393−instance FromFormUrlEncoded [(TextS.Text, TextS.Text)] where
394− fromFormUrlEncoded = return
395−
396−encodeFormUrlEncoded :: [(TextS.Text, TextS.Text)] -> ByteString
397−encodeFormUrlEncoded xs =
398− let escape :: TextS.Text -> ByteString
399− escape = cs . escapeURIString isUnreserved . cs
400− encodePair :: (TextS.Text, TextS.Text) -> ByteString
401− encodePair (k, "") = escape k
402− encodePair (k, v) = escape k <> "=" <> escape v
403− in B.intercalate "&" $ map encodePair xs
404−
405−decodeFormUrlEncoded :: ByteString -> Either String [(TextS.Text, TextS.Text)]
406−decodeFormUrlEncoded "" = return []
407−decodeFormUrlEncoded q = do
408− let xs :: [TextS.Text]
409− xs = TextS.splitOn "&" . cs $ q
410− parsePair :: TextS.Text -> Either String (TextS.Text, TextS.Text)
411− parsePair p =
412− case TextS.splitOn "=" p of
413− [k,v] -> return ( unescape k
414− , unescape v
415− )
416− [k] -> return ( unescape k, "" )
417− _ -> Left $ "not a valid pair: " <> cs p
418− unescape :: TextS.Text -> TextS.Text
419− unescape = cs . unEscapeString . cs . TextS.intercalate "%20" . TextS.splitOn "+"
420− mapM parsePair xs
421376
422377-- $setup
423378-- >>> import Servant.API
servant/test/Servant/API/ContentTypesSpec.hs−17
@@ -11,7 +11,6 @@ module Servant.API.ContentTypesSpec where
1111import Prelude ()
1212import Prelude.Compat
1313
14−import Control.Arrow
1514import Data.Aeson
1615import Data.ByteString.Char8 (ByteString, append, pack)
1716import qualified Data.ByteString.Lazy as BSL
@@ -25,7 +24,6 @@ import Data.String.Conversions (cs)
2524import qualified Data.Text as TextS
2625import qualified Data.Text.Lazy as TextL
2726import GHC.Generics
28−import Network.URL (exportParams, importParams)
2927import Test.Hspec
3028import Test.QuickCheck
3129import "quickcheck-instances" Test.QuickCheck.Instances ()
@@ -68,21 +66,6 @@ spec = describe "Servant.API.ContentTypes" $ do
6866 it "has mimeUnrender reverse mimeRender for valid top-level json " $ do
6967 property $ \x -> mimeUnrender p (mimeRender p x) == Right (x::SomeData)
7068
71− describe "The FormUrlEncoded Content-Type type" $ do
72− let p = Proxy :: Proxy FormUrlEncoded
73−
74− it "has mimeUnrender reverse mimeRender" $ do
75− property $ \x -> mempty `notElem` x
76− ==> mimeUnrender p (mimeRender p x) == Right (x::[(TextS.Text,TextS.Text)])
77−
78− it "has mimeUnrender reverse exportParams (Network.URL)" $ do
79− property $ \x -> mempty `notElem` x
80− ==> (mimeUnrender p . cs . exportParams . map (cs *** cs) $ x) == Right (x::[(TextS.Text,TextS.Text)])
81−
82− it "has importParams (Network.URL) reverse mimeRender" $ do
83− property $ \x -> mempty `notElem` x
84− ==> (fmap (map (cs *** cs)) . importParams . cs . mimeRender p $ x) == Just (x::[(TextS.Text,TextS.Text)])
85−
8669 describe "The PlainText Content-Type type" $ do
8770 let p = Proxy :: Proxy PlainText
8871