Návod k použití Node.js na FI
Běhové prostředí Node.js slouží k vytváření programů
v jazyce JavaScript. Tato platforma je primárně určena pro běh
samostatných serverů poslouchajících na dedikovaném TCP portu, což platí
i pro webové frameworky. Existují ale moduly, které umožňují běh pod
webovým serverem Apache a tedy i na Aise na adrese www.fi.muni.cz.
Po přečtení tohoto textu byste měli mít dost informací pro to,
abyste zvolili pro vás vhodné řešení.
Než budete pokračovat, doporučujeme vám prostudovat si návody
Uživatelské HTML stránky,
Vytváření CGI skriptů,
a Návod k použití PHP na FI.
Předpokládáme, že Apache má přístup do adresáře public_html.
CGI
CGI je jednoduché rozhraní, které lze využít v libovolném programovacím jazyce. V tomto návodu využijeme modul cgi-node, který poskytuje základní funkce pro jednodušší práci s HTTP požadavky a odpověďmi.
Nejprve vytvoříme adresáře pro naši novou aplikaci a podpůrné programy:
mkdir --parents ~/public_html/node-app/cgi-bin
Stáhneme knihovnu cgi-node a nastavíme jí právo na spuštění:
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
Pak v ní změníme cestu k Node.js binárce na prvním řádku na /usr/bin/node
a nastavíme cestu k adresáři se session soubory (proměnnou SessionPath)
na /tmp:
sed -i "1s|.*|#!/usr/bin/node|" cgi-node.cgi
sed -i "s|SessionPath:.*|SessionPath: '/tmp/'|" cgi-node.cgi
Samotnou aplikaci uložíme do souboru index.js. Zavoláme v ní jen
funkci CgiNodeInfo(), která se hodí pro testování a vypisuje
informace o prostředí, HTTP dotazu a session:
cd ~/public_html/node-app
echo "CgiNodeInfo();" > index.js
Jednoduchou "Hello world" aplikaci byste napsali takto:
response.headers['Content-Type'] = 'text/plain; charset=utf-8';
write("Hello world!\n");
Více podrobností o použití node-cgi zjistíte v dokumentaci
nebo ve zdrojovém kódu cgi-node.js.
Nakonec řekneme webovému serveru Apache, že má všechny soubory s příponou .js
spouštět pomocí cgi-node.cgi. Zde i v dalším textu nahraďte xlogin vlastním loginem.
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
Ověřte funkčnost aplikace navštívením https://www.fi.muni.cz/~xlogin/node-app/index.js.
V aplikaci můžete využít i další moduly. Buď zadejte plnou cestu k nim
(/home/xlogin/...) nebo je instalujte do adresáře ~/public_html/node-app/cgi-bin,
protože se hledají relativně k umístění cgi-node.cgi:
cd ~/public_html/node-app/cgi-bin
npm install wonderful-module
FastCGI
Při použití CGI brzy narazíte na limity této technologie. Každý HTTP požadavek je zpracován nově spuštěným procesem, což v případě Node.js znamená poměrně velkou latenci. Navíc nemůžete využít žádný z řady frameworků, které ke svému fungování potřebují modul http.
Naštěstí existuje modul node-fastcgi, který je postaven na specifikaci FastCGI. Tato umožňuje webovému serveru nechat dlouhodobě spuštěný proces obsluhovat více HTTP požadavků po sobě.
Nejprve si připravte adresář s aplikací, ve kterém nainstalujte modul node-fastcgi:
mkdir --parents ~/public_html/node-fastcgi-app
cd ~/public_html/node-fastcgi-app
npm install node-fastcgi
Samotná aplikace index.js může vypadat takto (převzato z dokumentace):
#!/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();
Skriptu je nutné dát práva pro vykonání (x) pro vlastníka:
chmod u+x index.js
Nakonec řekneme webovému serveru Apache, že má .js soubory spouštět
pomocí FastCGI:
cat > .htaccess <<'EOF'
AddHandler fastcgi-script .js
AddType application/x-httpd-javascript .js
DirectoryIndex index.js
EOF
Vyzkoušet její funkčnost můžete na adrese https://www.fi.muni.cz/~xlogin/node-fastcgi-app/.
Express
FastCGI server můžete použít jako náhradu za modul http.
Jako příklad uvedeme použití s frameworkem Express.
Tento framework nejdříve nainstalujeme (platí poznámky o umístění modulů
ze sekce CGI — hledají se relativně ke skriptu):
cd ~/public_html/node-fastcgi-app
npm install express
Aplikace pak může vypadat následovně:
#!/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();
a dostupná bude na https://www.fi.muni.cz/~xlogin/node-express-app/.
Pěkná URL
Aby se vám a uživatelům vaší aplikace dobře pracovalo s URL,
doporučujeme nastavit si v souboru .htaccess přepisování
URL pomocí 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
Zde řádek s RewriteRule zajišťuje, že URL tvaru
www.fi.muni.cz/~xlogin/node-express-app/LIBOVOLNY_SUFFIX
budou obsloužena aplikací uloženou v index.js.
Řádek s RewriteCond zabraňuje nekonečnému cyklu přepisování.
Vaši aplikaci můžete například napojit metodou use pod daný
prefix a používat tak cesty nezávislé na konkrétním umístění aplikace:
#!/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();
Vyzkoušet můžete adresy https://www.fi.muni.cz/~xlogin/node-fastcgi-app/hello
a https://www.fi.muni.cz/~xlogin/node-fastcgi-app/world.
© Text věnující se CGI vychází z návodu Patrika Vala.