Translated using DeepL

Machine-translated page for increased accessibility for English questioners.

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/nodeand 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 .jsextension 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_SUFFIXwill 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/helloand https://www.fi.muni.cz/~xlogin/node-fastcgi-app/world.

© The text on CGI is based on Patrik Val's tutorial.