Last Updated on July 25, 2021 by Amarjit Singh
Sometimes there comes a situation where you want to run a PHP Web App along with an Express Web App. For Example, you might want to:
1. Run a WordPress blog along with an ExpressJS App.
2. Run PHPMyAdmin along with an ExpressJS App.
3. Run a PHP Web App along with an ExpressJS App.
4. Run Angular Universal along with a PHP Web App.
The easiest and common way of doing this is to run the Expressjs on a different PORT as that of the PHP server (apache) or vice-versa.
But you won’t like your clients to put a port number after the domain name to access PHP or ExpressJS server.
Or you might think to run nodejs app on the apache server. But there is no official module for apache to run nodejs.
So to serve PHP and ExpressJS App on the same port we will be running ExpressJS on default port 80/443 as a reverse proxy server for the PHP Web App requests. A reverse proxy server is a server that handles the requests on behalf of the other server. So in our case, NodeJS will handle requests for the PHP server and forward them to the Apache server.
Let’s get started: we will be using http-proxy Nodejs package to transfer requests for PHP Web App to apache.
Part 1: Setting up the Nodejs server as a reverse proxy server.
1. Create a project folder: First, create a folder and open a terminal window in that folder. Then Initialize the directory as a NodeJS project and install the required npm packages using the following commands.
npm init
npm install --save cors express http-proxy
2. Import the dependencies: Now create a file with the name index.js and open it in your favorite text editor. At the start of this file put the following statements to import all the required packages.
var express = require('express');
var httpProxy = require('http-proxy');
var apiProxy = httpProxy.createProxyServer();
var app = express();
var cors = require('cors');
var http = require('http');
var https = require('https');
var fs = require('fs');
3. Create the Nodejs server instance: Now in the following code the sslCreds variable is initialized to null and after that, there are few commented lines if you have SSL certificates then uncomment these lines and replace paths for SSL certificates with your SSL certificates paths.
var sslCreds = null;
// sslCreds = {
// // uncomment the following code and replace the following paths if you have SSL certificates.
// key: fs.readFileSync('/root/key.pem'),
// cert: fs.readFileSync('/root/certificate.pem')
// };
if (sslCreds) {
var server = https.createServer(sslCreds, app);
port = 443;
http.createServer(function (req, res) {
res.writeHead(301, { "Location": "https://" + req.headers['host'].replace('80', '443') + req.url });
console.log("http request, will go to >> ");
console.log("https://" + req.headers['host'].replace('80', '443') + req.url );
res.end();
}).listen(80);
} else {
var server = http.createServer(app);
port = 80;
}
server.listen(port, '0.0.0.0',function(){
console.log(`Server listening on port `+port);
});
4. Routing web requests: Now below is the code where the real magic happens. We have a middleware that will check if the request path starts with “/blog/” or it is equals to /blog. So when the request path is equal to “/blog” or the path starts with “/blog/” we will simply forward this request to the Apache server. Otherwise, we will let the request pass through the middleware by calling next()
function.
app.use(function (req, res, next) {
if (req.path.startsWith('/blog/') || req.path == '/blog') {
console.log(`forwarding to http://localhost:8888`);
apiProxy.web(req, res, {
target: `http://localhost:8888`,
xfwd: true
});
} else {
next();
}
});
5. Define routes for nodejs: Now after the above middleware we can define our nodejs routes. In the code below we are defining one express route to handle all the get requests.
app.get('*', function(req, res) {
res.send('<h1> NodeJS</h1><p> You are accessing a nodejs route.</p>');
});
So with the above 5 steps, we have a Nodejs server that will forward all the requests to the Apache server when the request path starts with “/blog/” or the request path is equal to “/blog”.
Part 2: Setting up the Apache server to listing for the request coming on port 8888.
1. Change Apache Port: In case you are using Ubuntu. Open the file `/etc/apache2/ports.conf` using your favorite text editor. I prefer nano so I did it like below.
nano /etc/apache2/ports.conf
In Case of CentOS you need to open file `/etc/httpd/conf/httpd.conf`.
After opening the file Check for line starting with ‘Listen” and change this line to look like “Listen 8888” and if you are using CentOS then change it to look like “Listen *:8888”
2. Set SSL env variable (Optional): If you have enabled SSL in the above Nodejs script then you will need to put an env variable for PHP. As we are forwarding requests to http://localhost:8888. So PHP will not know about that the site has SSL enabled so it might malfunction. Therefore we need to tell apache to put the SSL variable. For this we need to edit vhosts file.
By default, Vhosts files for Ubuntu are located at /etc/apache2/sites-available/
and for CentOS the vhosts files are at /etc/httpd/conf.d
Edit the vhosts file with below command:
For Ubuntu
`nano /etc/apache2/sites-available/000-default.conf`
For CentOS
`nano /etc/httpd/conf.d/000-default.conf`
First of all, you need to change the following line
`<VirtualHost *:80>`
Make this line to look like `<VirtualHost *:8888>`
Now create a new line after the above line and put the following line
SetEnv HTTPS "on"
3. Restart the Apache server: Now we have done all the changes required to run Apache on port 8888. Now we just need to restart the Apache server using the following command.
For Ubuntu:
`service apache2 restart`
For CentOS:
`service httpd restart`
That’s it, now you can handle request for apache and NodeJS server on same port.
Important Note! you will have to create a folder with name “blog” inside your Apache’s Document root directory.