How to use Node.js on FI
The
Node.js runtime is used to create programs in JavaScript. This platform is primarily designed for running standalone servers listening on a dedicated TCP port, which is also true for web frameworks. However, there are modules that allow you to run under the Apache web server and therefore on Aise at
www.fi.muni.cz
. After reading this, you should have enough information to choose a solution that works for you.
Before proceeding, we recommend that you review the tutorials
User HTML Pages,
Creating CGI Scripts, and
How to Use PHP on FI. We assume that Apache has access to the
public_html
directory.
CGI
CGI is a simple interface that can be used in any programming language. In this tutorial, we will use the cgi-node module, which provides basic functionality to make working with HTTP requests and responses easier.
First, we will create directories for our new application and supporting programs:
mkdir --parents ~/public_html/node-app/cgi-bin
We will download the
cgi-node
library and set the right to run it:
cd ~/public_html/node-app/cgi-bin
wget -O cgi-node.cgi https://github.com/DEDAjs/cgi-node/releases/download/v0.2/cgi-node.js
chmod u+x cgi-node.cgi
Then we change the path to the Node.js binary on the first line to
/usr/bin/node
and set the path to the session files directory (variable
SessionPath
) to
/tmp
:
sed -i "1s|.*|#!/usr/bin/node|" cgi-node.cgi
sed -i "s|SessionPath:.*|SessionPath: '/tmp/'|" cgi-node.cgi
We'll save the application itself to
index.js
. We'll just call the
CgiNodeInfo()
function in it, which is useful for testing and prints out information about the environment, HTTP request and session:
cd ~/public_html/node-app
echo "CgiNodeInfo();" > index.js
You would write a simple "Hello world" application like this:
response.headers['Content-Type'] = 'text/plain; charset=utf-8';
write("Hello world!\n");
See the
documentation or the source code of
cgi-node.js
for more details on using
node-cgi
.
Finally, we tell the Apache web server to run all files with the
.js
extension using
cgi-node.cgi
. Here and in the following text, replace
xlogin
with your own login.
cd ~/public_html/node-app
cat > .htaccess <<'EOF'
AddHandler cgi-node .js
Action cgi-node /~xlogin/node-app/cgi-bin/cgi-node.cgi
DirectoryIndex index.js
EOF
Verify the functionality of the application by visiting
https://www.fi.muni.cz/~xlogin/node-app/index.js
.
You can also use other modules in the application. Either enter the full path to them (
/home/xlogin/...
) or install them in the
~/public_html/node-app/cgi-bin
directory , as they are looking relative to the
cgi-node.cgi
location:
cd ~/public_html/node-app/cgi-bin
npm install wonderful-module
FastCGI
When using CGI, you will soon run into the limitations of this technology. Each HTTP request is handled by a newly started process, which in the case of Node.js means quite high latency. In addition, you cannot use any of the many frameworks that need the http module to function.
Fortunately, there is a node-fastcgi module that is built on top of the FastCGI specification. This allows a web server to let a long running process handle multiple HTTP requests in sequence.
First, prepare an application directory in which to install the
node-fastcgi
module:
mkdir --parents ~/public_html/node-fastcgi-app
cd ~/public_html/node-fastcgi-app
npm install node-fastcgi
The
index.js
application itself might look like this (taken from the
documentation):
#!/usr/bin/node
var fcgi = require('node-fastcgi');
var server = fcgi.createServer(function(req, res) {
if (req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end("Hello, world!\n");
} else if (req.method === 'POST') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
var body = "";
req.on('data', function(data) { body += data.toString(); });
req.on('end', function() {
res.end("Received data:\n" + body);
});
} else {
res.writeHead(501);
res.end();
}
});
server.listen();
The script must be given execute rights (
x
) for the owner:
chmod u+x index.js
Finally, we tell the Apache web server to run the
.js
files using FastCGI:
cat > .htaccess <<'EOF'
AddHandler fastcgi-script .js
AddType application/x-httpd-javascript .js
DirectoryIndex index.js
EOF
You can test its functionality at
https://www.fi.muni.cz/~xlogin/node-fastcgi-app/
.
Express
You can use the FastCGI server as a replacement for the
http
module. As an example, let's use it with the
Express framework. We will install this framework first (notes about the location of modules from the CGI section apply - they are looked for relative to the script):
cd ~/public_html/node-fastcgi-app
npm install express
The application can then look like this:
#!/usr/bin/node
var fcgi = require('node-fastcgi');
var express = require('express');
var app = express();
app.get('/~xlogin/node-express-app/', function (req, res) {
res.set('Content-Type', 'text/plain');
res.send("Hello World!\n");
});
fcgi.createServer(app).listen();
and will be available at
https://www.fi.muni.cz/~xlogin/node-express-app/
.
A nice URL
To make the URLs easy to work with for you and your application's users, we recommend setting up URL rewriting in the
.htaccess
file using
mod_rewrite:
cat >> .htaccess <<'EOF'
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/~xlogin/node-express-app/index.js
RewriteRule (.*) /~xlogin/node-express-app/index.js/$1 [L,PT]
EOF
Here, a line with
RewriteRule
ensures that URLs of the form
www.fi.muni.cz/~xlogin/node-express-app/LIBOVOLNY_SUFFIX
will be served by the application stored in
index.js
. A line with
RewriteCond
prevents an endless cycle of rewriting.
For example, you can link your application using the
use
method under a given prefix and use paths independent of the specific application location:
#!/usr/bin/node
var prefix = '/~xlogin/node-express-app';
var fcgi = require('node-fastcgi');
var express = require('express');
var base_app = express();
var app = express();
app.get('/hello', function (req, res) {
res.set('Content-Type', 'text/plain');
res.send("Hello\n");
});
app.get('/world', function (req, res) {
res.set('Content-Type', 'text/plain');
res.send("World!\n");
});
base_app.use(prefix, app);
fcgi.createServer(base_app).listen();
You can try
https://www.fi.muni.cz/~xlogin/node-fastcgi-app/hello
and
https://www.fi.muni.cz/~xlogin/node-fastcgi-app/world
.
© The text on CGI is based on Patrik Val's tutorial.