Přejít k navigační liště

Zdroják » JavaScript » v8cgi: JavaScript na serveru

v8cgi: JavaScript na serveru

Články JavaScript, Různé

JavaScript je dnes prakticky hlavním jazykem, který je používán při psaní skriptů pro klientskou část webových aplikací. Je pochopitelné, že existují snahy použít stejný jazyk i pro serverové skripty. Dostupnost otevřeného JS engine V8 jim dodala nový impuls – podívejme se na jednu z možných implementací.

Koncem roku 2008 spatřil světlo světa nový webový browser, Google Chrome. Zatímco jeho renderovací jádro bylo prostě převzato z projektu WebKit, ostatní části prohlížeče byly napsány od základů. Mimo jiné i interpret JavaScriptu, známý jako V8. Jeho vysoký výkon je jednou z hlavních deviz Chrome; není proto s podivem, že se autoři V8 rozhodli pro svůj počin vytvořit komplexní veřejné API, pomocí kterého je možno interpret vložit do libovolné C++ aplikace. Podívejme se, jak výsledek takového propojení může vypadat.

Varování 1: v tomto článku je zhusta používán termín JavaScript, přestože V8 striktně vzato podporuje kompletně jen ECMAScript, 3. vydání. Řadovému kolemjdoucímu však tyto pojmy (docela pochopitelně) splývají, zůstaneme proto u známějšího náz­vu.

Varování 2: tento článek ukazuje neotřelé a nezvyklé postupy. Čtěte jej jen, pokud můžete kladně odpovědět alespoň na jeden z těchto bodů:

  • nebojíte se technologií pocházejících od Google
  • přijde vám jako dobrý nápad používat stejný jazyk na klientu i serveru
  • je vám sympatická syntaxe a expresivita JavaScriptu
  • nevěříte, že vše dobré již bylo vynalezeno a staré postupy se nesmí měnit

Stahujeme, kompilujeme, nastavujeme

Projekt v8cgi si klade za cíl vytvořit jednoduchý obal okolo interpretu V8 a poskytnout vazby na volání systémových funkcí, spolupráci většího množství kódu a používání standardních i doplňkových knihoven. Jistý důraz je také kladen na zpracovávání HTTP požadavků, ať již formou CGI, FastCGI nebo modulu do webserveru Apache. Kód v8cgi zdaleka nedosahuje produkční kvality, ale je v současné době stabilní a nabízí použivatelné množství funkcí a knihoven.

Pokud si chcete v8cgi vyzkoušet, musíte učinit tyto kroky:

  1. Zprovoznit konstrukční systém SCons
  2. Stáhnout a zkompilovat V8
  3. Stáhnout a zkompilovat v8cgi
  4. Upravit konfiguraci v8cgi

Pro uživatele Windows je k dispozici binární distribuce v8cgi, díky které je možno přeskočit první tři kroky. Protože cílem tohoto článku není kompletní návod k instalaci, ukažme jednotlivé body jen ve zkratce. Pro zkušené linuxové uživatele by neměly představovat zásadní problém.

SCons

SCons je poměrně jednoduchý nástroj, vytvořený jako alternativa ke známému kombu make + autoconf. Je napsaný v Pythonu a každá rozumná distribuce nabízí jeho balík ( apt-get
install scons
). SCons řídí proces kompilace zdrojových kódů, stará se o multiplatformní předávání parametrů překladači a linkeru, nabízí ovlivňování překladu pomocí parametrů.

V8

Samotný interpret V8 je představován jedinou knihovnou. Zdrojový kód buďto získáme pomocí Subversion ( svn checkout http://v8.googlecode.com/svn/trunk/ v8), nebo použijeme distribuci V8, která je součástí oficiálního balíku v8cgi. Po rozbalení v adresáři s V8 stačí spustit scons library=shared (bez parametru by byla zkompilována statická knihovna). Po chvíli překládání vznikne libv8.so – kýžený interpret V8.

v8cgi

K dispozici je opět buď checkout ( http://v8cgi.googlecode.com/svn/trunk/), nebo některý ze zdrojových balíků. O překlad se zase stará SCons; ukažme příklad použití:

scons module=0 gd=0 mysql=0 config_file=/tmp/v8cgi.conf

Jednotlivé parametry říkají, že nebudeme chtít překládat modul do Apache, že nechceme podporu pro knihovny GD či MySQL a že náš konfigurační soubor bude umístěn na zadané cestě. Pro výpis a vysvětlení všech takových parametrů lze napsat scons -h; všechny parametry jsou volitelné a mají výchozí hodnotu.
Cesta ke konfiguračnímu souboru je sice specifikována během překladu, při volání v8cgi lze ale tuto hodnotu přebít jinou.

Konfigurace

Zbývá poslední a nejjednodušší bod: zkopírujeme distribuční konfigurační soubor ( v8cgi.conf.posix) na místo, kde ho bude aplikace očekávat (hodnota parametru config_file) a trochu ho poupravíme. Jediná nutná změna je řádek obsahující require.paths.push  – parametrem je cesta do adresáře s jednotlivými knihovnami/moduly v8cgi. Pokud tedy experimentujeme třeba v ~/v8cgi, je chtěná cesta  /home/username/v8cgi/lib.

A jdeme na to

V nejjednodušším případě se v8cgi používá jako běžná aplikace na příkazové řádce:

./v8cgi examples/shell.js

Parametr -c určuje vlastní cestu ke konfiguračnímu souboru:

./v8cgi -c /tmp/v8cgi.conf examples/shell.js

Obě tyto ukázky pustí jednoduchý JavaScriptový shell. S ním bychom se ale moc daleko nedostali, pojďme se proto podívat, jak psát zdrojové kódy pro v8cgi.

Skripty na straně serveru

Zatímco v prostředí webového prohlížeče je k dispozici globální objekt window, proměnná document a řada funkcí a objektů od DOMu, na serveru nic takového nenajdeme. v8cgi poskytuje samo o sobě jen velmi málo globálních prvků (jsou to zejména funkce require a include a dále objekty system a v8cgi), takže bez využití dalších knihoven naše skripty nebudou nijak přepychové. Mohou vypadat třeba takto:

#!v8cgi
var inn = system.args[1];
var out = 1;
while (inn) { out *= inn--; }
system.stdout("Faktorial cisla "+system.args[1]+" je "+out+"n");

Skript lze nyní pouštět buď jako parametr v8cgi, nebo jako samostatně vykonatelný soubor (pokud mu dáme chmod +x).

require – do hry vstupuje CommonJS

Vývoj a psaní JavaScriptu na klientu nejsou nijak organizovány, a situace je proto dle očekávání chaotická. Poměrně mladá organizace OpenAjax Alliance se snaží tendence na tomto poli standardizovat, směrovat a kontrolovat; úspěchy těchto snah jsou ale diskutabilní a ne příliš viditelné. Aby se předešlo podobné situaci u JavaScriptu na serveru, vznikla neformální skupina CommonJS. Jejím cílem je poskytnout nutné standardy dříve, než dojde k roztříštění a implementaci mnoha různých nekompatibilních řešení. CommonJS je tvořena mimo jiné autory necelé desítky projektů podobných v8cgi, jejich uživateli a několika členy TC39.

Během své existence (která netrvá déle než rok a půl) vyprodukovalo CommonJS několik standardů a velké množství návrhů. V současné době probíhá finalizace binárního datového typu – něco, co JavaScriptu na serveru chybí jako sůl. My se zde ale zaměříme na jiný CommonJS standard – na funkci require() a filozofii psaní modulů. Jedna ukázka zdrojového kódu řekne víc než tisíc slov:

/* modul.js */
var nejakaKonstanta = 123456;
var Trida = function() {};
Trida.prototype.metoda = function(a) { system.stdout(a); };
exports.nejakaKonstanta = nejakaKonstanta;
exports.Trida = Trida;
/* main.js */
var modul = require("modul");
var inst = new modul.Trida();
inst.metoda(module.nejakaKonstanta);

Soubor main.js je zde ten, který vykonáváme pomocí v8cgi. Je vidět použití funkce require, která načte cílový modul a vykoná jej. Vrátí objekt zvaný exports, do které modul nadefinoval funkcionalitu, jež chce poskytovat. Přihodím ještě několik informací o  require:

  • V každém modulu je k dispozici objekt exports pro definování výstupu modulu a funkce require pro přístup k dalším modulům
  • Modul je vyhodnocen ve vlastním scope, takže jeho proměnné nejsou odnikud vidět
  • Názvy modulů se zadávají bez přípony (je tak možno používat i binární moduly – takové, které bychom vyrobili třeba pomocí  scons
    mysql=1 gd=1
    )
  • Názvy modulů začínají buďto tečkou (pak jsou relativní vůči právě zpracovávanému modulu), lomítkem (pak jsou absolutní), nebo čímkoliv jiným (pak jsou relativní vůči adresáři s moduly, viz konfigurace)
  • Moduly, resp. jejich objekty exports, se cachují; opakované použití modulu jej nevykoná znovu

v8cgi nabízí jisté množství modulů, některé jsou JavaScriptové a jiné binární. Binární moduly se musí kompilovat, děje se tak opět pomocí SCons. Jejich kompletní výčet i dokumentace jsou k dispozici na stránkách projektu.

Další ukázky

#!v8cgi
/* rozrezani velkeho obrazku na male ctverecky */
var GD = require("gd");
var tilex = 32;
var tiley = 32;
var img = new GD.Image(Image.PNG, "obrazek.png");
var w = img.sx();
var h = img.sy();
var x = Math.floor(w / tilex);
var y = Math.floor(h / tiley);
for (var i=0;i<x;i++) {
    for (var j=0;j<y;j++) {
        var small = new GD.Image(GD.Image.TRUECOLOR, tilex, tiley);
        small.copy(img, 0, 0, i*tilex, j*tiley, tilex, tiley);
        var parts = name.split(".");
        parts[0] += "_"+j+"_"+i;
        small.save(GD.Image.PNG, "small_"+j+"_"+i+".png");
    }
}
#!v8cgi
/* trivialni HTTP klient + zapis do souboru */
var Socket = require("socket").Socket;
var ip = Socket.getAddrInfo("www.seznam.cz");
var s = new Socket(Socket.PF_INET, Socket.SOCK_STREAM, Socket.IPPROTO_TCP);
s.connect(ip, 80);
s.send("GET / HTTP/1.0rnrn");
var received = "";
do {
    var part = s.receive(1024);
    received += part;
} while (part.length > 0);
s.close();
var out = new File("/tmp/data").open("w");
out.write(received);
out.close();
system.stdout(received);

HTTP: CGI a Apache

Webový server Apache lze nakonfigurovat tak, aby požadavky nechával zpracovat právě pomocí v8cgi. Komunikace může být realizována buď pomocí CGI, nebo jako modul do webserveru.

CGI

Našim skriptům dáme nějakou specifickou příponu a uděláme z nich spustitelné soubory. Pak stačí do konfigurace Apache přidat:

# konfigurace Apache pro CGI: predpokladame, ze soubor .ssjs bude spustitelny
AddHandler cgi-script .ssjs

Modul do Apache

Toto řešení je výkonnější, ale také o něco složitější. Nejprve je nutné zkompilovat v8cgi modul:

scons module=1

A dále upravit konfiguraci webového serveru:

LoadModule v8cgi_module /home/uzivatel/v8cgi/v8cgi_module.so
AddHandler v8cgi-script .ssjs

Všechny požadavky na soubory s příponou .ssjs bude nyní obhospodařovat v8cgi.

Modul http.js

Na konec článku se ještě seznámíme s modulem http.js. Ten předpokládá, že v8cgi používáme pro zpracování HTTP požadavků, třeba tak, jako PHP. Má tedy smysl ho používat jen v kombinaci s webovým serverem, jak bylo naznačeno v předchozích odstavcích.

Při použití modulu http.js vzniknou dvě globální proměnné, request a response. Ta první slouží pro získávání dat z požadavku; druhá poskytuje metody pro tvorbu odpovědi. Kompletní dokumentace je opět k dispozici na webu v8cgi, takže přejdeme rovnou k ukázkám.

#!v8cgi
/* nejjednodussi ukazka HTTP odpovedi */
response.write("<strong>funguje to!</strong>");
#!v8cgi
/* nazvy a hodnoty vstupnich POST parametru */
for (var p in request.post) {
    response.write(p + ": " + request.post[p] + "<br/>");
}
#!v8cgi
/* vypis zaznamu z databaze */
var MySQL = require("mysql").MySQL;
var db = new MySQL().connect("host", "user", "pass", "db");
var id = parseInt(request.get["id"]) || 0;
var result = db.query("SELECT * FROM tabulka WHERE id=" + id);
var row = result.fetchObjects()[0];
var str = JSON.stringify(row);
response.write(str);

A dál

Směr dalšího vývoje v8cgi je jasný. Jakmile dojde k finální standardizaci binárního datového typu, otevírají se dveře knihovnám pro komplexnější přístup k souborovému systému, práci s knihovnou zlib a také tvorbu nějakého webového frameworku. Co bude potom už záleží jen na uživatelích, jejich přáních, feature requestech a bugreportech…

Komentáře

Subscribe
Upozornit na
guest
18 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Jan Grmela

Před rokem a půl se všichni Palmu divili, že se odvažuje napsat celý operační systém v Javascriptu. A teď se mrkněte okolo, jakým směrem vývoj směřuje! No a tuším, že není daleko doba kdy si budeme do počítače stahovat javascriptové stolní aplikace.

blizzboz

pochybujem…

Murdej

Proč né, části aplikace náročné na výkon budou zatím furt psané nějakém nižším jazyce (DB, IO, …) nebo je dělá HW (dekomprimace mpeg, 3D akcelerace, …). Už teď se dost často používají aplikace psané se skriptovacích jazycích, nebo spouštěné virtuálními stroji (java, mono, .net). A při použití jit se rychlost už dost blíží i k aplikacím v C/C++.

pas

Myslím, že Chrome OS na to dá jasnou odpověď. Drtivá většina aplikací běžné denní potřeby bude v JS, specializované záležitosti ve Flashi, Silverlightu a jen těch pár nejnáročnějších aplikací v „native client“.

rooobertek

asi som čistá lama, ale skončil som pri kompilácii V8…

myd

Pokud mas Arch linux tak muzes pouzit
http://aur.archlinux.org/packages/v8-svn/v8-svn/PKGBUILD, pokud ne tak tam aspon najdes postup jak v8 spravne zkompilovat.

Jiří Kosek

naopak to byl jeden z prvních jazyků používaný pro serverové skriptování (pomineme-li volání čehokoliv přes CGI) – akorát se to jmenovalo LiveWire a přišel s tím tehdy Netscape.
http://en.wikipedia.org/wiki/Server-side_JavaScript

mol

Přesně tak. A už v roce 1997 existovalo i komfortní IDE (Borland Intrabuilder). Kromě toho klasická ASPčka se dala psát v JScriptu snad od začátku.

HUgo

Osobně mám s Javascriptem na serveru jen ty nejhorší zkušenosti aneb memory leak snadno a rychle.

Aichi

Fajn info, tak se rozepiš o konfiguraci, jakou JS knihovnu používáš (v8cgi, node.js, …..), atd. Nebo jen plácáš prázdnou slámu?

Glin

Spis by to chtelo clanek jak dostat python do prohlizece misto javascriptu, aby se clovek javascriptu zbavil :).

...

Tak tak, javascript je taky novy visual basic :-).

lopata

Jak se už zmínil Aichi, chtělo by to i nějaký článek o node.js. Podle mě node.js eliminuje cgi/apache a můžeme psát rovnou celé aplikace jako servery a to velmi efektivně, dost dobře by se dal dělat i debugger. To mi tedy přijde jako dost pecka a kdyby se v budoucnu tak nějak dělali web aplikace kompletně v js v třeba rovnou s podporou server side debuggeru v browseru, tak by mě to tedy vůbec nevadilo. MS se o tu jazykovou integraci pokouší se silverlightem (C# (VB?) na serveru i klientovi) a řekl bych že jim to zatím vychází. Jediné, kdo by jim asi do toho mohl promluvit by bylo serverové a klientské JS + Html5.

x

Cus, souhlasim s nazorem vyse-jak dostat Python do prohlizece namisto JS na server. JS je oproti Pythonu mrzak! Reknete, jak byste udelali nasledujici konstrukce v JS?

class Aaa(object):
  __metaclass__ = something
  desc = Descriptor(**{'toto': 'je', 'slovni%s' % 'k': 2})
  l = lambda self: reduce(lambda a, b: a+b, range(10))
  def __getattribute__(self, name):
     return 'Python je doprdele super!'
pimpo

Chod do prcic aj s lambda calculusom, a pythonich abominacii ako je trac, denyhosts a podobne som si uzil uz dost. Ked v pythone uvidim software a nije nejaky zmrd, potom sa nan pozriem.

Martin Malý

Prosím zúčastněné, aby podobné debaty vedli buď ve fóru, nebo nikde – dohady o tom, který jazyk je „lepší“, jsou sice vděčné, ale nikam nikdy nevedly, dokonce ani když účastníci používali vulgarity. Pro takovou diskusi tu není míto. Děkuji za pochopení.

valafan

Jazyk Vala má taky budoucnost…

_

v tomto článku je zhusta používán termín JavaScript, přestože V8 striktně vzato podporuje kompletně jen ECMAScript, 3. vydání.

Odkaz smeruje na 5. vydanie.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.