15

I am trying to POST some data from a Node.js application to a PHP script. For the time being I am just building a proof of concept but I am unable to get the actual data over to the PHP side. The request goes through and I get 200 back but PHP thinks the $_POST array is empty.

Here is my node code:

// simple end point just for testing

exports.testPost = function(request, response) {
    data = request.body.data;

    postToPHP(data);

    response.end(data);
}

function postToPHP (data) {
    var http = require('http');

    var options = {
        host : 'localhost',
        port : 8050,
        path : '/machines/test/index.php',
        method : 'POST',
        headers : {
            'Content-Type' : 'application/json',
            'Content-Length' : Buffer.byteLength(data)
        }
    };

    var buffer = "";

    var reqPost = http.request(options, function(res) {
        console.log("statusCode: ", res.statusCode);

        res.on('data', function(d) {
            console.info('POST Result:\n');
            //process.stdout.write(d);
            buffer = buffer+data;
            console.info('\n\nPOST completed');

        });

        res.on('end', function() {
            console.log(buffer);
        });
    });

    console.log("before write: "+data);

    reqPost.write(data);
    reqPost.end();

}

Again, the request makes it to localhost:8050/machines/test/index.php but when I do a var_dump of $_POST it is an empty array.

[29-Jan-2014 21:12:44] array(0) {

}

I suspect I am doing something wrong with the .write() method but I can't quite figure out what. Any input on what I am missing or doing incorrectly would be greatly appreciated.

* Update:

As some of the comments indicate using file_get_contents('php://input'); does work to get the data on the PHP side but I would still prefer to be able to access the $_POST array directly.

niczak
  • 3,897
  • 11
  • 45
  • 65
  • 1
    possible duplicate of [Issue reading HTTP request body from a JSON POST in PHP](http://stackoverflow.com/questions/7047870/issue-reading-http-request-body-from-a-json-post-in-php) – Quentin Jan 29 '14 at 20:22
  • @Quentin Nope, definitely not. I have tried passing other than JSON to PHP and it is still an empty $_POST array. – niczak Jan 29 '14 at 20:23
  • 1
    Is the "other than JSON" properly encoded application/x-www-form-urlencoded data? You've only shown us code which *shouldn't* populate `$_POST`. – Quentin Jan 29 '14 at 20:25
  • @Quentin Why wouldn't it populate $_POST? I believe the answer to that is the answer I am looking for. I did also try the built-in query string module to create a properly encoded string but $_POST was still empty. What am I missing? (thank you for the prompt replies too, btw!) – niczak Jan 29 '14 at 20:28
  • 1
    the way you have it you would need to read the raw input from php: `file_get_contents("php://input");` – Patrick Evans Jan 29 '14 at 20:29
  • @PatrickEvans I will have to adapt it as such that I can look at the $_POST[] array, what needs to change on the node side to enable that functionality? – niczak Jan 29 '14 at 20:31
  • @NicholasKreidberg, see my answer about making it so you can post data correctly. – Patrick Evans Jan 29 '14 at 20:42
  • @NicholasKreidberg — You have to send the data in a format that PHP knows how to decode, such as application/x-www-form-urlencoded – Quentin Jan 29 '14 at 20:54
  • using php://input seems a small price to pay considering you can avoid extra nodej modules and use built-in https easily – Randhir Rawatlal Sep 02 '20 at 06:21

1 Answers1

29

Since you are sending the data with Content-Type: application/json you would need to read the raw input as php does not know how to read json into their globals like _GET and _POST unless you have some php extension that does it.

You can use the querystring library to parse a object into a name-value pair query string that you could than transmit with Content-Type:application/x-www-form-urlencoded so that the data will be parsed into the globals

var data = {
   var1:"something",
   var2:"something else"
};
var querystring = require("querystring");
var qs = querystring.stringify(data);
var qslength = qs.length;
var options = {
    hostname: "example.com",
    port: 80,
    path: "some.php",
    method: 'POST',
    headers:{
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': qslength
    }
};

var buffer = "";
var req = http.request(options, function(res) {
    res.on('data', function (chunk) {
       buffer+=chunk;
    });
    res.on('end', function() {
        console.log(buffer);
    });
});

req.write(qs);
req.end();
Patrick Evans
  • 41,991
  • 6
  • 74
  • 87
  • How would I adapt this solution to work with incoming data such as: "[{"name":"test1", "value":"10"},{"name":"test2","value":"20"}]" ? I can't get the qs helper to stringify that for obvious reasons. – niczak Jan 29 '14 at 21:01
  • 1
    @NicholasKreidberg, if you mean data from php `JSON.parse(buffer)`, otherwise if you mean if the variable data contained that string, then just parse it to an object first `data = {myArray:JSON.parse(data)};` before passing it to stringify and then capture `$_POST['myArray']` in php. – Patrick Evans Jan 29 '14 at 21:09
  • That was most helpful! What would be required to get that same example working over HTTPS? – niczak Jan 29 '14 at 22:10
  • 1
    I ended up using the 'request' module and things are working great over HTTPS. I would still be curious as to how I would do it w/ the native module but for the time being the functionality is where I need it to be. Thanks again! – niczak Jan 30 '14 at 19:54
  • Works well although in a compromised way! – Subrata Sarkar May 30 '19 at 12:40