git.iko.soy/typeable/servant
on c19ed0f help sign in
17 files changed+23−69
since splitsnapshots
unifiedsplit
changelog.d/1580−12 changelog.d/1589−2 changelog.d/1595−2 doc/cookbook/using-free-client/UsingFreeClient.lhs+1−1 servant-auth/servant-auth-server/src/Servant/Auth/Server/Internal/ConfigTypes.hs+2−2 servant-auth/servant-auth-server/src/Servant/Auth/Server/Internal/JWT.hs+3−4 servant-auth/servant-auth-swagger/servant-auth-swagger.cabal+5−1 servant-client-core/src/Servant/Client/Core/Request.hs+3−4 servant-client/src/Servant/Client/Internal/HttpClient.hs+5−6 servant-client/src/Servant/Client/Internal/HttpClient/Streaming.hs+2−2 servant-client/test/Servant/SuccessSpec.hs+1−2 servant-docs/src/Servant/Docs/Internal.hs−4 servant-swagger/src/Servant/Swagger.hs−2 servant-swagger/src/Servant/Swagger/Internal.hs−11 servant-swagger/src/Servant/Swagger/Internal/Test.hs−2 servant/src/Servant/API/ContentTypes.hs+1−1 servant/test/Servant/API/ContentTypesSpec.hs−11
changelog.d/1580deleted−12
@@ -1,12 +0,0 @@
1−synopsis: Allow IO in validationKeys
2−prs: #1580
3−issues: #1579
4−
5−description: {
6−
7−Currently validationKeys are a fixed JWKSet. This does not work with OIDC
8−providers such as AWS Cognito or Okta, which regularly fetching jwks_uri to
9−discover new and expired keys.
10−
11−This change alters the type of validationKeys from JWKSet to IO JWKSet.
12−}
changelog.d/1589deleted−2
@@ -1,2 +0,0 @@
1−synopsis: Only include question mark for nonempty query strings
2−prs: 1589
changelog.d/1595deleted−2
@@ -1,2 +0,0 @@
1−synopsis: Run ClientEnv's makeClientRequest in IO.
2−prs: #1595
doc/cookbook/using-free-client/UsingFreeClient.lhs+1−1
@@ -119,7 +119,7 @@ Now we can use `servant-client`'s internals to convert servant's `Request`
119119to http-client's `Request`, and we can inspect it:
120120
121121```haskell
122− req' <- I.defaultMakeClientRequest burl req
122+ let req' = I.defaultMakeClientRequest burl req
123123 putStrLn $ "Making request: " ++ show req'
124124```
125125
servant-auth/servant-auth-server/src/Servant/Auth/Server/Internal/ConfigTypes.hs+2−2
@@ -33,7 +33,7 @@ data JWTSettings = JWTSettings
3333 -- | Algorithm used to sign JWT.
3434 , jwtAlg :: Maybe Jose.Alg
3535 -- | Keys used to validate JWT.
36− , validationKeys :: IO Jose.JWKSet
36+ , validationKeys :: Jose.JWKSet
3737 -- | An @aud@ predicate. The @aud@ is a string or URI that identifies the
3838 -- intended recipient of the JWT.
3939 , audienceMatches :: Jose.StringOrURI -> IsMatch
@@ -44,7 +44,7 @@ defaultJWTSettings :: Jose.JWK -> JWTSettings
4444defaultJWTSettings k = JWTSettings
4545 { signingKey = k
4646 , jwtAlg = Nothing
47− , validationKeys = pure $ Jose.JWKSet [k]
47+ , validationKeys = Jose.JWKSet [k]
4848 , audienceMatches = const Matches }
4949
5050-- | The policies to use when generating cookies.
servant-auth/servant-auth-server/src/Servant/Auth/Server/Internal/JWT.hs+3−4
@@ -58,15 +58,14 @@ makeJWT v cfg expiry = runExceptT $ do
5858
5959verifyJWT :: FromJWT a => JWTSettings -> BS.ByteString -> IO (Maybe a)
6060verifyJWT jwtCfg input = do
61− keys <- validationKeys jwtCfg
62− verifiedJWT <- runExceptT $ do
61+ verifiedJWT <- liftIO $ runExceptT $ do
6362 unverifiedJWT <- Jose.decodeCompact (BSL.fromStrict input)
6463 Jose.verifyClaims
6564 (jwtSettingsToJwtValidationSettings jwtCfg)
66− keys
65+ (validationKeys jwtCfg)
6766 unverifiedJWT
6867 return $ case verifiedJWT of
6968 Left (_ :: Jose.JWTError) -> Nothing
7069 Right v -> case decodeJWT v of
7170 Left _ -> Nothing
72− Right v' -> Just v'
71+ Right v' -> Just v'
servant-auth/servant-auth-swagger/servant-auth-swagger.cabal+5−1
@@ -31,13 +31,15 @@ library
3131 default-extensions: ConstraintKinds DataKinds DefaultSignatures DeriveFoldable DeriveFunctor DeriveGeneric DeriveTraversable FlexibleContexts FlexibleInstances FunctionalDependencies GADTs KindSignatures MultiParamTypeClasses OverloadedStrings RankNTypes ScopedTypeVariables TypeFamilies TypeOperators
3232 ghc-options: -Wall
3333 build-depends:
34− base >= 4.10 && < 4.17
34+ base >= 4.10 && < 4.16
3535 , text >= 1.2.3.0 && < 2.1
3636 , servant-swagger >= 1.1.5 && < 2
3737 , swagger2 >= 2.2.2 && < 3
3838 , servant >= 0.13 && < 0.20
3939 , servant-auth == 0.4.*
4040 , lens >= 4.16.1 && < 5.2
41+ if impl(ghc >= 9)
42+ buildable: False
4143 exposed-modules:
4244 Servant.Auth.Swagger
4345 default-language: Haskell2010
@@ -59,6 +61,8 @@ test-suite spec
5961 , servant
6062 , servant-auth
6163 , lens
64+ if impl(ghc >= 9)
65+ buildable: False
6266
6367 -- test dependencies
6468 build-depends:
servant-client-core/src/Servant/Client/Core/Request.hs+3−4
@@ -51,9 +51,9 @@ import Network.HTTP.Media
5151 (MediaType)
5252import Network.HTTP.Types
5353 (Header, HeaderName, HttpVersion (..), Method, QueryItem,
54− http11, methodGet, urlEncodeBuilder)
54+ http11, methodGet)
5555import Servant.API
56− (ToHttpApiData, toEncodedUrlPiece, toQueryParam, toHeader, SourceIO)
56+ (ToHttpApiData, toEncodedUrlPiece, toHeader, SourceIO)
5757
5858import Servant.Client.Core.Internal (mediaTypeRnf)
5959
@@ -165,8 +165,7 @@ appendToQueryString pname pvalue req
165165-- | Encode a query parameter value.
166166--
167167encodeQueryParamValue :: ToHttpApiData a => a -> BS.ByteString
168−encodeQueryParamValue = LBS.toStrict . Builder.toLazyByteString
169− . urlEncodeBuilder True . encodeUtf8 . toQueryParam
168+encodeQueryParamValue = LBS.toStrict . Builder.toLazyByteString . toEncodedUrlPiece
170169
171170-- | Add header to the request being constructed.
172171--
servant-client/src/Servant/Client/Internal/HttpClient.hs+5−6
@@ -80,7 +80,7 @@ data ClientEnv
8080 { manager :: Client.Manager
8181 , baseUrl :: BaseUrl
8282 , cookieJar :: Maybe (TVar Client.CookieJar)
83− , makeClientRequest :: BaseUrl -> Request -> IO Client.Request
83+ , makeClientRequest :: BaseUrl -> Request -> Client.Request
8484 -- ^ this function can be used to customize the creation of @http-client@ requests from @servant@ requests. Default value: 'defaultMakeClientRequest'
8585 -- Note that:
8686 -- 1. 'makeClientRequest' exists to allow overriding operational semantics e.g. 'responseTimeout' per request,
@@ -162,7 +162,7 @@ runClientM cm env = runExceptT $ flip runReaderT env $ unClientM cm
162162performRequest :: Maybe [Status] -> Request -> ClientM Response
163163performRequest acceptStatus req = do
164164 ClientEnv m burl cookieJar' createClientRequest <- ask
165− clientRequest <- liftIO $ createClientRequest burl req
165+ let clientRequest = createClientRequest burl req
166166 request <- case cookieJar' of
167167 Nothing -> pure clientRequest
168168 Just cj -> liftIO $ do
@@ -229,8 +229,8 @@ clientResponseToResponse f r = Response
229229-- | Create a @http-client@ 'Client.Request' from a @servant@ 'Request'
230230-- The 'Client.host', 'Client.path' and 'Client.port' fields are extracted from the 'BaseUrl'
231231-- otherwise the body, headers and query string are derived from the @servant@ 'Request'
232−defaultMakeClientRequest :: BaseUrl -> Request -> IO Client.Request
233−defaultMakeClientRequest burl r = return Client.defaultRequest
232+defaultMakeClientRequest :: BaseUrl -> Request -> Client.Request
233+defaultMakeClientRequest burl r = Client.defaultRequest
234234 { Client.method = requestMethod r
235235 , Client.host = fromString $ baseUrlHost burl
236236 , Client.port = baseUrlPort burl
@@ -289,8 +289,7 @@ defaultMakeClientRequest burl r = return Client.defaultRequest
289289 Https -> True
290290
291291 -- Query string builder which does not do any encoding
292− buildQueryString [] = mempty
293− buildQueryString qps = "?" <> foldl' addQueryParam mempty qps
292+ buildQueryString = ("?" <>) . foldl' addQueryParam mempty
294293
295294 addQueryParam qs (k, v) =
296295 qs <> (if BS.null qs then mempty else "&") <> urlEncode True k <> foldMap ("=" <>) v
servant-client/src/Servant/Client/Internal/HttpClient/Streaming.hs+2−2
@@ -140,7 +140,7 @@ performRequest :: Maybe [Status] -> Request -> ClientM Response
140140performRequest acceptStatus req = do
141141 -- TODO: should use Client.withResponse here too
142142 ClientEnv m burl cookieJar' createClientRequest <- ask
143− clientRequest <- liftIO $ createClientRequest burl req
143+ let clientRequest = createClientRequest burl req
144144 request <- case cookieJar' of
145145 Nothing -> pure clientRequest
146146 Just cj -> liftIO $ do
@@ -177,7 +177,7 @@ performWithStreamingRequest req k = do
177177 m <- asks manager
178178 burl <- asks baseUrl
179179 createClientRequest <- asks makeClientRequest
180− request <- liftIO $ createClientRequest burl req
180+ let request = createClientRequest burl req
181181 ClientM $ lift $ lift $ Codensity $ \k1 ->
182182 Client.withResponse request m $ \res -> do
183183 let status = Client.responseStatus res
servant-client/test/Servant/SuccessSpec.hs+1−2
@@ -162,8 +162,7 @@ successSpec = beforeAll (startWaiApp server) $ afterAll endWaiApp $ do
162162 mgr <- C.newManager C.defaultManagerSettings
163163 -- In proper situation, extra headers should probably be visible in API type.
164164 -- However, testing for response timeout is difficult, so we test with something which is easy to observe
165− let createClientRequest url r = fmap (\req -> req { C.requestHeaders = [("X-Added-Header", "XXX")] })
166− (defaultMakeClientRequest url r)
165+ let createClientRequest url r = (defaultMakeClientRequest url r) { C.requestHeaders = [("X-Added-Header", "XXX")] }
167166 clientEnv = (mkClientEnv mgr baseUrl) { makeClientRequest = createClientRequest }
168167 res <- runClientM (getRawSuccessPassHeaders HTTP.methodGet) clientEnv
169168 case res of
servant-docs/src/Servant/Docs/Internal.hs−4
@@ -62,7 +62,6 @@ import GHC.TypeLits
6262import Servant.API
6363import Servant.API.ContentTypes
6464import Servant.API.TypeLevel
65−import Servant.API.Generic
6665
6766import qualified Data.Universe.Helpers as U
6867
@@ -1151,9 +1150,6 @@ instance (ToAuthInfo (BasicAuth realm usr), HasDocs api) => HasDocs (BasicAuth r
11511150 authProxy = Proxy :: Proxy (BasicAuth realm usr)
11521151 action' = over authInfo (|> toAuthInfo authProxy) action
11531152
1154−instance HasDocs (ToServantApi api) => HasDocs (NamedRoutes api) where
1155− docsFor Proxy = docsFor (Proxy :: Proxy (ToServantApi api))
1156−
11571153-- ToSample instances for simple types
11581154instance ToSample NoContent
11591155instance ToSample Bool
servant-swagger/src/Servant/Swagger.hs−2
@@ -55,7 +55,6 @@ import Servant.Swagger.Internal.Orphans ()
5555-- >>> import Data.Typeable
5656-- >>> import GHC.Generics
5757-- >>> import Servant.API
58−-- >>> import System.Environment
5958-- >>> import Test.Hspec
6059-- >>> import Test.QuickCheck
6160-- >>> import qualified Data.ByteString.Lazy.Char8 as BSL8
@@ -65,7 +64,6 @@ import Servant.Swagger.Internal.Orphans ()
6564-- >>> :set -XGeneralizedNewtypeDeriving
6665-- >>> :set -XOverloadedStrings
6766-- >>> :set -XTypeOperators
68−-- >>> setEnv "HSPEC_COLOR" "no"
6967-- >>> data User = User { name :: String, age :: Int } deriving (Show, Generic, Typeable)
7068-- >>> newtype UserId = UserId Integer deriving (Show, Generic, Typeable, ToJSON)
7169-- >>> instance ToJSON User
servant-swagger/src/Servant/Swagger/Internal.hs−11
@@ -3,13 +3,11 @@
33{-# LANGUAGE DataKinds #-}
44{-# LANGUAGE FlexibleContexts #-}
55{-# LANGUAGE FlexibleInstances #-}
6−{-# LANGUAGE OverloadedLists #-}
76{-# LANGUAGE OverloadedStrings #-}
87{-# LANGUAGE PolyKinds #-}
98{-# LANGUAGE RankNTypes #-}
109{-# LANGUAGE ScopedTypeVariables #-}
1110{-# LANGUAGE TypeOperators #-}
12−{-# LANGUAGE TypeFamilies #-}
1311#if __GLASGOW_HASKELL__ >= 806
1412{-# LANGUAGE UndecidableInstances #-}
1513#endif
@@ -32,13 +30,11 @@ import qualified Data.Swagger as Swagger
3230import Data.Swagger.Declare
3331import Data.Text (Text)
3432import qualified Data.Text as Text
35−import GHC.Generics (D1, Meta(..), Rep)
3633import GHC.TypeLits
3734import Network.HTTP.Media (MediaType)
3835import Servant.API
3936import Servant.API.Description (FoldDescription,
4037 reflectDescription)
41−import Servant.API.Generic (ToServantApi, AsApi)
4238import Servant.API.Modifiers (FoldRequired)
4339
4440import Servant.Swagger.Internal.TypeLevel.API
@@ -153,10 +149,6 @@ mkEndpointNoContentVerb path _ = mempty
153149addParam :: Param -> Swagger -> Swagger
154150addParam param = allOperations.parameters %~ (Inline param :)
155151
156−-- | Add a tag to every operation in the spec.
157−addTag :: Text -> Swagger -> Swagger
158−addTag tag = allOperations.tags %~ ([tag] <>)
159−
160152-- | Add accepted content types to every operation in the spec.
161153addConsumes :: [MediaType] -> Swagger -> Swagger
162154addConsumes cs = allOperations.consumes %~ (<> Just (MimeList cs))
@@ -447,9 +439,6 @@ instance (ToSchema a, Accept ct, HasSwagger sub, KnownSymbol (FoldDescription mo
447439 & required ?~ True
448440 & schema .~ ParamBody ref
449441
450−instance (HasSwagger (ToServantApi routes), KnownSymbol datatypeName, Rep (routes AsApi) ~ D1 ('MetaData datatypeName moduleName packageName isNewtype) f) => HasSwagger (NamedRoutes routes) where
451− toSwagger _ = addTag (Text.pack $ symbolVal (Proxy :: Proxy datatypeName)) (toSwagger (Proxy :: Proxy (ToServantApi routes)))
452−
453442-- =======================================================================
454443-- Below are the definitions that should be in Servant.API.ContentTypes
455444-- =======================================================================
servant-swagger/src/Servant/Swagger/Internal/Test.hs−2
@@ -29,12 +29,10 @@ import Servant.Swagger.Internal.TypeLevel
2929-- >>> import Control.Applicative
3030-- >>> import GHC.Generics
3131-- >>> import Test.QuickCheck
32−-- >>> import System.Environment (setEnv)
3332-- >>> :set -XDeriveGeneric
3433-- >>> :set -XGeneralizedNewtypeDeriving
3534-- >>> :set -XDataKinds
3635-- >>> :set -XTypeOperators
37−-- >>> setEnv "HSPEC_COLOR" "no"
3836
3937-- | Verify that every type used with @'JSON'@ content type in a servant API
4038-- has compatible @'ToJSON'@ and @'ToSchema'@ instances using @'validateToJSON'@.
servant/src/Servant/API/ContentTypes.hs+1−1
@@ -295,7 +295,7 @@ instance {-# OVERLAPPABLE #-}
295295-- then this would be taken care of. However there is no more specific instance
296296-- between that and 'MimeRender JSON a', so we do this instead
297297instance {-# OVERLAPPING #-} ( Accept ctyp ) => AllMimeRender '[ctyp] NoContent where
298− allMimeRender _ NoContent = map (, "") $ NE.toList $ contentTypes pctyp
298+ allMimeRender _ _ = map (, "") $ NE.toList $ contentTypes pctyp
299299 where
300300 pctyp = Proxy :: Proxy ctyp
301301
servant/test/Servant/API/ContentTypesSpec.hs−11
@@ -33,8 +33,6 @@ import Data.String.Conversions
3333import qualified Data.Text as TextS
3434import qualified Data.Text.Encoding as TextSE
3535import qualified Data.Text.Lazy as TextL
36−import Control.Exception
37− (evaluate)
3836import GHC.Generics
3937import Test.Hspec
4038import Test.QuickCheck
@@ -80,15 +78,6 @@ spec = describe "Servant.API.ContentTypes" $ do
8078 it "has mimeUnrender reverse mimeRender for valid top-level json " $ do
8179 property $ \x -> mimeUnrender p (mimeRender p x) == Right (x::SomeData)
8280
83− describe "The NoContent Content-Type type" $ do
84− let p = Proxy :: Proxy '[JSON]
85−
86− it "does not render any content" $
87− allMimeRender p NoContent `shouldSatisfy` (all (BSL8.null . snd))
88−
89− it "evaluates the NoContent value" $
90− evaluate (allMimeRender p (undefined :: NoContent)) `shouldThrow` anyErrorCall
91−
9281 describe "The PlainText Content-Type type" $ do
9382 let p = Proxy :: Proxy PlainText
9483