Click here to Skip to main content
15,887,135 members
Articles / Web Development / HTML

NodeJS WEB Server Running PHP

Rate me:
Please Sign up or sign in to vote.
3.00/5 (2 votes)
10 Jan 2019CPOL5 min read 19.1K   30   1   4
How to use PHP scripts on NodeJS

Image 1

Introduction

This article comes from an attempt to be acquainted on NodeJS[1] and how a server built with JavaScript and NodeJS can call PHP scripts.

I am aware that there are many frameworks to speed up the development of applications, such as, to name one, Express.js and also a NodeJS extension for managing PHP based site (like WordPress sites), but it is precisely this abundance of products that is an indication of the easiness with which we can develop a pure NodeJS HTTP server.

NodeJS

There are two main features of NodeJS: modularity and the non-blocking asynchronously programming[2]. Modularity is based on require(JavaScript_File) function that reads and executes the contents of JavaScript_File, returning an object; NodeJS has many native modules and, of course, one can add their own modules.

The non-blocking characteristic is based on that NodeJS objects have, normally, the method addListener (or his synonym on) to manage events; in the fragment below, the event data is fired when the request object (that is the request made to the web server) has data; the same object reacts at the event end of data:

JavaScript
var inData = '';	//	for POST data recovery (possibly)
request.on('data', function(chunk) {
	inData += chunk.toString();
});
request.on('end', function() {
...

Create and Start the WEB Server

We can create and start a web server with few instructions:

JavaScript
// server definition and activation
var port = 1337;
var server = require('http').createServer().listen(port);
console.log('Server running at 127.0.0.1:' + port);
// end server definition and activation
server.on('request', function(req, resp) {
...

In these lines of the above code, I highlight the two main features of NodeJS:

  • JavaScript
    var server = require('http').createServer().listen(port);

    This statement arose because the createServer method on module http returns a server whose method listen returns the object server itself, i.e., this is a compact writing of:

    JavaScript
    var server = require('http').createServer();
    server.listen(port);
  • JavaScript
    server.on('request', function(request, response) {...

    This is the function that activates when a request arrives from the browser.

The script containing the web server is executed in the window console:

set path=C:\Sviluppo\php7;\%path% C:\Users\User>node 
         C:\www\condorinformatique\Nodejs\tryNodeJS.js

(The first line simply makes the PHP interpreter accessible.).

Managing the Requests

As previously mentioned, the server instance of HTTP object has the on method that allows to intercept an event, in particular, the request event that indicates the reception of a request from the browser, request that is managed by a function with two objects: request and response.
When the event end of request object occurs, there are three steps to meet the request:

  • to discover the type of the requested resource (HTML file, image, JavaScript, style sheet, PHP script, etc.)
  • to recover the data arrived, if any
  • to send the answer

Which is the Resource?

The module url is used to obtain an object that contains the URI components as properties:

JavaScript
var Url = require('url').parse(request.url,true)

Those necessary for the demo in question are pathname and query, i.e., the file requested and the possible parameters (the path property contains both):

JavaScript
query: { Authors: '' },
pathname: '/getData.php',
path: '/getData.php?Authors',
...

Which are the Data?

The query property of Url object contains the possible parameters present in the URI, but if the request method is POST, as when submitting a form, the data are retrieved by the event data of the request object.

JavaScript
...
var Regexp = /name=\"(.+)\"\r\n\r\n(.*)\r\n/gm;		// for extract form data
...
	var inData = '';	                  // for POST data recovery (possibly)
	request.on('data', function(chunk) {
		inData += chunk.toString();
	});
 ...
	var parms = Url['query'];	          // data from GET or URI
	// extract fields
	match = Regexp.exec(inData);	      // data from form (POST method)
	while (match != null) {		          // matched text: match[0]; 
                                          // capturing group n: match[n]
		parms[match[1]] = match[2];
		match = Regexp.exec(inData);
	}
...
In the above fragment, after having acquired the possible POST data, an array of input data is created both from URI both from POSTed data (if any). The first ones are contained in the property query of the url object:
var parms = Url['query'];.
For the second ones, in case of submission of a form, the data have a structure similar to this on the right and these can be extracted using the regular expression[3]:
/name=\"(.+)\"\r\n\r\n(.*)\r\n/gm
where the bold parts identify the name and the value of the fields on form:
parms[match[1]] = match[2];.
-----------------------------7e217f121030a
Content-Disposition: form-data; name="fg_Store"

fg_frm
-----------------------------7e217f121030a
Content-Disposition: form-data; name="Author_Group"

Social Aphorisms
-----------------------------7e217f121030a
Content-Disposition: form-data; name="Author"

Claudie Baudry
-----------------------------7e217f121030a-- 

Sending the Answer

The answer is sent when the event end of the request object is fired:

JavaScript
request.on('end', function() {
	Url = require('url').parse(request.url,true)		
	if (pathName == "/") pathName = "\\index.html";	// first call
	fs.access(__basedir + pathName,(err) => {		// check if file exists)
		if (err == null) {
			var type = path.extname(pathName).substring(1).toLowerCase();
			var cType = "text/html; charset=utf-8"
			if (typeof types[type] != "undefined") cType = types[type];
			if (type == "php") {
...
			} else {
				fs.readFile(__basedir + pathName, (err,data) => {
					if (err) throw err;
					response.writeHead(200, {'Content-Type': cType});
					response.end(data,'binary');
				});
			}				
		} else {
			response.writeHead(404, {'Content-Type': 'text/html; charset=utf-8'});
			response.end("<img src='images/condor.gif'>" + err.message);
			console.log(err.message);
		}
	}
	);		
});
...

The above function deals on a default request, if the pathname is root, i.e., /; if the resource called is not present generates an error message.

For the resources found, it is necessary to determine its Content-type in order to send an appropriate header and finally send the resource itself (for PHP scripts, see the paragraph below).

Dealing with PHP Resources

If the resource requested is a PHP script, the program calls a PHP interpreter with switch -r followed by PHP instructions; this can be simply as follows:

JavaScript
var spawnPHP = spawn('php',["-r","include 'phpscript'"]);

if the script has no parameters.

In case of this demo, before the instruction that includes the PHP script, the form fields must be inserted in the PHP associative array $_REQUEST so after the -r switch, there is something similar to:

JavaScript
$_REQUEST['Author'] = 'Nicolas de Condorcet';
$_REQUEST['Author_Group'] = 'Social Aphorisms';
$_REQUEST['fg_Store'] = 'fg_frm';
$_REQUEST['fg_Button'] = 'Author';
$_REQUEST['R'] = '0.7828608712500384';
include 'C:\www\condorinformatique\nodejs/getData.php';

The script fragment below shows how to start the PHP interpreter and how to retrieve the answer on the stdout when the data event succeeded:

JavaScript
var requests = "include '" + __basedir + pathName + "';";
// prepare fields for PHP
for(q in parms) requests = "\$_REQUEST['" + q +"'] = '" +
                            parms[q] + "';" + requests;
var spawnPHP = spawn('php',["-r",requests]);
spawnPHP.stdout.on('data',function (data) {
    response.writeHead(200, {'Content-Type': cType});
    response.end(data);
    console.log(getTime() + " Sent resource: " + pathName)
});

Using the Demo

Decompress the demo file in a folder of your choice. You must change in the first line set path=C:\Sviluppo\php7;\%path% with the path to your PHP interpreter; at this point, you are ready to start typing in the browser http://127.0.0.1:1337/.

The demo uses some of my programs that you can download with the documentation from my site:

  • Crossing field in PDO table, there is also a CodeProject article
  • JavaScript Form Generator, there is also a CodeProject article

Conclusion

This article is a first approach for how to create a web server and it does not cover all the possibilities, in particular, how to manage the upload of files (which could be the topic of a next article).

Note

  1. ^ For an introduction on NodeJS, see the CodeProject article All About Core NodeJS — Part 1.
    How Node.Js Single Thread mechanism Work ? Understanding Event Loop in NodeJs
  2. ^ The effect of the non-blocking asynchronously is that the sequence of resources required by the browser may be different from those provided: as we can see from the console login, a JavaScript script formgen.js is requested before the CSS file styles.css bat it is served after because the size of the first is larger than the second.
    JavaScript
    C:\www\condorinformatique\nodejs>node tryNodeJS.js
    16:28:45 Server running at 127.0.0.1:1337
    16:29:07 Request resource: \index.html
    16:29:07 Sent resource: \index.html
    16:29:07 Request resource: /js/formgen.js
    16:29:07 Request resource: /styles.css
    16:29:07 Sent resource: /js/formgen.js
    16:29:07 Sent resource: /styles.css
    16:29:07 Request resource: /images/condor.gif
    16:29:07 Sent resource: /images/condor.gif
    16:29:07 Request resource: /getData.php
    16:29:07 Request resource: /CONDOR.WAV
    16:29:08 Sent resource: /CONDOR.WAV
    16:29:08 Request resource: /favicon.ico
    16:29:08 Sent resource: /favicon.ico
    16:29:08 Sent resource: /getData.php
  3. ^A great site to try and increase knowledge is: Online regex tester and debugger.

History

  • 8th January, 2019: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Condor Informatique
Italy Italy
Computer literacy (software) : Languages: PHP, Javascript, SQL Autoit,Basic4Android; Frameworks: JOOMLA!
Teaching/Training skills on Office, WEB site development and programming languages.
Others : WEB site development.
UNDP Missions
feb – may 2003 Congo DR Bukavu: ground IT computer course
nov 2003 Burundi Bujumbura: Oracle Data Base course
feb 2005 Burundi Bujumbura: JAVA course
mar 2005 Mali Kati: MS Office course
oct 2006 Mali Kati: MS Office course
jun 2006 Burkina Faso Bobo Dioulasso: MS Office course
jun 2007 Burkina Faso Bobo Dioulasso: MS Office course
may 2007 Argentina Olavarria hospital: Internet application for access to medical records
apr 2008 Burkina Faso Ouagadougou: MS ACCESS and dynamic Internet applications
jun 2008 Niger Niamey: analysis of the computing needs of the Niamey hospital
may 2009 Burkina Faso Ouagadougou: MS ACCESS and dynamic Internet applications
oct 2010 Niger Niamey: analysis of the computing needs of the Niamey hospital (following)
Region Piedmont project Evaluation
mar 2006 Burkina Faso, Niger
mar 2007 Benin, Burkina Faso, Niger
sep 2008 Benin, Burkina Faso, Niger
Others
feb 2010 Burundi Kiremba hospital: MS Office course
feb 2011 Congo DR Kampene hospital: MS Office course

Comments and Discussions

 
GeneralMy vote of 5 Pin
Member 1303796912-Mar-21 17:44
Member 1303796912-Mar-21 17:44 
GeneralMy vote of 1 Pin
User 28168229-Jan-19 8:32
User 28168229-Jan-19 8:32 
GeneralRe: My vote of 1 Pin
Member 140567973-Feb-19 21:29
Member 140567973-Feb-19 21:29 
GeneralMy vote of 5 Pin
User 28168229-Jan-19 8:31
User 28168229-Jan-19 8:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.