packages feed

servant 0.8 → 0.8.1

raw patch · 7 files changed

+49/−10 lines, 7 filesdep ~aeson

Dependency ranges changed: aeson

Files

CHANGELOG.md view
@@ -1,3 +1,8 @@+0.8.1+----++* Add `CaptureAll` combinator. Captures all of the remaining segments in a URL.+ 0.8 --- 
servant.cabal view
@@ -1,5 +1,5 @@ name:                servant-version:             0.8+version:             0.8.1 synopsis:            A family of combinators for defining webservices APIs description:   A family of combinators for defining webservices APIs and serving them@@ -51,7 +51,7 @@   build-depends:       base                  >= 4.7  && < 4.10     , base-compat           >= 0.9  && < 0.10-    , aeson                 >= 0.7  && < 0.12+    , aeson                 >= 0.7  && < 1.1     , attoparsec            >= 0.12 && < 0.14     , bytestring            >= 0.10 && < 0.11     , bytestring-conversion >= 0.3  && < 0.4
src/Servant/API.hs view
@@ -8,7 +8,7 @@    -- * Accessing information from the request   module Servant.API.Capture,-  -- | Capturing parts of the url path as parsed values: @'Capture'@+  -- | Capturing parts of the url path as parsed values: @'Capture'@ and @'CaptureAll'@   module Servant.API.Header,   -- | Retrieving specific headers from the request   module Servant.API.HttpVersion,@@ -60,7 +60,7 @@  import           Servant.API.Alternative     ((:<|>) (..)) import           Servant.API.BasicAuth       (BasicAuth,BasicAuthData(..))-import           Servant.API.Capture         (Capture)+import           Servant.API.Capture         (Capture, CaptureAll) import           Servant.API.ContentTypes    (Accept (..), FormUrlEncoded,                                               FromFormUrlEncoded (..), JSON,                                               MimeRender (..), NoContent (NoContent),
src/Servant/API/Capture.hs view
@@ -2,7 +2,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE PolyKinds          #-} {-# OPTIONS_HADDOCK not-home    #-}-module Servant.API.Capture (Capture) where+module Servant.API.Capture (Capture, CaptureAll) where  import           Data.Typeable (Typeable) import           GHC.TypeLits  (Symbol)@@ -15,9 +15,22 @@ data Capture (sym :: Symbol) a     deriving (Typeable) ++-- | Capture all remaining values from the request path under a certain type+-- @a@.+--+-- Example:+--+-- >>>            -- GET /src/*+-- >>> type MyAPI = "src" :> CaptureAll "segments" Text :> Get '[JSON] SourceFile+data CaptureAll (sym :: Symbol) a+    deriving (Typeable)+ -- $setup -- >>> import Servant.API -- >>> import Data.Aeson -- >>> import Data.Text -- >>> data Book -- >>> instance ToJSON Book where { toJSON = undefined }+-- >>> data SourceFile+-- >>> instance ToJSON SourceFile where { toJSON = undefined }
src/Servant/API/Internal/Test/ComprehensiveAPI.hs view
@@ -13,6 +13,13 @@ type GET = Get '[JSON] NoContent  type ComprehensiveAPI =+  ComprehensiveAPIWithoutRaw :<|>+  Raw++comprehensiveAPI :: Proxy ComprehensiveAPI+comprehensiveAPI = Proxy++type ComprehensiveAPIWithoutRaw =   GET :<|>   Get '[JSON] Int :<|>   Capture "foo" Int :> GET :<|>@@ -22,7 +29,6 @@   QueryParam "foo" Int :> GET :<|>   QueryParams "foo" Int :> GET :<|>   QueryFlag "foo" :> GET :<|>--- Raw :<|>   RemoteHost :> GET :<|>   ReqBody '[JSON] Int :> GET :<|>   Get '[JSON] (Headers '[Header "foo" Int] NoContent) :<|>@@ -30,7 +36,8 @@   Vault :> GET :<|>   Verb 'POST 204 '[JSON] NoContent :<|>   Verb 'POST 204 '[JSON] Int :<|>-  WithNamedContext "foo" '[] GET+  WithNamedContext "foo" '[] GET :<|>+  CaptureAll "foo" Int :> GET -comprehensiveAPI :: Proxy ComprehensiveAPI-comprehensiveAPI = Proxy+comprehensiveAPIWithoutRaw :: Proxy ComprehensiveAPIWithoutRaw+comprehensiveAPIWithoutRaw = Proxy
src/Servant/Utils/Links.hs view
@@ -107,7 +107,7 @@  import Web.HttpApiData import Servant.API.BasicAuth ( BasicAuth )-import Servant.API.Capture ( Capture )+import Servant.API.Capture ( Capture, CaptureAll ) import Servant.API.ReqBody ( ReqBody ) import Servant.API.QueryParam ( QueryParam, QueryParams, QueryFlag ) import Servant.API.Header ( Header )@@ -163,6 +163,8 @@     IsElem sa (ReqBody y x :> sb)           = IsElem sa sb     IsElem (Capture z y :> sa) (Capture x y :> sb)                                             = IsElem sa sb+    IsElem (CaptureAll z y :> sa) (CaptureAll x y :> sb)+                                            = IsElem sa sb     IsElem sa (QueryParam x y :> sb)        = IsElem sa sb     IsElem sa (QueryParams x y :> sb)       = IsElem sa sb     IsElem sa (QueryFlag x :> sb)           = IsElem sa sb@@ -283,6 +285,13 @@     toLink _ l v =         toLink (Proxy :: Proxy sub) $             addSegment (escape . Text.unpack $ toUrlPiece v) l++instance (ToHttpApiData v, HasLink sub)+    => HasLink (CaptureAll sym v :> sub) where+    type MkLink (CaptureAll sym v :> sub) = [v] -> MkLink sub+    toLink _ l vs =+        toLink (Proxy :: Proxy sub) $+            foldl' (flip $ addSegment . escape . Text.unpack . toUrlPiece) l vs  instance HasLink sub => HasLink (Header sym a :> sub) where     type MkLink (Header sym a :> sub) = MkLink sub
test/Servant/Utils/LinksSpec.hs view
@@ -13,6 +13,7 @@ type TestApi =   -- Capture and query params        "hello" :> Capture "name" String :> QueryParam "capital" Bool :> Delete '[JSON] NoContent+  :<|> "all" :> CaptureAll "names" String :> Get '[JSON] NoContent    -- Flags   :<|> "balls" :> QueryFlag "bouncy" :> QueryFlag "fast" :> Delete '[JSON] NoContent@@ -46,6 +47,10 @@                                          :> Delete '[JSON] NoContent)         apiLink l2 "bye" (Just True) `shouldBeURI` "hello/bye?capital=true" +    it "generates correct links for CaptureAll" $ do+        apiLink (Proxy :: Proxy ("all" :> CaptureAll "names" String :> Get '[JSON] NoContent))+          ["roads", "lead", "to", "rome"]+          `shouldBeURI` "all/roads/lead/to/rome"      it "generates correct links for query flags" $ do         let l1 = Proxy :: Proxy ("balls" :> QueryFlag "bouncy"