首页 > 解决方案 > Elm 0.19:使用 elm/http 2.0.0 接收 BadStatus 时如何获取请求正文

问题描述

elm/http 1.0.0 定义Http.Error

type Error
    = BadUrl String
    | Timeout
    | NetworkError
    | BadStatus (Response String)
    | BadPayload String (Response String)

但 2.0.0 将其更改为

type Error
    = BadUrl String
    | Timeout
    | NetworkError
    | BadStatus Int
    | BadBody String

收到时BadStatus我无法获取请求的正文,只能获取状态码。在文档中,埃文为此提出了一个解决方案,但我不明白如何使它工作。

如果我们定义自己的expectJson类似

expectJson : (Result Http.Error a -> msg) -> D.Decoder a -> Expect msg
expectJson toMsg decoder =
  expectStringResponse toMsg <|
    \response ->
      case response of
        Http.BadStatus_ metadata body ->
          Err (Http.BadStatus metadata.statusCode)
        ...

然后我们可以访问元数据和正文,但是我该如何使用它们呢?我应该定义自己的myBadStatus并返回它吗?

Http.BadStatus_ metadata body ->
  Err (myBadStatus metadata.statusCode body)

这行得通吗?

我需要的是转换以下代码:

myErrorMessage : Http.Error -> String
myErrorMessage error =
    case error of
        Http.BadStatus response ->
            case Decode.decodeString myErrorDecoder response.body of
                Ok err ->
                    err.message
                Err e ->
                    "Failed to parse JSON response."
        ...

谢谢你。

标签: httpelm

解决方案


编辑 22/4/2019:我为 http-extras 的 2.0+ 版本更新了这个答案,其中有一些 API 更改。感谢 Berend de Boer 指出这一点!

下面的答案使用我编写的包(根据请求)给出了解决方案,但您不必使用包!我写了一篇关于如何从 HTTP 响应中提取详细信息的文章,其中包括多个不需要包的 Ellie 示例,以及使用包的示例。


正如弗朗西斯科所提到的,我正是为此目的创建了一个包,使用问题中描述的类似方法:https ://package.elm-lang.org/packages/jzxhuang/http-extras/latest/ 。

具体来说,要使用的模块Http.Detailed。它定义了一个错误类型,使原始正文保持错误:

type Error body
    = BadUrl String
    | Timeout
    | NetworkError
    | BadStatus Metadata body Int
    | BadBody Metadata body String

提出这样的请求:

type Msg
    = MyAPIResponse (Result (Http.Detailed.Error String) ( Http.Metadata, String ))

sendRequest : Cmd Msg
sendRequest =
    Http.get
        { url = "/myapi"
        , expect = Http.Detailed.expectString MyAPIResponse

在您的更新中,处理结果,包括在为 BadStatus 时对正文进行解码:

update msg model =
    case msg of
        MyAPIResponse httpResponse ->
            case httpResponse of
                Ok ( metadata, respBody ) ->
                    -- Do something with the metadata if you need! i.e. access a header

                Err error ->
                    case error of
                        Http.Detailed.BadStatus metadata body statusCode ->
                            -- Try to decode the body the body here...

                        ...

        ...

感谢弗朗西斯科就此事与我联系,希望这个答案可以帮助任何面临与 OP 相同问题的人。


推荐阅读