HTML 5 as interface to a local script, with Node.js

Node.js can receive form data and send them as parameters to a PHP script on the local desktop.

This opens the way for the use of HTML 5 as an interface to local applications as well. Note that form data are not passed to a PHP script in the variable $_POST (or $ _GET) but as command line parameters, which has the same effect.

In fact they are transmitted as such to a JavaScript server script. But this demonstration is made to add GUIs to PHP scripts, you normally use at command line (there are many on this site) without changing the script code.

Here is the code of a generic PHP script (phpback.php) receiving parameters from the command line:

<?php
echo "phpback.php here...\n";
echo $argc-1, " infos received from HTML interface:\n\n";
for($i = 1; $i < $argc; $i++)
{
  $p = $argv[$i];
  list($k, $v) = explode('=', $p);
  echo $k, "=", $v, "\n";
}

echo "\nReady to use them, add your code to the source...";
?>

Apart from the display of the infos received, by echo statements, which are just for demonstration, this code is generic to process any PHP script parameters.

To this script we want to give a graphical interface. It looks like this:

Node.js interface graphique

The data entered by the user, ie a login and password (this is just an example, all other data are possible), will be passed as parameters to the command line PHP program, thanks to Node.js .

To display the interface, you must start the server with this command:

node htmlinterface.js

This can be put into a batch file and associated with an icon on the desktop.

And to run the PHP script, you type in the URL bar of a browser the name of the interface:

http://127.0.0.1:1000/phpfront.php

This too can be automated by placing it in bookmark.

When you click the "Run script" button, you should see in the browser displayed the results of the PHP script:

Obviously the display could be more sophisticated using HTML tags, but in this tutorial, we want to keep it simple.

How it works?

If you have already read the two previous tutorial, How to build a page and application server script and Running locally a PHP program from the browser, which is recommended, you already have an idea of the code, in fact it is the synthesis of these two previous articles.

  1. When the JavaScript server receives the URL of the interface, it displays the corresponding page, for this purpose it uses the principle stated in the first article.
  2. The user enters data and clicks the "Run Script" button. The form data are sent and received by the JavaScript server.
  3. This then is converted to a command line by transforming the data as parameters, and the PHP script is executed, as explained in the second article.
  4. The results of the PHP script are displayed instead of the interface. Integrating them into the interface would be better, but it will be the subject of a future article.

When the user requests the interface in the browser, the server receives a GET command. He assigns the code variable with value 0, so that the runphp function calls the fs.readFile method that displays the HTML page.

Then when the user sends the form data, the server receives a POST method, it assigns the code variable with 1, and the runphp function calls the exec method to run the PHP script in backend. The results are sent to the browser by the sendData function.

But in the meantime we must interpret the form data. This is accomplished by the following code:

if(request.method == 'POST')
{
  var data;
  var formData;
  var phpvar="";
  request.on('data', function(chunk) { data = chunk.toString(); });
  request.on('end', function()
  {
    formData = qs.parse(data);
    code = 1;
    for(var key in formData)
    {
      phpvar =  phpvar + key + "=" + '"' + formData[key] + '" ';
    }
    });
}      

We need the querystring module whose parse method converts the form data in associative array with for keys the names of variables and their values ​​assigned to the keys.
It remains to transform this array to command line parameters. This is accomplished through the loop that turns formData into phpvar.

The full source code

http = require("http"),
path = require("path"),
url = require("url"),
qs = require('querystring'),
runner = require("child_process");
fs = require("fs");

function sendError(errCode, errString, response)
{
  response.writeHead(errCode, {"Content-Type": "text/plain;charset=utf-8"});
  response.write("Error: " + errString + "\n");
  response.end();
  return false;
}

function sendData(err, stdout, stderr, response)
{
  if (err) return sendError(500, stderr, response);
  response.writeHead(200,{"Content-Type": "text/plain;charset=utf-8"});
  response.write(stdout);
  response.end();
}

function sendFile(err, file, response)
{
  if(err) return sendError(500, err, response);
  response.writeHead(200);
  response.write(file, "binary");
  response.end();
}

function runPHP(exists, code, localpath, param, response)
{
  if(!exists) return sendError(404, 'File not found', response);
  console.log("php " + localpath + " " + param);
  if(code==1)
  {
    runner.exec("php " + localpath + " " + param,
      function(err, stdout, stderr) { sendData(err, stdout, stderr, response); });
    return;
  }
  fs.readFile(localpath, "binary",
    function(err, localpath){ sendFile(err, localpath, response);});
}

function php(request, response)
{
  var urlpath = url.parse(request.url).pathname;
  code = 0;
  if(request.method == 'POST')
  {
    var data;
    var formData;
    var phpvar="";
    request.on('data', function(chunk) { data = chunk.toString(); });
    request.on('end', function()
    {
      formData = qs.parse(data);
      code = 1;
      for(var key in formData)
      {
        phpvar =  phpvar + key + "=" + '"' + formData[key] + '" ';
      }
     });
    }
    var param = url.parse(request.url).query;
    var localpath = path.join(process.cwd(), urlpath);
    fs.exists(localpath, function(result) { runPHP(result, code, localpath, phpvar, response)});
}

var server = http.createServer(php);
server.listen(1000);
console.log("Server ready to get the HTML interface on port 1000.");  

Files corresponding to this tutorial are:

And there is much, much more to do with Node.js on the local machine.  In the next article we will show how to create interaction between the HTML interface and a PHP script.