Skip to content

Commit a2c0a55

Browse files
committed
Write tests for Optional ReqBody' and fix some cases
1 parent a6be2ee commit a2c0a55

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

servant-server/src/Servant/Server/Internal.hs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ import qualified Data.ByteString.Lazy as BL
4949
import Data.Constraint (Constraint, Dict(..))
5050
import Data.Either
5151
(partitionEithers)
52-
import Data.Function
53-
((&))
5452
import Data.Maybe
5553
(fromMaybe, isNothing, mapMaybe, maybeToList)
5654
import Data.String
@@ -681,9 +679,7 @@ instance ( AllCTUnrender list a, HasServer api context
681679
Just f -> return f
682680

683681
-- Body check, we get a body parsing functions as the first argument.
684-
bodyCheck f = withRequest $ \ request -> do
685-
mrqbody <- f <$> liftIO (lazyRequestBody request)
686-
682+
bodyCheck f = withRequest $ \ request ->
687683
let
688684
hasReqBody =
689685
case requestBodyLength request of
@@ -692,13 +688,15 @@ instance ( AllCTUnrender list a, HasServer api context
692688

693689
serverErr :: String -> ServerError
694690
serverErr = formatError rep request . cs
695-
696-
mrqbody & case (sbool :: SBool (FoldRequired mods), sbool :: SBool (FoldLenient mods), hasReqBody) of
697-
(STrue, STrue, _) -> return . bimap cs id
698-
(STrue, SFalse, _) -> either (delayedFailFatal . serverErr) return
699-
(SFalse, _, False) -> return . const Nothing
700-
(SFalse, STrue, True) -> return . Just . bimap cs id
701-
(SFalse, SFalse, True) -> either (delayedFailFatal . serverErr) (return . Just)
691+
in
692+
fmap f (liftIO $ lazyRequestBody request) >>=
693+
case (sbool :: SBool (FoldRequired mods), sbool :: SBool (FoldLenient mods), hasReqBody) of
694+
(STrue, STrue, _) -> return . bimap cs id
695+
(STrue, SFalse, _) -> either (delayedFailFatal . serverErr) return
696+
(SFalse, STrue, False) -> return . either (const Nothing) (Just . Right)
697+
(SFalse, SFalse, False) -> return . either (const Nothing) Just
698+
(SFalse, STrue, True) -> return . Just . bimap cs id
699+
(SFalse, SFalse, True) -> either (delayedFailFatal . serverErr) (return . Just)
702700

703701
instance
704702
( FramingUnrender framing, FromSourceIO chunk a, MimeUnrender ctype chunk

servant-server/test/Servant/ServerSpec.hs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ import Servant.API
5151
BasicAuthData (BasicAuthData), Capture, Capture', CaptureAll,
5252
Delete, EmptyAPI, Fragment, Get, HasStatus (StatusOf), Header,
5353
Headers, HttpVersion, IsSecure (..), JSON, Lenient,
54-
NoContent (..), NoContentVerb, NoFraming, OctetStream, Patch,
55-
PlainText, Post, Put, QueryFlag, QueryParam, QueryParams, Raw,
56-
RemoteHost, ReqBody, SourceIO, StdMethod (..), Stream, Strict,
57-
UVerb, Union, Verb, WithStatus (..), addHeader)
54+
NoContent (..), NoContentVerb, NoFraming, OctetStream,
55+
Optional, Patch, PlainText, Post, Put, QueryFlag, QueryParam,
56+
QueryParams, Raw, RemoteHost, ReqBody, ReqBody', SourceIO,
57+
StdMethod (..), Stream, Strict, UVerb, Union, Verb,
58+
WithStatus (..), addHeader)
5859
import Servant.Server
5960
(Context ((:.), EmptyContext), Handler, Server, Tagged (..),
6061
emptyServer, err401, err403, err404, respond, serve,
@@ -501,6 +502,7 @@ fragmentSpec = do
501502
------------------------------------------------------------------------------
502503
type ReqBodyApi = ReqBody '[JSON] Person :> Post '[JSON] Person
503504
:<|> "blah" :> ReqBody '[JSON] Person :> Put '[JSON] Integer
505+
:<|> "meh" :> ReqBody' '[Optional, Strict] '[JSON] Person :> Put '[JSON] Integer
504506

505507
reqBodyApi :: Proxy ReqBodyApi
506508
reqBodyApi = Proxy
@@ -509,7 +511,7 @@ reqBodySpec :: Spec
509511
reqBodySpec = describe "Servant.API.ReqBody" $ do
510512

511513
let server :: Server ReqBodyApi
512-
server = return :<|> return . age
514+
server = return :<|> return . age :<|> return . maybe 0 age
513515
mkReq method x = THW.request method x
514516
[(hContentType, "application/json;charset=utf-8")]
515517

@@ -526,6 +528,31 @@ reqBodySpec = describe "Servant.API.ReqBody" $ do
526528
THW.request methodPost "/"
527529
[(hContentType, "application/nonsense")] "" `shouldRespondWith` 415
528530

531+
describe "optional request body" $ do
532+
it "request without body succeeds" $ do
533+
THW.request methodPut "/meh" [] mempty `shouldRespondWith` 200
534+
535+
it "request without body responds with proper default value" $ do
536+
response <- THW.request methodPut "/meh" [] mempty
537+
liftIO $ simpleBody response `shouldBe` encode (0 :: Integer)
538+
539+
it "responds with 415 if the request body media type is unsupported" $ do
540+
THW.request methodPut "/meh" [(hContentType, "application/nonsense")]
541+
(encode alice) `shouldRespondWith` 415
542+
THW.request methodPut "/meh" [(hContentType, "application/octet-stream")]
543+
(encode alice) `shouldRespondWith` 415
544+
545+
it "request without body and with content-type header succeeds" $ do
546+
mkReq methodPut "/meh" mempty `shouldRespondWith` 200
547+
548+
it "request without body and with content-type header returns default value" $ do
549+
response <- mkReq methodPut "/meh" mempty
550+
liftIO $ simpleBody response `shouldBe` encode (0 :: Integer)
551+
552+
it "optional request body can be provided" $ do
553+
response <- mkReq methodPut "/meh" (encode alice)
554+
liftIO $ simpleBody response `shouldBe` encode (age alice)
555+
529556
-- }}}
530557
------------------------------------------------------------------------------
531558
-- * headerSpec {{{

0 commit comments

Comments
 (0)