HTML 5 comme interface d'un script local, avec Node.js

Node.js peut recevoir les données d'un formulaire et les transmettre comme paramètres à un script PHP, sur le poste local.

Cela ouvre donc la voie à l'utilisation de HTML 5 comme interface d'applications locales aussi. Noter que les données de formulaires ne sont pas transmises à un script PHP dans la variable $_POST (ou $_GET) mais comme paramètres de ligne de commande, ce qui a le même effet.

En fait elles sont transmises comme telles à un script serveur JavaScript. Mais la présente démonstration est faite pour ajouter des interfaces graphiques à vos scripts PHP, que vous utilisez habituellement en ligne de commande (il y en a de nombreux sur ce site) sans avoir à changer le code du script.

Voici le code générique d'un script PHP (phpback.php) recevant des paramètres en ligne de commande:

<?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...";
?>

Mis à part l'affichage par echo des données reçues, qui ne sont là que pour la démonstration, ce code est général à tout script PHP recevant des paramètres.

A ce script nous voulons donner une interface graphique. Elle ressemble à ceci:

Node.js interface graphique

Les données entrées par l'utilisateur, à savoir un login et un mot de passe (c'est juste un exemple, toutes autres données sont possibles), seront transmises comme paramètres en ligne de commande au programme PHP, cela grâce à Node.js.

Pour lancer l'interface, on démarre le serveur par la commande:

node htmlinterface.js

Cela peut être mis dans un fichier batch et associé à une icône sur le bureau.

Et pour lancer le script PHP, on tape dans la barre d'URL d'un navigateur le nom de l'interface:

http://127.0.0.1:1000/phpfront.php

Cela aussi peut être automatisé en le plaçant en bookmark.

Quand vous cliquer sur le bouton "Run script", Vous devez voir afficher dans le navigateur le résultat du script PHP:

Evidemment l'affichage pourrait être plus élaboré en utilisant des balises HTML, mais pour ce tutoriel, on veut rester simple.

Comment cela fonctionne?

Si vous avez déjà lu nos deux précédents tutoriel, Comment réaliser un serveur de pages ou d'applications avec Node.js et Exécuter localement un programme PHP à partir du navigateur, ce qui est recommandé, vous avez déjà une idée du code, en fait il est la synthèse de ces deux précédents articles.

  1. Quand le serveur JavaScript reçoit l'URL de l'interface, il affiche la page correspondante, pour cela il utilise le principe exposé dans le premier article.
  2. L'utilisateur entre des données et clique sur la bouton "Run script". Les données de formulaires sont envoyées et reçues par le serveur JavaScript.
  3. Celui-ci forme alors une ligne de commande en transformant ces données en paramètres, et lance le script PHP, comme exposé dans le second article.
  4. Les résultats du script PHP sont affichés à la place de l'interface. Les intégrer dans l'interface serait mieux, mais ce sera l'objet d'un prochain article.

Quand l'utilisateur demande l'interface dans le navigateur, le serveur reçoit une commande GET. Il assigne la variable code avec la valeur 0, ce qui fait que la fonction runphp appelle la méthode fs.readFile qui affiche la page HTML.

Puis quand l'utilisateur envoie les données de formulaire, le serveur reçoit une méthode POST, il assigne code avec la variable 1, et la fonction runphp appelle la méthode exec pour exécuter le script PHP en backend. Les résultats sont envoyés au navigateur par la fonction sendData.

Mais il faut entretemps que les données de formulaire soient interprétés. C'est accompli avec le code suivant:

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] + '" ';
    }
    });
} 
On a besoin du module querystring dont la méthode parse transforme les données de formulaire en tableau associatif avec les noms de variables en clés, et leurs valeurs assignées aux clés.
Il reste alors à transformer ce tableau en paramètres de lignes de commandes. Cela est réalisé par la boucle qui transforme formData en phpvar.

Le code source complet

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."); 

Les fichiers correspondant à ce tutoriel sont:

Et il y a beaucoup, beaucoup plus à faire avec Node.js sur le poste local. Dans le prochain article nous verrons comment créer une interaction entre l'interface HTML et un script PHP.