4
4
{-# LANGUAGE FlexibleContexts #-}
5
5
{-# LANGUAGE FlexibleInstances #-}
6
6
{-# LANGUAGE GADTs #-}
7
+ {-# LANGUAGE LambdaCase #-}
7
8
{-# LANGUAGE MultiParamTypeClasses #-}
8
9
{-# LANGUAGE OverloadedStrings #-}
9
10
{-# LANGUAGE PolyKinds #-}
15
16
{-# OPTIONS_GHC -freduction-depth=100 #-}
16
17
{-# OPTIONS_GHC -fno-warn-orphans #-}
17
18
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
18
- {-# LANGUAGE EmptyCase #-}
19
19
20
20
module Servant.ClientTestUtils where
21
21
22
22
import Prelude ()
23
23
import Prelude.Compat
24
24
25
- import Control.Concurrent
26
- (ThreadId , forkIO , killThread )
27
- import Control.Monad
28
- (join )
29
- import Control.Monad.Error.Class
30
- (throwError )
25
+ import Control.Concurrent (ThreadId , forkIO , killThread )
26
+ import Control.Monad (join )
27
+ import Control.Monad.Error.Class (throwError )
31
28
import Data.Aeson
32
- import Data.ByteString
33
- ( ByteString )
29
+ import Data.ByteString ( ByteString )
30
+ import Data.ByteString.Builder ( byteString )
34
31
import qualified Data.ByteString.Char8 as C8
35
- import Data.ByteString.Builder
36
- (byteString )
37
32
import qualified Data.ByteString.Lazy as LazyByteString
38
- import Data.Char
39
- (chr , isPrint )
40
- import Data.Maybe (fromMaybe )
33
+ import Data.Char (chr , isPrint )
34
+ import Data.Maybe (fromMaybe )
41
35
import Data.Monoid ()
42
36
import Data.Proxy
43
37
import Data.SOP
44
- import Data.Text
45
- (Text )
38
+ import Data.Text (Text )
46
39
import qualified Data.Text as Text
47
- import Data.Text.Encoding
48
- (decodeUtf8 , encodeUtf8 )
49
- import GHC.Generics
50
- (Generic )
51
- import qualified Generics.SOP as GSOP
40
+ import Data.Text.Encoding (decodeUtf8 , encodeUtf8 )
41
+ import qualified Generics.SOP as GSOP
42
+ import GHC.Generics (Generic )
52
43
import qualified Network.HTTP.Client as C
53
44
import qualified Network.HTTP.Types as HTTP
54
45
import Network.Socket
55
46
import qualified Network.Wai as Wai
56
47
import Network.Wai.Handler.Warp
57
- import System.IO.Unsafe
58
- (unsafePerformIO )
48
+ import System.IO.Unsafe (unsafePerformIO )
59
49
import Test.QuickCheck
60
- import Text.Read (readMaybe )
61
- import Web.FormUrlEncoded
62
- (FromForm , ToForm )
50
+ import Text.Read (readMaybe )
51
+ import Web.FormUrlEncoded (FromForm , ToForm )
63
52
64
53
import Servant.API
65
- ((:<|>) ((:<|>) ), (:>) , AuthProtect , BasicAuth ,
66
- BasicAuthData (.. ), Capture , CaptureAll , DeepQuery , DeleteNoContent ,
67
- EmptyAPI , FormUrlEncoded , Fragment , FromHttpApiData (.. ), Get , Header , Headers ,
68
- JSON , MimeRender (mimeRender ), MimeUnrender (mimeUnrender ),
54
+ (AuthProtect , BasicAuth , BasicAuthData (.. ), Capture ,
55
+ CaptureAll , DeepQuery , DeleteNoContent , EmptyAPI ,
56
+ FormUrlEncoded , Fragment , FromHttpApiData (.. ), Get , Header ,
57
+ Headers , Host , JSON , MimeRender (mimeRender ),
58
+ MimeUnrender (mimeUnrender ), NamedRoutes ,
69
59
NoContent (NoContent ), PlainText , Post , QueryFlag , QueryParam ,
70
- QueryParams , QueryString , Raw , ReqBody , StdMethod (GET ), ToHttpApiData (.. ),
71
- UVerb , Union , Verb , WithStatus (WithStatus ), NamedRoutes , addHeader , Host )
72
- import Servant.API.Generic ((:-) )
73
- import Servant.API.QueryString (FromDeepQuery (.. ), ToDeepQuery (.. ))
60
+ QueryParams , QueryString , Raw , ReqBody , StdMethod (GET ),
61
+ ToHttpApiData (.. ), UVerb , Union , Verb ,
62
+ WithStatus (WithStatus ), addHeader , (:<|>) ((:<|>) ), (:>) )
63
+ import Servant.API.Generic ((:-) )
64
+ import Servant.API.MultiVerb
65
+ import Servant.API.QueryString
66
+ (FromDeepQuery (.. ), ToDeepQuery (.. ))
67
+ import Servant.API.Range
74
68
import Servant.Client
75
69
import qualified Servant.Client.Core.Auth as Auth
76
70
import Servant.Server
77
71
import Servant.Server.Experimental.Auth
78
72
import Servant.Test.ComprehensiveAPI
79
- import Servant.API.MultiVerb
80
73
81
74
-- This declaration simply checks that all instances are in place.
82
75
_ = client comprehensiveAPIWithoutStreaming
@@ -152,7 +145,7 @@ instance ToDeepQuery Filter where
152
145
-----------------------------
153
146
154
147
-- This is the list of all possible responses
155
- type MultipleChoicesIntResponses =
148
+ type MultipleChoicesIntResponses =
156
149
'[ RespondEmpty 400 " Negative"
157
150
, Respond 200 " Even number" Bool
158
151
, Respond 200 " Odd number" Int
@@ -222,6 +215,7 @@ type Api =
222
215
:<|> " multiple-choices-int" :> MultipleChoicesInt
223
216
:<|> " captureVerbatim" :> Capture " someString" Verbatim :> Get '[PlainText ] Text
224
217
:<|> " host-test" :> Host " servant.example" :> Get '[JSON ] Bool
218
+ :<|> PaginatedAPI
225
219
226
220
api :: Proxy Api
227
221
api = Proxy
@@ -258,6 +252,7 @@ recordRoutes :: RecordRoutes (AsClientT ClientM)
258
252
multiChoicesInt :: Int -> ClientM MultipleChoicesIntResult
259
253
captureVerbatim :: Verbatim -> ClientM Text
260
254
getHost :: ClientM Bool
255
+ getPaginatedPerson :: Maybe (Range 1 100 ) -> ClientM [Person ]
261
256
262
257
getRoot
263
258
:<|> getGet
@@ -288,7 +283,8 @@ getRoot
288
283
:<|> recordRoutes
289
284
:<|> multiChoicesInt
290
285
:<|> captureVerbatim
291
- :<|> getHost = client api
286
+ :<|> getHost
287
+ :<|> getPaginatedPerson = client api
292
288
293
289
server :: Application
294
290
server = serve api (
@@ -299,10 +295,10 @@ server = serve api (
299
295
:<|> (\ name -> return $ Person name 0 )
300
296
:<|> (\ names -> return (zipWith Person names [0 .. ]))
301
297
:<|> return
302
- :<|> (\ name -> case name of
303
- Just " alice" -> return alice
304
- Just n -> throwError $ ServerError 400 (n ++ " not found" ) " " []
305
- Nothing -> throwError $ ServerError 400 " missing parameter" " " [] )
298
+ :<|> (\ case
299
+ Just " alice" -> return alice
300
+ Just n -> throwError $ ServerError 400 (n ++ " not found" ) " " []
301
+ Nothing -> throwError $ ServerError 400 " missing parameter" " " [] )
306
302
:<|> const (Tagged $ \ request respond ->
307
303
respond . maybe (Wai. responseLBS HTTP. notFound404 [] " Missing: payload" )
308
304
(Wai. responseLBS HTTP. ok200 [] . LazyByteString. fromStrict)
@@ -338,21 +334,22 @@ server = serve api (
338
334
:<|> RecordRoutes
339
335
{ version = pure 42
340
336
, echo = pure
341
- , otherRoutes = \ _ -> OtherRoutes
337
+ , otherRoutes = const OtherRoutes
342
338
{ something = pure [" foo" , " bar" , " pweet" ]
343
339
}
344
340
}
345
- :<|> (\ param ->
346
- if param < 0
341
+ :<|> (\ param ->
342
+ if param < 0
347
343
then pure NegativeNumber
348
344
else
349
- if even param
345
+ if even param
350
346
then pure $ Odd 3
351
347
else pure $ Even True
352
348
)
353
-
349
+
354
350
:<|> pure . decodeUtf8 . unVerbatim
355
351
:<|> pure True
352
+ :<|> usersServer
356
353
)
357
354
358
355
-- * api for testing failures
@@ -473,3 +470,14 @@ instance ToHttpApiData Verbatim where
473
470
474
471
instance FromHttpApiData Verbatim where
475
472
parseUrlPiece = pure . Verbatim . encodeUtf8
473
+
474
+ -- * range type example
475
+
476
+ type PaginatedAPI =
477
+ " users" :> QueryParam " page" (Range 1 100 ) :> Get '[JSON ] [Person ]
478
+
479
+ usersServer :: Maybe (Range 1 100 ) -> Handler [Person ]
480
+ usersServer mpage = do
481
+ let pageNum = maybe 1 unRange mpage
482
+ -- pageNum is guaranteed to be between 1 and 100
483
+ return [Person " Example" $ fromIntegral pageNum]
0 commit comments