Add HasServer instance for Redirect
This commit is contained in:
parent
bfa854f20e
commit
56f639b581
3 changed files with 42 additions and 6 deletions
|
@ -74,7 +74,7 @@ import Servant.API
|
||||||
CaptureAll, Description, EmptyAPI, Fragment,
|
CaptureAll, Description, EmptyAPI, Fragment,
|
||||||
FramingRender (..), FramingUnrender (..), FromSourceIO (..),
|
FramingRender (..), FramingUnrender (..), FromSourceIO (..),
|
||||||
Header', If, IsSecure (..), NoContentVerb, QueryFlag,
|
Header', If, IsSecure (..), NoContentVerb, QueryFlag,
|
||||||
QueryParam', QueryParams, Raw, ReflectMethod (reflectMethod),
|
QueryParam', QueryParams, Raw, Redirect, ReflectMethod (reflectMethod),
|
||||||
RemoteHost, ReqBody', SBool (..), SBoolI (..), SourceIO,
|
RemoteHost, ReqBody', SBool (..), SBoolI (..), SourceIO,
|
||||||
Stream, StreamBody', Summary, ToSourceIO (..), Vault, Verb,
|
Stream, StreamBody', Summary, ToSourceIO (..), Vault, Verb,
|
||||||
WithNamedContext, WithRoutingHeader, NamedRoutes)
|
WithNamedContext, WithRoutingHeader, NamedRoutes)
|
||||||
|
@ -89,7 +89,7 @@ import Servant.API.Modifiers
|
||||||
import Servant.API.ResponseHeaders
|
import Servant.API.ResponseHeaders
|
||||||
(GetHeaders, Headers, getHeaders, getResponse)
|
(GetHeaders, Headers, getHeaders, getResponse)
|
||||||
import Servant.API.Status
|
import Servant.API.Status
|
||||||
(statusFromNat)
|
(Redirection, statusFromNat)
|
||||||
import qualified Servant.Types.SourceT as S
|
import qualified Servant.Types.SourceT as S
|
||||||
import Servant.API.TypeErrors
|
import Servant.API.TypeErrors
|
||||||
import Web.HttpApiData
|
import Web.HttpApiData
|
||||||
|
@ -102,6 +102,7 @@ import Servant.Server.Internal.Delayed
|
||||||
import Servant.Server.Internal.DelayedIO
|
import Servant.Server.Internal.DelayedIO
|
||||||
import Servant.Server.Internal.ErrorFormatter
|
import Servant.Server.Internal.ErrorFormatter
|
||||||
import Servant.Server.Internal.Handler
|
import Servant.Server.Internal.Handler
|
||||||
|
import Servant.Server.Internal.Redirect
|
||||||
import Servant.Server.Internal.Router
|
import Servant.Server.Internal.Router
|
||||||
import Servant.Server.Internal.RouteResult
|
import Servant.Server.Internal.RouteResult
|
||||||
import Servant.Server.Internal.RouterEnv
|
import Servant.Server.Internal.RouterEnv
|
||||||
|
@ -260,6 +261,23 @@ instance ( HasServer api context
|
||||||
route _ context d =
|
route _ context d =
|
||||||
EnvRouter enableRoutingHeaders $ route (Proxy :: Proxy api) context d
|
EnvRouter enableRoutingHeaders $ route (Proxy :: Proxy api) context d
|
||||||
|
|
||||||
|
-- | TODO: Documentation
|
||||||
|
instance ( HasServer api context
|
||||||
|
, HasContextEntry (MkContextWithErrorFormatter context) ErrorFormatters
|
||||||
|
, KnownSymbol location
|
||||||
|
, AllStatusesInClass Redirection api
|
||||||
|
)
|
||||||
|
=> HasServer (Redirect location :> api) context where
|
||||||
|
|
||||||
|
type ServerT (Redirect location :> api) m = ServerT api m
|
||||||
|
|
||||||
|
hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt s
|
||||||
|
|
||||||
|
route _ context d =
|
||||||
|
EnvRouter
|
||||||
|
(withLocationHeader $ symbolVal $ Proxy @location)
|
||||||
|
(route (Proxy :: Proxy api) context d)
|
||||||
|
|
||||||
allowedMethodHead :: Method -> Request -> Bool
|
allowedMethodHead :: Method -> Request -> Bool
|
||||||
allowedMethodHead method request = method == methodGet && requestMethod request == methodHead
|
allowedMethodHead method request = method == methodGet && requestMethod request == methodHead
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import Network.Wai
|
||||||
import Servant.Server.Internal.DelayedIO
|
import Servant.Server.Internal.DelayedIO
|
||||||
import Servant.Server.Internal.Handler
|
import Servant.Server.Internal.Handler
|
||||||
import Servant.Server.Internal.RouterEnv
|
import Servant.Server.Internal.RouterEnv
|
||||||
(RouterEnv (..), hRoutedPathHeader, routedPathRepr)
|
(RouterEnv (..), hLocationHeader, hRoutedPathHeader, routedPathRepr)
|
||||||
import Servant.Server.Internal.RouteResult
|
import Servant.Server.Internal.RouteResult
|
||||||
import Servant.Server.Internal.ServerError
|
import Servant.Server.Internal.ServerError
|
||||||
|
|
||||||
|
@ -266,11 +266,17 @@ runAction action env req respond k = runResourceT $
|
||||||
e <- runHandler a
|
e <- runHandler a
|
||||||
case e of
|
case e of
|
||||||
Left err -> return . Route . withRoutingHeaders $ responseServerError err
|
Left err -> return . Route . withRoutingHeaders $ responseServerError err
|
||||||
Right x -> return $! withRoutingHeaders <$> k x
|
Right x -> return $! withHeaders <$> k x
|
||||||
withRoutingHeaders :: Response -> Response
|
withRoutingHeaders :: Response -> Response
|
||||||
withRoutingHeaders = if shouldReturnRoutedPath env
|
withRoutingHeaders = if shouldReturnRoutedPath env
|
||||||
then mapResponseHeaders ((hRoutedPathHeader, cs $ routedPathRepr env) :)
|
then mapResponseHeaders ((hRoutedPathHeader, cs $ routedPathRepr env) :)
|
||||||
else id
|
else id
|
||||||
|
withLocationHeader :: Response -> Response
|
||||||
|
withLocationHeader = case locationHeader env of
|
||||||
|
Nothing -> id
|
||||||
|
Just location -> mapResponseHeaders ((hLocationHeader, cs location) :)
|
||||||
|
withHeaders :: Response -> Response
|
||||||
|
withHeaders = withLocationHeader . withRoutingHeaders
|
||||||
|
|
||||||
{- Note [Existential Record Update]
|
{- Note [Existential Record Update]
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
@ -23,14 +23,20 @@ import Network.HTTP.Types.Header
|
||||||
(HeaderName)
|
(HeaderName)
|
||||||
|
|
||||||
data RouterEnv env = RouterEnv
|
data RouterEnv env = RouterEnv
|
||||||
{ routedPath :: [PathPiece]
|
{ locationHeader :: Maybe String
|
||||||
|
, routedPath :: [PathPiece]
|
||||||
, shouldReturnRoutedPath :: Bool
|
, shouldReturnRoutedPath :: Bool
|
||||||
, routerEnv :: env
|
, routerEnv :: env
|
||||||
}
|
}
|
||||||
deriving Functor
|
deriving Functor
|
||||||
|
|
||||||
emptyEnv :: a -> RouterEnv a
|
emptyEnv :: a -> RouterEnv a
|
||||||
emptyEnv v = RouterEnv [] False v
|
emptyEnv v = RouterEnv
|
||||||
|
{ locationHeader = Nothing
|
||||||
|
, routedPath = []
|
||||||
|
, shouldReturnRoutedPath = False
|
||||||
|
, routerEnv = v
|
||||||
|
}
|
||||||
|
|
||||||
enableRoutingHeaders :: RouterEnv env -> RouterEnv env
|
enableRoutingHeaders :: RouterEnv env -> RouterEnv env
|
||||||
enableRoutingHeaders env = env { shouldReturnRoutedPath = True }
|
enableRoutingHeaders env = env { shouldReturnRoutedPath = True }
|
||||||
|
@ -61,5 +67,11 @@ toCaptureTag hint = captureName hint <> "::" <> (T.pack . show) (captureType hin
|
||||||
toCaptureTags :: [CaptureHint] -> Text
|
toCaptureTags :: [CaptureHint] -> Text
|
||||||
toCaptureTags hints = "<" <> T.intercalate "|" (map toCaptureTag hints) <> ">"
|
toCaptureTags hints = "<" <> T.intercalate "|" (map toCaptureTag hints) <> ">"
|
||||||
|
|
||||||
|
withLocationHeader :: String -> RouterEnv a -> RouterEnv a
|
||||||
|
withLocationHeader loc env = env { locationHeader = Just loc}
|
||||||
|
|
||||||
hRoutedPathHeader :: HeaderName
|
hRoutedPathHeader :: HeaderName
|
||||||
hRoutedPathHeader = "Servant-Routed-Path"
|
hRoutedPathHeader = "Servant-Routed-Path"
|
||||||
|
|
||||||
|
hLocationHeader :: HeaderName
|
||||||
|
hLocationHeader = "Location"
|
||||||
|
|
Loading…
Add table
Reference in a new issue