@@ -17,8 +17,10 @@ import Prelude.Compat
18import Control.Monad
18import Control.Monad
19 (forM_, unless, when)
19 (forM_, unless, when)
20+import Control.Monad.Reader (runReaderT, ask)
20import Control.Monad.Error.Class
21import Control.Monad.Error.Class
21 (MonadError (..))
22 (MonadError (..))
23+import Control.Monad.IO.Class (MonadIO(..))
22import Data.Aeson
24import Data.Aeson
23 (FromJSON, ToJSON, decode', encode)
25 (FromJSON, ToJSON, decode', encode)
24import Data.Acquire
26import Data.Acquire
@@ -54,19 +56,19 @@ import Servant.API
54 Delete, EmptyAPI, Fragment, Get, HasStatus (StatusOf), Header,
56 Delete, EmptyAPI, Fragment, Get, HasStatus (StatusOf), Header,
55 Headers, HttpVersion, IsSecure (..), JSON, Lenient,
57 Headers, HttpVersion, IsSecure (..), JSON, Lenient,
56 NoContent (..), NoContentVerb, NoFraming, OctetStream, Patch,
58 NoContent (..), NoContentVerb, NoFraming, OctetStream, Patch,
57− PlainText, Post, Put, QueryFlag, QueryParam, QueryParams, Raw,
59+ PlainText, Post, Put, QueryFlag, QueryParam, QueryParams, Raw, RawM,
58 RemoteHost, ReqBody, SourceIO, StdMethod (..), Stream, Strict,
60 RemoteHost, ReqBody, SourceIO, StdMethod (..), Stream, Strict,
59 UVerb, Union, Verb, WithStatus (..), addHeader)
61 UVerb, Union, Verb, WithStatus (..), addHeader)
60import Servant.Server
62import Servant.Server
61− (Context ((:.), EmptyContext), Handler, Server, Tagged (..),
63+ (Context ((:.), EmptyContext), Handler, Server, ServerT, Tagged (..),
62− emptyServer, err401, err403, err404, respond, serve,
64+ emptyServer, err401, err403, err404, hoistServer, respond, serve,
63 serveWithContext)
65 serveWithContext)
64import Servant.Test.ComprehensiveAPI
66import Servant.Test.ComprehensiveAPI
65import qualified Servant.Types.SourceT as S
67import qualified Servant.Types.SourceT as S
66import Test.Hspec
68import Test.Hspec
67 (Spec, context, describe, it, shouldBe, shouldContain)
69 (Spec, context, describe, it, shouldBe, shouldContain)
68import Test.Hspec.Wai
70import Test.Hspec.Wai
69− (get, liftIO, matchHeaders, matchStatus, shouldRespondWith,
71+ (get, matchHeaders, matchStatus, shouldRespondWith,
70 with, (<:>))
72 with, (<:>))
71import qualified Test.Hspec.Wai as THW
73import qualified Test.Hspec.Wai as THW
@@ -102,6 +104,7 @@ spec = do
102 reqBodySpec
104 reqBodySpec
103 headerSpec
105 headerSpec
105 alternativeSpec
108 alternativeSpec
106 responseHeadersSpec
109 responseHeadersSpec
107 uverbResponseHeadersSpec
110 uverbResponseHeadersSpec
@@ -610,6 +613,46 @@ rawSpec = do
612------------------------------------------------------------------------------
615------------------------------------------------------------------------------
617+------------------------------------------------------------------------------
619+type RawMApi = "foo" :> RawM
621+rawMApi :: Proxy RawMApi
624+rawMServer :: (Monad m, MonadIO m, Show a) => (Request -> m a) -> ServerT RawMApi m
625+rawMServer f req resp = liftIO . resp . responseLBS ok200 [] . cs . show =<< f req
629+ describe "Servant.API.RawM" $ do
630+ it "gives access to monadic context" $ do
631+ flip runSession (serve rawMApi
632+ (hoistServer rawMApi (flip runReaderT (42 :: Integer)) (rawMServer (const ask)))) $ do
633+ response <- Network.Wai.Test.request defaultRequest{
637+ simpleBody response `shouldBe` "42"
639+ it "lets users throw servant errors" $ do
640+ flip runSession (serve rawMApi (rawMServer (const $ throwError err404 >> pure (42 :: Integer)))) $ do
641+ response <- Network.Wai.Test.request defaultRequest{
645+ statusCode (simpleStatus response) `shouldBe` 404
647+ it "gets the pathInfo modified" $ do
648+ flip runSession (serve rawMApi (rawMServer (pure . pathInfo))) $ do
649+ response <- Network.Wai.Test.request defaultRequest{
650+ pathInfo = ["foo", "bar"]
653+ simpleBody response `shouldBe` cs (show ["bar" :: String])
655+------------------------------------------------------------------------------
613-- * alternativeSpec {{{
656-- * alternativeSpec {{{
614------------------------------------------------------------------------------
657------------------------------------------------------------------------------
615type AlternativeApi =
658type AlternativeApi =