Elm http request returns NetworkError for successf

2019-06-18 00:49发布

I have a fair amount of experience building web apps with React but want to learn Elm. I've been banging my head against an HTTP request issue for a couple days now.

I'm running an Elm app at localhost:8080 and my supporting API at localhost:8081. Whenever I make an HTTP request (I've tried both GET and POST requests) I get a NetworkError. I've been looking into Elm JSON decoders and think it's possible that this is where my problem exists but I've tried sending simple strings from my server and using the Decode.string decoder in my Elm app and I still get the NetworkError.

Here's what my code looks like currently:

Commands.elm

module Commands exposing (..)

import Models exposing (..)
import Msg exposing (..)
import Http
import Json.Decode as Decode
import Json.Encode as Encode


createTempUser : Model -> Cmd Msg
createTempUser model =
  let
    tempUserBody =
      [ ( "firstname", Encode.string model.firstname )
      , ( "lastname", Encode.string model.lastname )
      , ( "phone", Encode.string model.phone )
      ]
        |> Encode.object
        |> Http.jsonBody

    url =
      myAPIUrl ++ "/endpoint"

    contentType = Http.header "Content-type" "text/plain"

    post =
      Http.request
        { method = "POST"
        , headers =  [contentType]
        , url = url
        , body = tempUserBody
        , expect = Http.expectJson decodeApiResponse
        , timeout = Nothing
        , withCredentials = False
        }

  in
    Http.send Msg.TempUserCreated post


decodeApiResponse : Decode.Decoder ApiResponse
decodeApiResponse =
  Decode.map4 ApiResponse
    (Decode.at ["status"] Decode.int)
    (Decode.at ["message"] Decode.string)
    (Decode.at ["created"] Decode.int)
    (Decode.at ["error"] Decode.string)


myAPIUrl : String
myAPIUrl = "http://localhost:8081"

Models.elm

module Models exposing (..)


type alias ApiResponse =
  { status: Int
  , message: String
  , created: Int
  , error: String
  }

Msg.elm

module Msg exposing (..)

import Navigation exposing (Location)
import Models exposing (..)
import Http


type Msg
  = ChangeLocation String
  | OnLocationChange Location
  | CreateTemporaryUser
  | TempUserCreated ( Result Http.Error ApiResponse )

Update.elm

module Update exposing (..)

import Msg exposing (Msg)
import Models exposing (..)
import Routing exposing (..)
import Commands exposing (..)
import Navigation

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    Msg.ChangeLocation path ->
      ( { model | changes = model.changes + 1 }, Navigation.newUrl path )

    Msg.OnLocationChange location ->
      ( { model | error = "", route = parseLocation(location) }, Cmd.none )

    Msg.CreateTemporaryUser ->
      ( model, createTempUser model )

    Msg.TempUserCreated (Ok res) ->
       update (Msg.ChangeLocation signupCodePath) { model | httpResponse = toString(res) }

    Msg.TempUserCreated (Err err) ->
      ( { model | error = toString(err) }, Cmd.none )

Chrome's Network devtools show the response as this

{"status":200,"message":"Successfully inserted temporary 
user","created":1518739596447,"error":""}

I think this may be all the relevant code but if there's more you need to see I'll make an update including the requested code. I'll admit that I don't have a full understanding of the Elm Json.Decode library but I was under the impression that if this was where the issue was I would get an UnexpectedPayload Error that included additional context.

标签: http elm
1条回答
干净又极端
2楼-- · 2019-06-18 01:36

@Sidney and @SimonH,

Thank you for looking into this for me, I feel bad because this wasn't an Elm issue after all.

The solution ended up using a CORS middleware on the server to add the 'Access-Control-Allow-Origin' header. The server was still responding with a 200 status and even included the entire successful response body but this resulted in a failure in Elm's Http Result.

Thank you again for your time and thought!

查看更多
登录 后发表回答