Allow BaseUrl to specify whether root has slash.

Previously this would cause an error with double slashes.
This commit is contained in:
Julian K. Arni 2018-02-09 15:17:37 +01:00
parent e8e62d6d99
commit 742c9906a0
2 changed files with 24 additions and 1 deletions

View file

@ -25,6 +25,7 @@ import Control.Monad.Trans.Control (MonadBaseControl (..))
import Control.Monad.Trans.Except import Control.Monad.Trans.Except
import Data.ByteString.Builder (toLazyByteString) import Data.ByteString.Builder (toLazyByteString)
import qualified Data.ByteString.Lazy as BSL import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString.Lazy.Char8 as BSLC
import Data.Foldable (toList, for_) import Data.Foldable (toList, for_)
import Data.Functor.Alt (Alt (..)) import Data.Functor.Alt (Alt (..))
import Data.Maybe (maybeToList) import Data.Maybe (maybeToList)
@ -166,7 +167,7 @@ requestToClientRequest burl r = Client.defaultRequest
, Client.port = baseUrlPort burl , Client.port = baseUrlPort burl
, Client.path = BSL.toStrict , Client.path = BSL.toStrict
$ fromString (baseUrlPath burl) $ fromString (baseUrlPath burl)
<> toLazyByteString (requestPath r) </> toLazyByteString (requestPath r)
, Client.queryString = renderQuery True . toList $ requestQueryString r , Client.queryString = renderQuery True . toList $ requestQueryString r
, Client.requestHeaders = , Client.requestHeaders =
maybeToList acceptHdr ++ maybeToList contentTypeHdr ++ headers maybeToList acceptHdr ++ maybeToList contentTypeHdr ++ headers
@ -197,3 +198,13 @@ catchConnectionError :: IO a -> IO (Either ServantError a)
catchConnectionError action = catchConnectionError action =
catch (Right <$> action) $ \e -> catch (Right <$> action) $ \e ->
pure . Left . ConnectionError . T.pack $ show (e :: Client.HttpException) pure . Left . ConnectionError . T.pack $ show (e :: Client.HttpException)
-- Concatenate path components, making sure there's exactly one slash between
-- them, unless they're both empty.
(</>) :: BSL.ByteString -> BSL.ByteString -> BSL.ByteString
a </> b = case (BSLC.unsnoc a, BSLC.uncons b) of
(Just (_, '/') , Just ('/', tailB)) -> a <> tailB
(Just (_, '/') , _ ) -> a <> b
(_ , Just ('/', _ )) -> a <> b
(_ , Nothing ) -> a
(_ , _ ) -> a <> "/" <> b

View file

@ -367,6 +367,18 @@ sucessSpec = beforeAll (startWaiApp server) $ afterAll endWaiApp $ do
Left e -> assertFailure $ show e Left e -> assertFailure $ show e
Right val -> getHeaders val `shouldBe` [("X-Example1", "1729"), ("X-Example2", "eg2")] Right val -> getHeaders val `shouldBe` [("X-Example1", "1729"), ("X-Example2", "eg2")]
describe "baseUrl" $ do
it "accepts urls with trailing slashes without modifying non-root paths"
$ \(_, burl) -> do
left show <$> runClient getGet (burl { baseUrlPath = baseUrlPath burl ++ "/"} )
`shouldReturn` Right alice
it "still works with root paths when it has a trailing slash"
$ \(_, burl) -> do
left show <$> runClient getRoot (burl { baseUrlPath = baseUrlPath burl ++ "/"} )
`shouldReturn` Right carol
modifyMaxSuccess (const 20) $ do modifyMaxSuccess (const 20) $ do
it "works for a combination of Capture, QueryParam, QueryFlag and ReqBody" $ \(_, baseUrl) -> it "works for a combination of Capture, QueryParam, QueryFlag and ReqBody" $ \(_, baseUrl) ->
property $ forAllShrink pathGen shrink $ \(NonEmpty cap) num flag body -> property $ forAllShrink pathGen shrink $ \(NonEmpty cap) num flag body ->