I am attempting to send a JSON response body when my API serves up a 4xx http response code. Everything works fine when the code is 200, but changed to 4xx, no body is received. Postman for Chrome shows the body response, but XHR (Chrome, FF) does not.
Is it even possible to get the response body inside an XHR with nginx CORS properly set up (I set it to simply echo ...Allow-Origin: $http_origin)? I have nginx as a proxy_pass to the actual API server on 127.0.0.1:9001. When I send in known credentials, CORS and Allow-Origin are all working fine with 200 OK. If I simply use a bad password, I see the error status code in Firebug, but the XHR object (also jQuery's $.ajax) has Status = 0, even though a request hits the API server.
At a very minimum I would like to be able to grab the 4xx status code in the XHR object so I can at least show general info on certain 4xx codes instead of a generic "it didn't work." This is also not available and I always get status=0, even though the API is hit and the proper response code is logged in nginx.
Update 3/23 Javascript XHR code:
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://arinna-api/v1/401', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onload = function () {
// do something to response
console.log(this);
};
Play framework code to return status 200 OK JSON content type response body:
SimpleResult(
header = ResponseHeader(200, Map(CONTENT_TYPE -> "application/json")),
body = Enumerator("{\"error\":\"invalid grant\"}".getBytes())
)
200 OK works as expected:
Changing the HTTP Code to 401 causes the response body to not be received by the XMLHttpRequest (xhr.status is also 0 instead of 401):
SimpleResult(
header = ResponseHeader(401, Map(CONTENT_TYPE -> "application/json")),
body = Enumerator("{\"error\":\"invalid grant\"}".getBytes())
)
xhr.send('username=username&password=badpassword&grant_type=password&client_id=mobile_platform');
Postman works as expected:
Is it possible to get a 4xx response body and status code via XHR? According to the W3C Status Code Definitions on HTTP 4xx:
Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method. User agents SHOULD display any included entity to the user.
However, according to this discussion:
2) Browsers do not display the text/html response body of a HTTP 401 response, instead, they just pop up a modal authentication dialog (until "cancel" is pressed).
3) Servers do not send a meaningful response body with the 401 status as browsers do not display it anyway.
The code below functions as expected:
Application.scala
routes
index.html.scala
The text
"test"
is shown in the response (Opera, Chrome and Firefox). Note that I run Play twice, at port9000
and9001
and use Play2.2.1
. Then from Play at9001
I make a request to9000
.