0

I have a form in a HTML page which does the following:

form method="POST" id="myForm" onsubmit="callSlates();">

Javascript function is as follows:

function callSlates(){
    var form=document.getElementById('myForm');

    form.action = "https://dev1-apiservicesweb.dev.jabs.com:8111/api/v1/systems/slates";

    // collect the form data while iterating over the inputs
    var data = {};
    for (var i = 0, ii = form.length; i < ii; ++i) {
        var input = form[i];
        if (input.name == "ID1") {
            data[input.name] = input.value;
        }
        if (input.name == "SDCode") {
            data[input.name] = input.value;
        }
    }
    var xhr = new XMLHttpRequest();
    xhr.open('POST', form.action);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) {
            alert(xhr.responseText);
        }
    }
    xhr.send(JSON.stringify(data));

}
//return false;
}

POST calls are happening but when I check the Request Header, it shows that the application/x-www-form-urlencoded and am ending with error 504-Gateway Timeout Error

The endpoint I am calling expects json header and JSON data. I believe I am doing that but when I used Chrome developer tools, I don't see that. Has it got something to do with the way am making the call?

Edit: When I tried hitting that URL with Postman, with header and body as JSON, am getting 200 response (as expected).

UPDATE: I understood that the form was getting submitted rather than the Ajax call and thus took Barmar advice and put return false; in form onsubmit. Now am not getting 504 anymore and getting 405 instead.

Following is the request header am seeing currently:

Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:dev1-apiservicesweb.dev.jabs.com:8111
Origin:http://localhost:3000

And in general information, it says:

Request Method:OPTIONS
Status Code:405

As per le_m, could this be a CORS issue?

Anuj Balan
  • 7,629
  • 23
  • 58
  • 92

2 Answers2

2

Since your request works from your local host via postman but not from within the browser, the culprit is probably the Same Origin Policy:

Your browser attempts to send a Cross Origin Request (CORS). There are two types of CORS requests:

  • Preflighted requests: The browser first asks the server about supported HTTP methods by sending an HTTP OPTIONS request followed by the actual HTTP request upon approval.

  • Simple requests: The browser directly sends the actual HTTP request.

Now, which of the above does your browser choose? MDN states that simple requests will be send if the Content-Type is one of the following:

 application/x-www-form-urlencoded
 multipart/form-data
 text/plain

However, Content-Type: application/json is not allowed for simple requests. Thus, you currently send preflighted CORS requests. You can verify that by opening the developer console e.g. in Firefox: You will notice that your code first sends an OPTIONS request.

Now, this OPTIONS request receives a 405 Method not allowed error. This indicates that the server doesn't support preflighted CORS requests. You either need to change the server configuration OR change the Content-Type to one of the compatible ones listed above. If your server can't accept one of those content types, then you are probably out of luck.

See also this answer given by @ArslanTariq in reply to a similar issue.

Community
  • 1
  • 1
le_m
  • 19,302
  • 9
  • 64
  • 74
  • I believe it could be le_m. Posted more information now. – Anuj Balan Apr 29 '17 at 02:59
  • That exactly was the issue. I turned off the web security in Chrome to confirm that and even with content-type: Json, I got 200 response. I believe I need not do anything in code specially than the one I posted here. Also, I'll be moving this code to a specific server/. Going forward I may not see this issue (As it won't be localhost anymore) ? – Anuj Balan Apr 29 '17 at 12:44
  • @AnujBalan If you run this code from the same domain as your server API endpoint is on, then you should see no issues at all. – le_m Apr 29 '17 at 13:57
0

You're not preventing the normal form submission. Change your form to:

<form method="POST" id="myForm" onsubmit="callSlates();return false;">

return false; prevents the default submit action.

There's also no need to set form.action in your function, since you don't want to submit the form normally.

Barmar
  • 741,623
  • 53
  • 500
  • 612