1

I have a php file on server which have a function, and I have Node Js API also. I want to pass Node Js value to php script then get back the function output to node js.

I tried this using cookie-parser as sugggested by Christian in here. But it does not work

php script

<?php
$max = $_COOKIE["usrMob"];  // Taken from cookie
$min = 1111;

$number = mt_rand($min, $max);  // Find random number
echo $number;   // Send back to Node Js
?>

Node.Js

const express = require("express");
const cookieParser = require('cookie-parser'); 

const app = express();
app.use(cookieParser('Your Secret'));


router.get('/cookie', function (req,res)
{
    // Set cookie
    res.cookie('userMax', '46556') // options is optional
    res.end();
    console.log("Cookie is : " + res.cookie);
})
executable
  • 3,365
  • 6
  • 24
  • 52

1 Answers1

0

I have a php file on server which have a function, and I have Node Js API also. I want to pass Node Js value to php script then get back the function output to node js.

I tried this using cookie-parser as sugggested by Christian in here. But it does not work

Short answer

Sharing COOKIES won't work because of CORS, your nodejs server must be in the allow origin list of the PHP server.

Long answer

COOKIES are very used when storing user settings/tokens/password or some sensitive data on your browser that allows the user browsing experience behave different mostly the user decisions.

Therefore they cannot be sent in requests when different servers communicates between them unless they are allowed to leave to an 'authorized-origin' otherwise that would be a major leak of data through cookies, say hello to CORS (unless you don't own the target server).

Example:

You have a script on a TargetServer(TS), that sets a cookie there when user does some stuff. After the user finishes with your script you want to send data back to YourServer(YS), when the AJAX triggers, cookies won't be sent with the request as you normally see when you develop on localhost. Following your stack of tools, another problem issues, each request that you'll make to YS will generate a new id/session (i'm looking at you PHPSESSID), and that means, you won't know for example if the user is logged or not, and you know for sure that he already logged earlier (Yes - he is logged, but in another session file ... ).

HOW TO TACKLE THIS PROBLEM:

  1. Find an appropriate mechanism for encrypt/decrypt strings that your script and php will know.
  2. When you're sending a request from TS to YS add a custom header that YS will expect.eg. REQUEST-CUSTOM-HEADER: encodedVersionOf('hey-give-me-the-session-id') , PHP will see the incoming header, will decodeVersionOf('hey-give-me-the-session-id') and will trigger some special if and send you a response with a different header RESPONSE-CUSTOM-HEADER: encodedVersionOf('here-is-the-session-id'). Your script will now save it in COOKIES so you won't have to request it again. and just append it to your header on future requests.
  3. If PHP recognizes the incoming string as a valid session then php can load that session that you know you had data in it with session_id($incoming_id), make sure to set session_id before session_start
  4. I highly advise using JWT for this kind of things or some encrypted stringify json, so you can have an object like {session_id : 12idn3oind, userInfo: {name: 'test'}}.
  5. Exchanging data through headers is the next best thing when CORS is involved.

I tackled this example once, wasn't pretty to do, but worth it in the end.

You can send/receive data to/from php, only thing is that you should use headers so you won't affect php output. Since you own both servers you can do something like:

MOST IMPORTANT :

  1. npm install -S express
  2. Make sure you have enabled headers_module/mod_headers on your webserver.
  3. We will use custom headers so you should allow & expose them:

.htaccess

Header add Access-Control-Allow-Headers "node-request, node-response"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
Header add Access-Control-Expose-Headers "node-request, node-response"
Header add Access-Control-Allow-Origin "*"

PHP

<?php
    $max = @$_COOKIE["usrMob"];  // Taken from cookie
    $min = 1111;
    $number = rand($min, $max);  // Find random number
    echo $number;   // Send back to Node Js
    if( isset($_SERVER['HTTP_NODE_REQUEST'])){
       $req = json_decode($_SERVER['HTTP_NODE_REQUEST'], true);
       $data = array();
       // 'givemeanumber' is sent from Node.js server
       if( isset($req['givemeanumber']) ){
         $data = array(
             'number' => $number
         );

       }
       header('NODE-RESPONSE: '. json_encode(array("req" => $req, "res"=> $data)));
    }
?>

Node.JS

Don't forget to change these line to point to your php-server:

getFromPHP('localhost', '9999', '/path-to-php-script', {givemeanumber: 1})

index.js

const express = require("express");
const app = express();
const port = 9999;

const { getFromPHP } = require('./middleware.js');

const apachePHPconfig = {

    host: 'localhost',
    port: 80,
    urlpath: 'path-to-php-script'

}

app.get(
    '/',
    getFromPHP(apachePHPconfig.host, apachePHPconfig.port, apachePHPconfig.urlpath , {givemeanumber: 1}),
    function (req, res) {

        // here is your php object
        console.log('php', req.php);

        res.end();

    })

app.listen(port, () => {

    console.clear();
    console.log(`Example app listening on port ${port}!`)

})

middleware.js

/**
 *  Middleware to get data from PHP
 */
const getFromPHP = (phpHost, phpPort, phpPath, phpObject) => {

    if (typeof phpHost === 'undefined') {
        throw new Error('phpHost was not defined');
    }
    if (typeof phpPort === 'undefined') {
        throw new Error('phpPort was not defined');
    }
    if (typeof phpPath === 'undefined') {
        phpPath = '/';
    }
    if (typeof phpObject !== 'object' ) {
        phpObject = {};
    }

    return (req, res, next) => {

        if (typeof req.php === 'undefined') {
            req.php = {};
        }

        const options = {
            hostname: phpHost, // change this to your php server host
            port: phpPort, // change this with your php server port
            path: phpPath, // change this with your php server path to script
            method: 'POST',
            headers: {
                // here we send 'NODE-REQUEST', it will be available in php unde $_SERVER global prefixed with HTTP_ string because is a custom client request header.
                'NODE-REQUEST': JSON.stringify(phpObject)
            }
        };

        const isJSON = (str ) => {
            try {

                let j = JSON.parse(str);

                return typeof j === 'object' && j !== null;

            } catch (e) {
                return false;
            }

        };

        const httpModule = require('http');
        let reqHttp = httpModule.request(options, (response) => {

            if( typeof response.headers['node-response'] === 'undefined' || !isJSON(response.headers['node-response'])){

                req.php = {};

            }else{

                req.php =  JSON.parse(response.headers['node-response']);
            }

            // START - Remove this code when everything runs as expected
            let dataStack = []; 
            response.on('data', (data)=>{ 
               dataStack.push(data.toString());
            }) 
            response.on('end', ()=>{ 
               console.log("PHP HEADERS", response.headers) 
               console.log('PHP OUTPUT', dataStack.join('')); 
            })
            // END

            next();

        });

        reqHttp.on('error', (e) => {
            console.error(`problem with request to php server: ${e.message}`);
            next();
        });

        reqHttp.on('end', () => {
            next();
        });

        reqHttp.end();

    }

}

exports.getFromPHP = getFromPHP;
darklightcode
  • 2,738
  • 1
  • 14
  • 17
  • Can I send the number using params(req.params.number) or body (req.body.number) instead of {giveMeNumber:yourNum} ? –  Oct 09 '18 at 05:28
  • First, change `'NODE-REQUEST': JSON.stringify(phpObject)` to `'NODE-REQUEST': JSON.stringify(req.params.number)`, second, why did you removed my accepted answer ? – darklightcode Oct 09 '18 at 05:35
  • @SAKTHY let me put it this way, don't take it personally but you need to learn the basic of Javascript & PHP, object manipulation, arrays, for what i see during our more-than-enough conversation, you have a major lack on these fronts. Right now you're trying to swim with a curl in deep waters, how much would you remain afloat is the question, if i were you, i'd give it a thought. Good luck with your code mate. – darklightcode Oct 09 '18 at 05:43
  • Thank you so much, Now I did the tick. Any advises, to become like you? –  Oct 09 '18 at 05:59
  • Of course, for the start, do some basic javascript tutorials, the same goes for php, then start reading the docs on nodejs, express server and php, and use google alot if something is not clear – darklightcode Oct 09 '18 at 06:05
  • Thank you, Currently I use this, `var givNum = 1234; app.post('/sendMessage', getFromPHP(apachePHPconfig.host, apachePHPconfig.port, apachePHPconfig.urlpath, {giveMeNumber:givNum}), function (req, res) ...` How can I change above (`{giveMeNumber:givNum}`) to pass as parameter? I already changed in middleware as said before. –  Oct 09 '18 at 06:30
  • I tried this `app.post('/find/:number', getFromPHP(a.host, a.port, a.urlpath,{givemeanumber:req.params.number}), function (req, res)` but I got the error `ReferenceError: req is not defined` –  Oct 09 '18 at 07:06
  • Change `'NODE-REQUEST': JSON.stringify(phpObject)` to `'NODE-REQUEST': JSON.stringify({...phpObject, ...req.params})` and `{givemeanumber:req.params.number}` to `{givemeanumber: true}` – darklightcode Oct 09 '18 at 07:18
  • Nice, Working as expected. Thanks again –  Oct 09 '18 at 07:33
  • Shall I remove the `port` in the `const a = {host: 'http://sakthywebpage.com', port: null, urlpath:'/index.php'}` ? Because I think there is no port number. –  Oct 10 '18 at 07:16
  • 1. Your website is not accesible. 2. HTTP is always on port 80, so no, don't remove `port`, just set it to `80`, and HTTPS is on port 443. 3. Pay attention to the following protocols , `https://stackoverflow.com = https://stackoverflow.com:443` and `http://sakthywebpage.com = http://sakthywebpage.com:80` – darklightcode Oct 10 '18 at 07:21
  • I used `const a = {host: 'https://sakthywebpage.com', port: 443, urlpath:'/index.php'}` Then it echos the following `problem with request to php server: getaddrinfo ENOTFOUND https://sakthywebpage.com/index.php https://sakthywebpage.com/index.php:443` and the `req.php` is `{}` –  Oct 10 '18 at 07:33
  • I tried yuxhuang's [answer](https://stackoverflow.com/a/17691556/10248547) but no improvement –  Oct 10 '18 at 10:27
  • An why my website is not accessible? `req.php`returns for `localhost` but not for my webpage –  Oct 10 '18 at 15:25
  • Is there any way to use to access this @darklightcode ? –  Oct 11 '18 at 07:22