0

I'm sending a JSON request (an applicative login but the kind of request doesn't matter) to a server with the following function:

function login() {
    var payload = {
    "api_key" : "", "cmd" : "login",
    "params" : {}
    }
    payload["params"]["username"] = document.getElementById("uname").value
    payload["params"]["password"] = document.getElementById("passwd").value

    var xhr = new XMLHttpRequest();
    xhr.open("POST", "http://localhost:4000/api", true);
    xhr.setRequestHeader("Content-type", "application/json");
    xhr.setRequestHeader("Accept", "application/json");

    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
            resp = JSON.parse(xhr.responseText);
            console.log("resp.status=" + resp.status);
            console.log("resp.[\"status\"]=" + resp["status"]);
        }
    }
    xhr.send(JSON.stringify(payload));
}

I'm actually getting the correct reply in the responseText field. For example, if the credentials are wrong, I get

{
  "status": "ko", 
  "errors": [
    {
      "cmd": "login",
      "long": "Login error : 'user-20' has no access to the system",
      "short": "login_error"
    }
  ]
}

If the credentials are OK I get

{
  "status": "ok",
  ... some additional data
}   

Yet, I can't manage to get the status field : resp.status or resp["status"] are always undefined. Same if the call is done in asynchroneous mode (xhr.open("POST", "http://localhost:4000/api", false);) or if I don't JSON.parse() the reply, ie: resp = xhr.responseText;.

Update - 2017.09.06

I finally found a way to get it working, but I don't quite understand why it is so. I actually changed

resp = JSON.parse(xhr.responseText);

into

resp = JSON.parse(JSON.parse(xhr.responseText));

To figure this out, I printed typeof(xhr.responseText) which is a sting. Actually typeof(JSON.parse(xhr.responseText)) is also a string and this is why it has no fields like status. Eventually, parsing xhr.responseText twice gives an object from which I actually can retrieve my data.

If somebody has a clue about what is happening, I would be interested... I don't know if this is related, but the app server that is sending the JSON is the latest version of Elixir/Phoenix, ie, 1.5/1.3 and JSON encoding/decoding is done with poison.

mszmurlo
  • 1,250
  • 1
  • 13
  • 28
  • Can you add JSON.stringify(xhr.responseText) output ?? – MyTwoCents Sep 03 '17 at 14:46
  • @mszmurlo - Can you paste the output of - console.log(xhr.responseText); ? – Johnbabu Koppolu Sep 03 '17 at 15:02
  • @Johnbabu: For a failed login `xhr.responseText="{ \"status\" : \"ko\", \"errors\" : [{\"short\":\"login_error\",\"long\":\"Login error : user 'user-20' has no access to the system\",\"cmd\":\"login\"}] }\n"`. And for a successful login : `xhr.responseText="{ \"status\" : \"ok\", \"data\" : {\"user\":{\"username\":\"user-20\",\"user_type\":\"customer\",\"user_status\":\"registered\",\"sex\":null,\"prefered_language\":null,\"msisdn\":\"XXXXXXXXX\",\"last_name\":null,\"first_name\":null,\"email\":\"user-20@toto.com\"},\"api_key\":\"84afcfb033034a8898d590135d1b7174\"} }\n"` – mszmurlo Sep 03 '17 at 18:24
  • @mszmurlo - this looks ok to me. just a wild guess - I see 'resp' is a not a local variable - is something else going on in the code - that changes 'resp'? can you put a 'var' before resp and define it locally and check? – Johnbabu Koppolu Sep 03 '17 at 19:05

1 Answers1

1

This is because you have assigned the resp variable to responseText

resp = JSON.parse(xhr.responseText);

To get the response code

respCode = xhr.status

Or if you want both in the same resp variable you could do

resp = {
    responseText: xhr.responseText,
    status: xhr.status
}

Then you can access them as resp.responseText and resp.status

  • My question wasn't clear enough : I'm non interested in the HTTP respose code (returned by `xhr.status`), but by the **applicative** status returned in the payload of the reply. I should get "ok" upon successful login and "ko" otherwise (for the `login` example). – mszmurlo Sep 03 '17 at 14:56