elm/http 1.0.0 defined Http.Error
as
type Error
= BadUrl String
| Timeout
| NetworkError
| BadStatus (Response String)
| BadPayload String (Response String)
but 2.0.0 changed it to
type Error
= BadUrl String
| Timeout
| NetworkError
| BadStatus Int
| BadBody String
When receiving BadStatus
I cannot obtain the body of the request, only the status code. In the docs Evan suggests a solution for this, but I don't understand how to make it work.
If we defined our own expectJson
similar to
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)
...
Then we have access to the metadata and body, but how do I use them? Should I define my own myBadStatus
and return that instead?
Http.BadStatus_ metadata body ->
Err (myBadStatus metadata.statusCode body)
Would this work?
What I need is to convert the following code:
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."
...
Thank you.
Edit 22/4/2019: I updated this answer for version 2.0+ of http-extras which has some API changes. Thanks to Berend de Boer for pointing this out!
The answer below gives a solution using a package I wrote (as per request), but you don't have to use the package! I wrote an entire article on how to extract detailed information from an HTTP response, it includes multiple Ellie examples that don't require the package, as well as an example that uses the package.
As Francesco mentioned, I created a package for exactly this purpose, using a similar approach described in the question: https://package.elm-lang.org/packages/jzxhuang/http-extras/latest/.
Specifically, the module to use Http.Detailed
. It defines an Error type that keeps the original body around on error:
type Error body
= BadUrl String
| Timeout
| NetworkError
| BadStatus Metadata body Int
| BadBody Metadata body String
Make a request like so:
type Msg
= MyAPIResponse (Result (Http.Detailed.Error String) ( Http.Metadata, String ))
sendRequest : Cmd Msg
sendRequest =
Http.get
{ url = "/myapi"
, expect = Http.Detailed.expectString MyAPIResponse
In your update, handle the result including decoding the body when it is 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...
...
...
Thanks the Francisco for reaching out to me about this, hopefully this answer helps anyone who faces the same problem as OP.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With