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

如何在Haskell Servant中解析无Content-Type头的API响应?

解决Servant解析无Content-Type的纯文本响应问题

当第三方API未指定Content-Type头仅返回纯文本时,Servant默认的解析逻辑会因为无法匹配对应MIME类型而报错,以下是两种常用的解决思路:

方法一:自定义通用MIME类型解析为Text

通过定义一个匹配任意Content-Type的类型,并实现对应的解析实例,让Servant直接将响应体转为Text:

  1. 定义通用Accept类型
data AnyContent

instance Accept AnyContent where
    contentType _ = "*/*"  -- 匹配所有Content-Type
  1. 实现Text的MimeUnrender实例
import Data.Text.Encoding (decodeUtf8)
import Servant.API (MimeUnrender(..))

instance MimeUnrender AnyContent Text where
    mimeUnrender _ body = Right $ decodeUtf8 body
  1. 在API类型中使用
type ThirdPartyAPI = "target-endpoint" :> Get '[AnyContent] Text

之后通过Servant客户端调用就能直接拿到Text类型的响应内容。

方法二:获取原始响应手动转换(更灵活)

如果需要额外处理响应头或做更复杂的错误处理,可以直接获取原始响应体再手动转换:

  1. 定义返回原始响应的API
import Network.HTTP.Client (Response)
import Data.ByteString (ByteString)

type ThirdPartyAPI = "target-endpoint" :> Get '[()] (Response ByteString)
  1. 手动转换为Text(含错误处理)
import Data.Text.Encoding (decodeUtf8')
import Servant.Client (ClientM, client, throwError, ServantError)
import Control.Monad.Except (ExceptT(..))

getRawResponse :: ClientM (Response ByteString)
getRawResponse = client ThirdPartyAPI

getResponseText :: ClientM Text
getResponseText = do
    resp <- getRawResponse
    case decodeUtf8' $ responseBody resp of
        Right txt -> return txt
        Left err -> throwError $ ServantError $ "Failed to decode text: " ++ show err

转换为自定义类型

如果需要将响应转为自定义类型,只需扩展MimeUnrender实例即可:

data MyCustomType = MyCustomType Text deriving (Show, Eq)

instance MimeUnrender AnyContent MyCustomType where
    mimeUnrender _ body = Right . MyCustomType $ decodeUtf8 body

之后API类型改为Get '[AnyContent] MyCustomType,客户端调用就能直接得到自定义类型的结果。

内容的提问来源于stack exchange,提问作者DarkHorse1997

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 10:03:27