Search code examples
javascriptjquerypostxmlhttprequest

POST works with JQuery but does not work with XMLHttpRequest


So I'm trying to POST to my server (php) from Javascript and am trying to not use JQuery.

This code works and posts the necessary data to the database

var msg = {};
msg['name'] = 'joe';
msg['message'] = 'why no work';

$.post(phpURL, msg, function(data) {});

but this one does not

var xhr = new XMLHttpRequest();
xhr.open("POST", phpURL, true);
xhr.send(msg);

I even looked at my php logs, looked at the headers and the only difference of the JQuery one from the XHR one I could see was the content-type header "application/x-www-form-urlencoded; charset=UTF-8" and this header "x-requested-with" "XMLHttpRequest".

So I tried all combinations of the following headers.

var xhr = new XMLHttpRequest();
xhr.open("POST", phpURL, true);
//xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
//xhr.setRequestHeader('x-requested-with', 'XMLHttpRequest');
xhr.send(msg);

to no effect.

It is worth mentioning if I try to add JSON.stringify(msg) anywhere, it does not work, neither in JQuery or XHR. But I would like to get this working first, and explain this bizarre difference.

I am inclined to believe this is a Javascript issue since the JQuery post works and in addition, a GET request of the server and the same table I'm trying to post to does work.


Solution

  • Do not confuse JavaScript objects with JSON.

    If you pass an object to jQuery's data parameter then it will encode it as application/x-www-form-urlencoded data (not JSON!).

    If you POST application/x-www-form-urlencoded data to PHP then it will parse it and populate the $_POST superglobal with it.

    If you pass an object to the send() method of an XMLHttpRequest object then it will not encode it for you. It will invoke .toString() on it implicit and send nothing very useful at all.

    To achieve the same effect as jQuery will do then you need to encode the data yourself. Don't forget to also set the Content-Type header!

    const encoded = new URLSearchParams(Object.entries(msg)).toString();
    const xhr = new XMLHttpRequest();
    xhr.open("POST", phpURL, true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.send(encoded);
    

    If you want to send JSON then you also have to encode it, but that is done simply with JSON.stringify() although you also need to set the Content-Type header (to application/json this time).

    const encoded = JSON.stringify(msg);
    const xhr = new XMLHttpRequest();
    xhr.open("POST", phpURL, true);
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.send(encoded);
    

    However, PHP will not parse JSON automatically so $_POST will remain empty, so you need to parse it manually.

    <?php 
        $json = file_get_contents('php://input');
        $msg = json_decode($json);