Haskell Servant添加Raw端点后provideOptions类型错误解决问询
解决Servant添加Raw端点后的CORS与类型错误问题
问题根源
添加Raw端点后,provideOptions报错是因为servant-options库要求API中所有端点都实现HasForeign和GenerateList类型类,但Raw并没有对应的实例,导致类型检查失败。
解决方案:改用wai-cors中间件
放弃servant-options,使用更通用的wai-cors库处理CORS——它不依赖Servant的类型推导,直接在WAI层处理OPTIONS请求,完美兼容Raw端点。
步骤1:添加依赖
在你的cabal文件中加入wai-cors依赖:
build-depends: -- 其他已有依赖 wai-cors >= 0.2.7
步骤2:替换CORS中间件代码
删除原来的addOriginsAllowed、addAllOriginsMiddleware和optionMidlleware,替换为以下代码:
import Network.Wai.Middleware.Cors (cors, simpleCorsResourcePolicy, CorsResourcePolicy(..)) -- 配置CORS规则,生产环境建议限制具体域名 corsPolicy :: CorsResourcePolicy corsPolicy = simpleCorsResourcePolicy { corsOrigins = Just (["*"], False) , corsMethods = ["GET", "POST", "PUT", "OPTIONS"] , corsRequestHeaders = ["Content-Type", "Authorization"] } app :: Application app = cors (const $ Just corsPolicy) $ serve proxy routes
步骤3:实现Raw端点的文件服务Handler
从SFTP获取文件并返回WAI响应,示例代码如下:
import Network.Wai (Application, Response) import Network.HTTP.Types.Status (ok200) import Network.Wai.Internal (responseLBS) import qualified Data.ByteString.Lazy as LBS import qualified Network.SFTP.Client as SFTP -- 替换为你实际使用的SFTP客户端库 -- 从SFTP下载文件的核心逻辑 fetchSftpDocument :: Text -> Text -> IO LBS.ByteString fetchSftpDocument tenantId infoId = do -- 替换为你的SFTP连接、路径拼接和下载逻辑 conn <- SFTP.connect "sftp-host" 22 "username" "password" fileContent <- SFTP.getFile conn $ "/tenants/" <> unpack tenantId <> "/docs/" <> unpack infoId SFTP.disconnect conn pure fileContent handlerGetInformationDocuments :: Text -> Text -> Application handlerGetInformationDocuments tenantId infoId _req respond = do fileBytes <- fetchSftpDocument tenantId infoId respond $ responseLBS ok200 [ ("Content-Type", "application/octet-stream") -- 根据文件类型调整,比如"application/pdf" , ("Content-Disposition", "attachment; filename=\"document\"") -- 控制浏览器下载/预览行为 ] fileBytes
步骤4:简化启动逻辑
startApp函数无需再嵌套自定义中间件:
startApp :: IO () startApp = run 9080 app
方案优势
wai-cors直接在WAI层处理CORS请求,不需要解析Servant的API类型,因此不会受Raw端点的类型限制,同时能自动处理OPTIONS预检请求,正确添加所有所需的CORS响应头。
内容的提问来源于stack exchange,提问作者Nkalla
相关产品推荐
相关产品推荐

