Det å skrive CGI-skript (Common Gateway Interface) i Ruby skiller seg ikke nevneverdig fra å skrive CGI-skript i andre språk. Skriv ut HTTP-hodelinjer (headers), hent inn CGI-variabler, generer HTML (eller noe annet interessant innhold) dynamisk og spyl det av gårde til klienten.
1| #!/store/bin/ruby 2| # ^^^ - linje for å angi hvor man finner Ruby-fortolkeren 3| 4| # Print ut HTTP-hodelinjer for å angi at vi serverer HTML. 5| print "Content-type: text/html\r\n\r\n" 6| 7| # Server litt HTML. 8| print "<html><body><h1>Hei verden!</h1></body></html>" |
Øverste linje angir hvor Ruby-fortolkeren befinner seg på serveren.
/store/bin/ruby
er bare en vanlig plassering
på NTNU maskiner som bruker store
.
Prøv å skriv 'which ruby
' om du lurer på hvor fortolkeren er på den maskinen du er på nå.
Men dette var ikke særlig spennende uten noen mulighet for å påvirke resultatet dynamisk...
... så la oss lage en liten web-basert kalkulator.
1| #!/store/bin/ruby 2| print "Content-type: text/html\r\n\r\n" 3| # Starter HTML-dokumentet. 4| print '<html><body>' 5| 6| # Hent inn CGI-biblioteket. 7| require 'cgi' 8| # Lag en instans slik at vi får tak i CGI-variablene. 9| cgi = CGI.new 10| 11| # Hent CGI-variablene 12| x = cgi['x'][0] # Oppslaget returnerer en Array, 13| y = cgi['y'][0] # så vi plukker ut første element. 14| 15| # Skriv dem bare ut dersom vi fikk noe. 16| if (x and x.size.nonzero?) and 17| (y and y.size.nonzero?) then 18| a = x.to_i # Gjør om til heltall. 19| b = y.to_i 20| print "#{a} multiplisert med #{b} er ", a*b 21| end 22| 23| # Skriv ut et lite skjema. 24| print '<form>' 25| print '<input name="x" type="text"> *' 26| print '<input name="y" type="text"> = ' 27| print '<input type="submit" value="gange">' 28| print '</form>' 29| 30| # Avslutter HTML-dokumentet. 31| print '</body></html>' |
CGI-biblioteket kan også hjelpe deg litt med å skrive HTML-koden.
1| #!/store/bin/ruby 2| require 'cgi' 3| 4| # CGI-biblioteket kan også hjelpe deg med å få skrevet HTML-koden. 5| cgi = CGI.new('html4') 6| cgi.out { 7| cgi.html { 8| cgi.head { 9| cgi.title { 'Penere kildekode?' } 10| } + 11| cgi.body { 12| cgi.h1 { 'Gjør dette kildekoden penere?' } + 13| cgi.p + 14| 'Eller får man krøllparentes-overdose?' 15| } 16| } 17| } |
Du slipper å huske hvilke element som skal avsluttes og i hvilken rekkefølge, men får noe som ligner litt for mye på Lisp.
Cookies er en måte å lagre små datamengder på maskinen til brukeren som surfer inn på sidene våre, som vi kan hente ut igjen når de kommer tilbake en annen gang.
1| #!/store/bin/ruby 2| require 'cgi' 3| c = CGI.new('html4') 4| 5| # Hent ut den gamle kaken. 6| gammel_cookie = c.cookies['rubywebnuby'] 7| 8| # Kurstekst i første element, antall besøk i andre element. 9| kurs_tekst, antall_tekst = gammel_cookie 10| antall_besok = if antall_tekst then 11| antall_tekst.to_i + 1 12| else 0 end 13| 14| # Lag ny kake. 15| ny_cookie = CGI::Cookie.new('rubywebnuby', # Kakenavn. 16| 'Ruby Web Nuby', antall_besok.to_s # Verdier. 17| ) 18| 19| c.out( 'cookie' => [ny_cookie] ) do # Sett kaken via HTTP. 20| c.html do 21| c.body do 22| # Print ut de forrige kakene 23| gammel_cookie.join(c.br) + 24| "<P>Du har vært her #{antall_besok} ganger før, " + 25| "da i forbindelse med #{kurs_tekst} kurs." 26| end 27| end 28| end |
Cookies er et kjekt verktøy når man ikke har noen database å lagre i, dataene er små eller brukerne er overmåte allergisk mot innloggingsskjermer. Ellers er det kanskje en ide å lagre ting på serversiden og/eller i skjulte input-elementer.
Sesjoner er et overbygg over cookies, som lagrer en liten bit data i en cookie hos klienten, og (potensielt) et tonn med data på serveren.
1| #!/store/bin/ruby 2| require 'cgi' 3| require 'cgi/session' 4| c = CGI.new('html4') 5| sesjon = CGI::Session.new( c, 6| 'session_key' => 'rubywebnuby2', 7| 'prefix' => 'ruby_sesjon.') 8| 9| # Hent ut antall besøk fra sesjonen 10| antall_tekst = sesjon['AntallBesok'] 11| antall_besok = (antall_tekst ? antall_tekst.to_i+1 : 0) 12| 13| # Sett det nye antallet tilbake i sesjonen 14| sesjon['AntallBesok'] = antall_besok 15| 16| c.out do 17| c.html do 18| c.body do 19| "Du har vært her #{sesjon['AntallBesok']} ganger før." 20| end 21| end 22| end |
Da har vi iallfall fått lagret en god del mer på serversiden, og høyde, alder, øyenfarge, samt en million "theme"-innstillinger for webapplikasjonen vår må ikke sendes over nettet hver gang en side hentes.
Til nå har vi bare kjørt disse CGI-skriptene på den trauste, trege måten. For hvert kall til sidene, må Ruby-fortolkeren startes opp og biblioteker lastes. Dette er ufattelig ineffektivt.
Vi trenger å ha minimum Ruby-fortolkeren, og helst også biblioteker, ferdig lastet og klare til dyst når en HTTP-forespørsel kommer inn. Det er flere muligheter, blant annet:
mod_ruby, WEBrick, Radical, fastcgi, IOWA, Borges, httpd, httpserv, wwwd, wwwsrv ... etc