Haskell Servant中如何可选捕获路径段?
为Servant应用添加向后兼容的国际化路径支持
我需要以向后兼容的方式为Servant应用添加国际化支持,要求将语言代码设为可选路径段:
- 若首个路径段属于已知语言代码列表,则使用该语言,处理器接收
Just 语言代码 - 否则默认传入
Nothing,服务端将其解析为默认语言
示例:
/some/path => myHandler Nothing /en/some/path => myHandler (Just "en") /fr/some/path => myHandler (Just "fr")
为避免编写重复代码(无需为每个端点实现带语言段和不带语言段的两种版本,处理器也无需对应两种变体),我尝试编写一个Servant组合子,检查请求的head $ pathInfo req,若为语言代码则捕获,否则传递Nothing给子服务。但当前实现始终要求pathSegment必须存在,无法实现可选捕获,代码如下:
data HostWithLocale = HostWithLocale instance (HasServer api context) => HasServer (HostWithLocale :> api) context where type ServerT (HostWithLocale :> api) m = (Hostname, Maybe LanguageCode) -> ServerT api m hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt . s route _ context server = CaptureRouter [hint] $ route (Proxy :: Proxy api) context subserver where hint = CaptureHint "language" (typeRep (Proxy :: Proxy (Hostname, Maybe LanguageCode))) subserver = addCapture server $ \pathSegment -> withRequest $ \req -> case DL.lookup (fromString "Host") (requestHeaders req) of Nothing -> delayedFail err406 Just hname -> if Prelude.not (isWhiteListedDomain hname) then delayedFail err406 else if pathSegment `DL.elem` knownLanguageCodes then pure $ (toS hname, Just $ LanguageCode pathSegment) else pure $ (toS hname, Nothing) isWhiteListedDomain :: C8.ByteString -> Bool isWhiteListedDomain = undefined knownLanguageCodes :: [Text] knownLanguageCodes = undefined
内容的提问来源于stack exchange,提问作者Saurabh Nanda
相关产品推荐
相关产品推荐

