elm / http

Make HTTP requests in Elm
https://package.elm-lang.org/packages/elm/http/latest
BSD 3-Clause "New" or "Revised" License
154 stars 46 forks source link

`Http.post` can't handle responses with empty bodies #12

Closed dimbleby closed 5 years ago

dimbleby commented 7 years ago

... because it takes a Json.Decode.Decoder and - correctly - I can't write such a decoder that will succeed on an empty string.

One can use Http.request and eg expect = Http.expectStringResponse (\_ -> Ok ()).

However I'd suggest that it's not unusual for a POST to return an empty body, and so it would be a good thing if the convenience function could be made convenient for that case.

(Same would be true of the put and delete methods proposed in #9).

What do you think?

process-bot commented 7 years ago

Thanks for the issue! Make sure it satisfies this checklist. My human colleagues will appreciate it!

Here is what to expect next, and if anyone wants to comment, keep these things in mind.

marcosccm commented 7 years ago

You can also use a Decode.succeed to return a hardcoded value, but I agree that posts that return nothing are a very common case and it would be cool if we had another way of handling that

dimbleby commented 7 years ago

@marcosccm: Decode.succeed does not parse empty input. Try it!

jonnyarnold commented 7 years ago

@dimbleby Some parsing still takes place, even with Decode.succeed; here's a REPL session:

> import Json.Decode exposing (..)
> decodeString (succeed 42) ""
Err "Given an invalid JSON: Unexpected end of JSON input"
    : Result.Result String number

If the above returned 42 then empty bodies wouldn't be a problem. However, the error is valid: an empty string is not valid JSON.

I did some digging around the source for Html and built this module that ignores any body in the response:

module Http.IgnoreResponseBody exposing (..)

import Http exposing (..)

{-| Requests have "expectations" attached to them; these are essentially
functions that run against the response. The Http module provides
`expectString`; we could simply ignore the string it returns.
`ignoreResponseBody` tells the type system explicitly that we don't care about
the response body.
-}
ignoreResponseBody : Expect ()
ignoreResponseBody =
    expectStringResponse (\response -> Ok ())

{-| A version of `post` with the `ignoreResponseBody` expectation.
-}
postAndIgnoreResponseBody : String -> Body -> Request ()
postAndIgnoreResponseBody url body =
    request
        { method = "POST"
        , headers = []
        , url = url
        , body = body
        , expect = ignoreResponseBody
        , timeout = Nothing
        , withCredentials = False
        }
dimbleby commented 7 years ago

@jonnyarnold it sounds as though you think you're disagreeing with me; but I think you are agreeing!

MrMatten commented 6 years ago

Has there come a solution to this? Currently in a similar situation and would like to be able to handle it in an idiomatic way

evancz commented 5 years ago

This should be possible with version 2.0.0 of this package.