You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 12:51:10