@@ -14,7 +14,6 @@
1414
1515module Servant.Server.Internal
1616 ( module Servant.Server.Internal
17− , module Servant.Server.Internal.PathInfo
1817 , module Servant.Server.Internal.Router
1918 , module Servant.Server.Internal.RoutingApplication
2019 , module Servant.Server.Internal.ServantErr
@@ -31,8 +30,6 @@ import Data.Maybe (mapMaybe, fromMaybe)
3130import Data.String (fromString)
3231import Data.String.Conversions (cs, (<>), ConvertibleStrings)
3332import Data.Text (Text)
34−import qualified Data.Text as T
35−import Data.Text.Encoding (encodeUtf8)
3633import Data.Typeable
3734import GHC.TypeLits (KnownSymbol, symbolVal)
3835import Network.HTTP.Types hiding (Header, ResponseHeaders)
@@ -41,11 +38,10 @@ import Network.Wai (Application, lazyRequestBody,
4138 rawQueryString, requestHeaders,
4239 requestMethod, responseLBS, remoteHost,
4340 isSecure, vault, httpVersion, Response,
44− Request)
41+ Request, pathInfo)
4542import Servant.API ((:<|>) (..), (:>), Capture,
4643 Delete, Get, Header,
47− IsSecure(..), MatrixFlag, MatrixParam,
48− MatrixParams, Patch, Post, Put,
44+ IsSecure(..), Patch, Post, Put,
4945 QueryFlag, QueryParam, QueryParams,
5046 Raw, RemoteHost, ReqBody, Vault)
5147import Servant.API.ContentTypes (AcceptHeader (..),
@@ -54,7 +50,6 @@ import Servant.API.ContentTypes (AcceptHeader (..),
5450import Servant.API.ResponseHeaders (Headers, getResponse, GetHeaders,
5551 getHeaders)
5652
57−import Servant.Server.Internal.PathInfo
5853import Servant.Server.Internal.Router
5954import Servant.Server.Internal.RoutingApplication
6055import Servant.Server.Internal.ServantErr
@@ -548,123 +543,6 @@ instance (KnownSymbol sym, HasServer sublayout)
548543 examine v | v == "true" || v == "1" || v == "" = True
549544 | otherwise = False
550545
551−parseMatrixText :: B.ByteString -> QueryText
552−parseMatrixText = parseQueryText
553−
554−-- | If you use @'MatrixParam' "author" Text@ in one of the endpoints for your API,
555−-- this automatically requires your server-side handler to be a function
556−-- that takes an argument of type @'Maybe' 'Text'@.
557−--
558−-- This lets servant worry about looking it up in the query string
559−-- and turning it into a value of the type you specify, enclosed
560−-- in 'Maybe', because it may not be there and servant would then
561−-- hand you 'Nothing'.
562−--
563−-- You can control how it'll be converted from 'Text' to your type
564−-- by simply providing an instance of 'FromHttpApiData' for your type.
565−--
566−-- Example:
567−--
568−-- > type MyApi = "books" :> MatrixParam "author" Text :> Get [Book]
569−-- >
570−-- > server :: Server MyApi
571−-- > server = getBooksBy
572−-- > where getBooksBy :: Maybe Text -> ExceptT ServantErr IO [Book]
573−-- > getBooksBy Nothing = ...return all books...
574−-- > getBooksBy (Just author) = ...return books by the given author...
575−instance (KnownSymbol sym, FromHttpApiData a, HasServer sublayout)
576− => HasServer (MatrixParam sym a :> sublayout) where
577−
578− type ServerT (MatrixParam sym a :> sublayout) m =
579− Maybe a -> ServerT sublayout m
580−
581− route Proxy subserver = WithRequest $ \ request ->
582− case parsePathInfo request of
583− (first : _)
584− -> do let querytext = parseMatrixText . encodeUtf8 $ T.tail first
585− param = case lookup paramname querytext of
586− Nothing -> Nothing -- param absent from the query string
587− Just Nothing -> Nothing -- param present with no value -> Nothing
588− Just (Just v) -> parseQueryParamMaybe v -- if present, we try to convert to
589− -- the right type
590− route (Proxy :: Proxy sublayout) (feedTo subserver param)
591− _ -> route (Proxy :: Proxy sublayout) (feedTo subserver Nothing)
592−
593− where paramname = cs $ symbolVal (Proxy :: Proxy sym)
594−
595−-- | If you use @'MatrixParams' "authors" Text@ in one of the endpoints for your API,
596−-- this automatically requires your server-side handler to be a function
597−-- that takes an argument of type @['Text']@.
598−--
599−-- This lets servant worry about looking up 0 or more values in the query string
600−-- associated to @authors@ and turning each of them into a value of
601−-- the type you specify.
602−--
603−-- You can control how the individual values are converted from 'Text' to your type
604−-- by simply providing an instance of 'FromHttpApiData' for your type.
605−--
606−-- Example:
607−--
608−-- > type MyApi = "books" :> MatrixParams "authors" Text :> Get [Book]
609−-- >
610−-- > server :: Server MyApi
611−-- > server = getBooksBy
612−-- > where getBooksBy :: [Text] -> ExceptT ServantErr IO [Book]
613−-- > getBooksBy authors = ...return all books by these authors...
614−instance (KnownSymbol sym, FromHttpApiData a, HasServer sublayout)
615− => HasServer (MatrixParams sym a :> sublayout) where
616−
617− type ServerT (MatrixParams sym a :> sublayout) m =
618− [a] -> ServerT sublayout m
619−
620− route Proxy subserver = WithRequest $ \ request ->
621− case parsePathInfo request of
622− (first : _)
623− -> do let matrixtext = parseMatrixText . encodeUtf8 $ T.tail first
624− -- if sym is "foo", we look for matrix parameters
625− -- named "foo" or "foo[]" and call parseQueryParam on the
626− -- corresponding values
627− parameters = filter looksLikeParam matrixtext
628− values = mapMaybe (convert . snd) parameters
629− route (Proxy :: Proxy sublayout) (feedTo subserver values)
630− _ -> route (Proxy :: Proxy sublayout) (feedTo subserver [])
631− where paramname = cs $ symbolVal (Proxy :: Proxy sym)
632− looksLikeParam (name, _) = name == paramname || name == (paramname <> "[]")
633− convert Nothing = Nothing
634− convert (Just v) = parseQueryParamMaybe v
635−
636−-- | If you use @'MatrixFlag' "published"@ in one of the endpoints for your API,
637−-- this automatically requires your server-side handler to be a function
638−-- that takes an argument of type 'Bool'.
639−--
640−-- Example:
641−--
642−-- > type MyApi = "books" :> MatrixFlag "published" :> Get [Book]
643−-- >
644−-- > server :: Server MyApi
645−-- > server = getBooks
646−-- > where getBooks :: Bool -> ExceptT ServantErr IO [Book]
647−-- > getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument...
648−instance (KnownSymbol sym, HasServer sublayout)
649− => HasServer (MatrixFlag sym :> sublayout) where
650−
651− type ServerT (MatrixFlag sym :> sublayout) m =
652− Bool -> ServerT sublayout m
653−
654− route Proxy subserver = WithRequest $ \ request ->
655− case parsePathInfo request of
656− (first : _)
657− -> do let matrixtext = parseMatrixText . encodeUtf8 $ T.tail first
658− param = case lookup paramname matrixtext of
659− Just Nothing -> True -- param is there, with no value
660− Just (Just v) -> examine v -- param with a value
661− Nothing -> False -- param not in the query string
662− route (Proxy :: Proxy sublayout) (feedTo subserver param)
663− _ -> route (Proxy :: Proxy sublayout) (feedTo subserver False)
664− where paramname = cs $ symbolVal (Proxy :: Proxy sym)
665− examine v | v == "true" || v == "1" || v == "" = True
666− | otherwise = False
667−
668546-- | Just pass the request to the underlying application and serve its response.
669547--
670548-- Example:
@@ -762,5 +640,11 @@ instance HasServer api => HasServer (HttpVersion :> api) where
762640 route Proxy subserver = WithRequest $ \req ->
763641 route (Proxy :: Proxy api) (feedTo subserver $ httpVersion req)
764642
643+pathIsEmpty :: Request -> Bool
644+pathIsEmpty = go . pathInfo
645+ where go [] = True
646+ go [""] = True
647+ go _ = False
648+
765649ct_wildcard :: B.ByteString
766650ct_wildcard = "*" <> "/" <> "*" -- Because CPP