Psaní CGI nebo FastCGI aplikací není s využitím knihovny libfcgi a jejich bindingů do Haskellu FastCGI žádný problém. V tomto článku si ukážeme jednoduchý příklad fastcgi aplikace, která reaguje na Ajaxové requesty.
Následující příklad vznikl na základě článku, který jsem na toto téma našel.
Pro jednoduchost pracuji pouze s obyčejnými řetězci, ale existují i knihovny pro JSON.
module Main where -- bindingy na libfcgi -- http://hackage.haskell.org/cgi-bin/hackage-scripts/package/fastcgi-3001.0.2 import Network.FastCGI import Data.Maybe (fromMaybe) -- prace s casem import System.Time import System.Locale (defaultTimeLocale) -- spusti smycky obsluhujici fastcgi dotazy main = runFastCGI echo echo :: CGI CGIResult echo = do cmd <- getInput "command" outStr <- case cmd of -- obsluha prikazu 'echo' Just "echo" -> do str <- getInput "text" return $ fromMaybe "N/A" str -- obsluha prikazu 'time' Just "time" -> liftIO $ formatTime =<< getClockTime -- promenna 'command' je nastavena na neznamy prikaz Just c -> return $ "Neznamy prikaz '" ++ c ++ "'" -- v postBody nebyla nalezena promenna 'command' _ -> return "Zadej prikaz, hulvate!" -- vratime klientovi vysledek setHeader "Content-type" "application/x-javascript" output outStr formatTime ctime = return . formatCalendarTime defaultTimeLocale "%H:%M:%S" =<< toCalendarTime ctime
Máme-li nainstalované ghc a FasCGI, pak můžeme příklad zkompilovat příkazem
ghc --make Main.hs -o main.fcgi
Příklad volání z html vidíme na následujícím příkladu. Pro ajaxové volání jsem zde použil javascriptový framework Prototype.
<html> <head> <script type="text/javascript" src="prototype.js"/></script> <script type="text/javascript"> function echo(text) { new Ajax.Request("main.fcgi", { asynchronous: true, method: 'post', postBody: 'command=echo&text=' + text, onComplete: function(response) { alert(response.responseText); }, evalScripts: false}); } function cas() { new Ajax.Updater('cas', "main.fcgi", { asynchronous: true, method: 'post', postBody: 'command=time', evalScripts: false}); } </script> </head> <body> <br/> <span style="padding: 10px; border: 1px solid" onclick="echo('foobar');">echo</span> <span style="padding: 10px; border: 1px solid" onclick="cas();">Kolik je?</span> <span id="cas">nevim</span> </body> </html>
Možná by se zde hodilo uvést nějaké výsledky benchmarků, ale nejsem si jistý o vypovídací hodnotě u tak jednoduchého programu. Faktem ale je, že kompilátor ghc většinou generuje co do rychlosti mnohem efektivnější kód než jazyky, které se pro web běžně používají (viz. The Computer Language Benchmarks Game). Paměťová náročnost také není nikterak velká (FreeBSD 6.2):
#ps aux ... www 2432 0.0 0.1 3052 1240 ?? I 12:05PM 0:00.00 /root/code/ajax/ajax-simple/main.fcgi ...
Tedy tento příklad v paměti zabírá něco málo pod 3 MB.
Kompletní příklad obsahující zdrojový kód, ukázkové html, Makefile a konfigurační soubor pro lighttpd můžete stáhnout zde.
V případě, že máte nainstalované potřebné knihovny, stačí změnit cesty v lighttpd.conf (vše, co začíná na /root/code/ajax/ajax-simple/) a zadat
make run
, což program skompiluje a spustí lighttpd na portu 8080. Testovací příklad bude dostupný na URL http://localhost:8080/test.html.