Bob Swart (aka Dr.Bob)
CGI met Kylix 2 Open Edition

Een eerdere versie van dit artikel verscheen in Blaise 58, oktober 2001.

Op dit moment zijn er drie edities van Kylix 2 beschikbaar: Kylix 2 Enterprise, een dure versie voor desktop, database en gedistribueerde (web) server toepassingen, Kylix Professional, zonder de ondersteuning voor gedistribueerde toepassingen (maar met WebBroker), en Kylix Open editie, een Open Source variant, geheel zonder de ondersteuning voor web server toepassingen (noch WebSnap, noch WebBroker).
Aangezien niet iedereen kapitaalkrachtig genoeg zal zijn om Kylix 2 Enterprise of zelfs Kylix 2 Professional aan te schaffen, wil ik deze keer laten zien hoe we web server toepassingen kunnen bouwen in Kylix Open Edition zonder daarbij gebruik te maken van de speciale NetCLX (voormalig WebBroker) componenten.

Common Gateway Interface
De eenvoudigste manier om een web server toepassing te maken zonder NetCLX is een zogenoemde Common Gateway Interface (CGI) toepassing. Die leest van standaard input, en genereert standaard output (meestal HTML, maar dat kan ook iets anders zijn, zoals GIF of JPEG plaatjes of zelfs streaming video of audio).
De meeste distributies van Linux installeren automatisch een web server. Meestal is dat Apache, die ik ook in dit artikel zal gebruiken. Als Apache niet geïnstalleerd is kun je kijken of hij alsnog op de Linux CD's staat, en anders is altijd de laatste versie te downloaden van de http://www.apache.org website.

CGI Output
Laten we ons beperken tot het produceren van HTML als output. Een CGI web server toepassing kan dan in feite gebouwd worden als een "console" toepassing (File | New - en dan kiezen voor Console ...), en via writeln statements de HTML code wegschrijven. Voordat we echter beginnen met het wegschrijven van HTML, moet de web server toepassing eerst (aan de web server zelf) vertellen wat voor soort output er gestuurd wordt. De web server gebruikt deze informatie weer om aan de web client (meestal een web browser) door te geven wat voor soort data er volgt. In ons geval is dat HTML, wat het meest voorkomende voormaat is, maar toch moeten we dit explicit opgeven. Dat gebeurt in de eerste twee regels tekst die onze CGI web server toepassing wegschrijft, en wel als volgt:

  writeln('content-type: text/html');
  writeln;
In de eerste regel geef ik aan het formaat text/html is (een MIME type), en direct hierna moet verplicht een lege regel volgen. Vanaf dat moment kunnen we de HTML gaan schrijven. Wie nog niks of weinig weet van HTML kan hiervoor het beste een naslagwerk aanschaffen (er zijn kleine "HTML in 10 Minuten" gidsjes die de meeste mogelijkheden van HTML kort en duidelijk kunnen uitleggen).
Het volgende kleine programma laat bijvoorbeeld de tekst "Kylix 2 Open Edition!" zien:
  program Hello;
  {$APPTYPE CONSOLE}
  begin
    writeln('content-type: text/html');
    writeln;
    writeln('<html>');
    writeln('<body bgcolor="ffffcc">');
    writeln('<h1>Kylix 2 Open Edition!</h1>');
    writeln('</body>');
    writeln('</html>');
  end.
Als we dit programma compileren tot "Hello" en vervolgens het resultaat in de cgi-bin directory van Apache neerzetten (op mijn Red Hat installatie kan ik die vinden in /home/httpd/cgi-bin), dan kunnen we het programma vanuit een web browser uitvoeren als http://localhost/cgi-bin/Hello, zoals het plaatje laat zien.

In plaats van localhost kun je ook het IP adres of de logische (DNS) naam van de machine opgeven.

Euro Rekenmachine
Als iets nuttiger voorbeeld, zal ik nu een gulden-naar-euro (en terug) omzetter bouwen in Kylix. Hiervoor heb ik reeds de volgende HTML startpagina geschreven:

  <html>
  <body>
  <form method="post" action="http://localhost/cgi-bin/convert">
  Gulden: <input type="text" name="Gulden"> <br>
  Euro: <input type="text" name="Euro"> <br>
  <input type="submit" value="Converteer!">
  </form>
  </body>
  </html>
Het action deel van de form-tag geeft aan dat ik een web server toepassing wil uitvoeren die staat op de localhost webserver in de cgi-bin directory, en als naam convert heeft. De toepassing convert zal de input variabele Gulden naar Euro moeten omzetten, of (als Gulden leeg is), de waarde van Euro naar Gulden.

Het bestand euro.htm heb ik in de /home/httpd/html directory neergezet, waarna ik het als http://localhost/euro.htm in een web browser kan laten zien (zie hierboven). Ik had natuurlijk ook deze HTML code vanuit het Kylix web server programma kunnen laten genereren - wat een leuke oefening voor de lezer is.

CGI Input
En dat brengt ons bij het tweede deel van dit artikel: behalve het genereren van HTML output, zou het natuurlijk ook handig zijn als web server toepassingen de input van de gebruikers kunnen lezen (anders is het web niets anders dan een televisie waarbij je wel van zender kunt veranderen, maar verder geen feedback of sturing kunt geven - laat staan boeken kunt bestellen).
Zoals ik al eerder aangaf, is een web server toepassing in feite een normale console toepassing, die standaard output genereert. Het zal dan ook niet onlogisch overkomen dat de input van standaard input gelezen moet worden. Echter de vraag is: hoeveel input moet er gelezen worden? Dit is een belangrijke vraag, want er volgt geen "end-of-file" teken, en als de web server toepassing teveel probeert te lezen blijft hij "hangen" (wachtend op antwoord). Gelukkig worden er ook zgn. environment variabelen van een waarde voorzien, waaronder de "CONTENT_LENGTH" variabele. Desalnietemin lijkt het niet eenvoudig om snel achter de input te komen die de gebruiker heeft meegestuurd - er moet op z'n minst heel wat gebeuren.

DrBobCGI
Omdat ik al langer web server toepassingen schrijf (ook met Delphi), heb ik een speciale unit geschreven die in feite het verzamelen van de input voor zijn rekening neemt. De unit heet DrBobCGI, en is door iedereen gratis te gebruiken (maar wel op eigen risico).

Converteer!
De unit DrBobCGI heeft een funktie "Value" die ons de waarde van de CGI input variabelen kan verschaffen. Als strings, dus we zullen ze nog moeten converteren naar integers. Dit doe ik altijd met StrToIntDef (uit de SysUtils unit), waarbij we een "default" waarde kunnen opgeven voor als de conversie niet goed gaat, bijvoorbeeld bij een lege string. Het gebruik gaat als volgt:

  program convert;
  uses
    DrBobCGI, SysUtils;
  var
    Gulden, Euro: Integer;
  begin
    Gulden := StrToIntDef(Value('Gulden'),0);
    Euro := StrToIntDef(Value['Euro'),0);
Nadat we de waarden van Gulden en Euro hebben opgehaald, moeten we kijken wat we gaan converteren. Als Gulden gelijk is aan 0, dan ga ik de Euros naar Guldens converteren, en anders andersom:
    if Gulden = 0 then
      Gulden := Round(Euro * 2.20371)
    else
      Euro := Round(Gulden / 2.20371)
Merk op dat ik de berekeningen moet afronden met Round omdat ik gebruik heb gemaakt van Integer variabelen in plaats van Doubles. Weer een kleine oefening voor wie dit programma mooier wil maken. Tot slot hoef ik als laatste stap alleen nog maar de output als HTML weg te schrijven, wat als volgt kan gebeuren:
    writeln('content-type: text/html');
    writeln;
    writeln('<html>');
    writeln('<body bgcolor="ffffcc">');
    writeln('<h1>Kylix 2 Open Edition!</h1>');
    writeln('<p>',Gulden,' Gulden is (afgerond) ',Euro,' Euro.</p>');
    writeln('</body>');
    writeln('</html>');
  end.
De drie kleine listings bij elkaar vormen het gehele programma "convert" (die dus wel de unit DrBobCGI nodig heeft), en het resultaat van de conversie van 25 gulden is 11 euro. Bij benadering dan...

Natuurlijk hebben we deze keer maar simpele web server toepassingen geschreven. Echter, de technieken die we gebruikt hebben werken met elke versie van Kylix en Delphi (behalve de 16-bits Delphi 1.0). Ook met de gratis Kylix Open Edition (of Delphi 6 Open Edition) kunnen - met behulp van de unit DrBobCGI - web server toepassingen gebouwd worden. De laatste versie van unit DrBobCGI.pas (compatible met Kylix en Delphi) is te vinden op http://www.drbob42.com/DrBobCGI.
Mocht iemand nog vragen, opmerkingen of suggesties hebben, dan hoor ik die het liefst via .


This webpage © 2001-2006 by webmaster drs. Robert E. Swart (aka - www.drbob42.com). All Rights Reserved.