[ zurück ]

Programmierung von Windows-CGI


allgemeine Anforderungen

Die Programmierung von Windows-CGI-Programmen erfordert gegenüber der Programmierung sonstiger Applikationen keinerlei besondere Techniken. Das zu programmierende Script muß als Input die Daten aus dem vom Server per Namen in der Kommandozeile übergebenem temporären CGI-Data-File (und eventuell aus dem Content-File und den Form-External-Files) herausziehen und alle seine Outputs in das ebenfalls vom Server benannte temporäre Output-File schreiben.

Da das Script auf dem ohnehin mehr oder weniger stark belasteten Server-Computer abläuft, sind allerdings einige Eckpunkte zu beachten, um nicht durch schlecht programmierte Scripts die Performance des Gesamtsystems in die Knie zu zwingen. Die unter diesem Aspekt besonders zu beachtenden Punkte sind: Minimierung der Anzahl der tatsächlichen I/O-Zugriffe

Im Gegensatz zu Standard-CGI, das für die Eingaben Umgebungsvariablen und für die Ausgaben die Standardausgabe nutzt, verwendet Windows-CGI in Ermangelung dieser Instrumentarien temporäre Übergabedateien. Ein derartiger Datenaustausch ist schon naturgemäß um ein Vielfaches langsamer und systembelastender. Deshalb sollte bei der Programmierung alles getan werden, um die Anzahl der Zugriffe auf die Übergabedateien zu begrenzen.

Bei der Win-CGI-Programmierung sollten unbedingt speichergepufferte Zugriffstechniken für die I/O-Files verwendet werden. In allen zur Windows-Programmierung üblichen Sprachen bietet sich dazu die Nutzung von Memory-Streams und File-Streams an.

Die Eingabedateien sollten also nicht Zeile für Zeile oder gar Byte für Byte eingelesen und analysiert werden sondern im Ganzen mit einem Zugriff aus dem temporären File in eine Speicherstruktur abgebildet werden. Da das CGI-Data-File ohnehin die Struktur einer INI-Datei hat, können die in der jeweiligen Programmiersprache für INI-Files vorhandenen Klassen/Objekte mit deren Methoden eventuell zweckmäßig eingesetzt werden. Aber noch besser mit eigenen Speicherstrukturen läßt sich die Dateneingabe schonend und effizient programmieren.

Für die Ausgabe gilt sinngemäß das Gleiche. Es wäre unklug, die Antwort des CGI-Scripts Zeile für Zeile direkt in das temporäre Output-File zu schreiben. Statt dessen sollte das Script alle Ausgaben zunächst in einem Memory-Abbild puffern und erst beim Beenden diesen Puffer im Block in die Ausgabedatei schreiben.

Ressourcenschonende Programmierung

Mit echten Ressourcen hat ein Win-CGI-Script ohnehin nicht viel zu tun, falls man nicht gerade versucht Grafiken dynamisch aus vorgehaltenen Symbolteilen oder Standardantworten aus vorrätigen Stringlisten zusammenzusetzen.

Grund hierfür ist, daß kein Nutzer unmittelbar am Server mit dem Script agiert. So braucht das CGI-Script weder ein Menü noch Accellerator-Tasten, ja nicht einmal ein Icon. Sogar noch weiter lassen sich die Einsparungen am Programm treiben. Das Win-Cgi-Programm braucht nicht einmal ein eigenes Fenster/Formular. Jede einschließlich der visuellen Programmiersprachen ermöglicht derartige "formlose" Programme.

Zu überlegen ist, wie das Script an die für die Ausgabe notwendigen Daten herankommt. Sehr oft wird ja mit dem CGI-Script eine Datenbank abgefragt. Die Datenbasis muß nicht (und sollte in vielen Fällen auch nicht) auf dem Webserver liegen, sollte aber im lokalen Netz gut und schnell erreichbar sein. Bei häufigen Anfragen an große Datenbanken wird das CGI-Script den Webserver zu stark belasten. Dann sollte die Datenbank auf einem eigenen Datenbankserver laufen und das CGI-Script nur die Anfrage an diesen Server realisieren.

Zu bedenken ist auch, daß das Script bei jedem Aufruf komplett neu in den Speicher geladen wird und nicht resistent bleibt (im Gegensatz zu ISAPI-Techniken). Deshalb sollte man neben der Größe des Scripts auch die Zahl der benutzten DLLs im Auge behalten und keinen Wildwuchs mit unzähligen eigenen DLLs für die Scripts zulassen.

keine Beeinflussung anderer Prozesse auf dem Server

Der Betriebssicherheit des Scripts kommt eine enorme Bedeutung zu. Es gibt derzeit in der Netzwelt ohnehin schon genügend Schwachstellen, über die sich ein Server festfahren kann. Das Script sollte hier nicht ein weiterer Risikofaktor sein.

Alle Fehlersituationen müssen im Programmcode abgefangen und automatisch bereinigt werden. Eine Meldungsbox an den Benutzer wie sonst üblich ergibt keinen Sinn. Das Script muß sich trotz Fehler beim Datenzugriff, trotz fehlerhafter Eingabe durch den Aufrufer usw. stets ordentlich beenden und eine korrekte Antwort an den Server zurückliefern.

Das Script darf laut CGI-Spezifikation die Z-Ordnung der auf dem Server laufenden Fenster nicht ändern (vgl. cgi13doc.htm#42). Da das Script aber sowieso nicht fensterorientiert ist, gibt es auch keinen Grund, derartige Aktionen hineinzuprogrammieren. Von der Aktivierung andere Programme/Prozesse/Anwendungen auf dem Server-Computer vom Script aus sollte man die Finger lassen.

Programmierung der Scripteingaben

Das Script erhält beim Aufruf durch den Webserver den Namen des CGI-Data-File als ersten Kommandozeilenparameter mit (vgl. cgiwin.htm#Bsp2). Die weiteren Eingabedateien (Content-File, Form-External-Files, Form-Huge-Files) sind in den entsprechenden Sektionen des CGI-Data-File mit vollem Pfadnamen aufgeführt (vgl. cgiwin.htm#Bsp1).

In vielen Fällen wird ausgewertet werden müssen, ob die Anfrage an das Script über die Methode GET oder POST erfolgt. Dazu muß in der Sektion [CGI] des CGI-Data-File der Schlüssel "REQUEST METHOD" gelesen werden.

In den meisten Fällen werden aber die mit der Anfrage geschickten Daten von entscheidendem Interesse für den weiteren Ablauf des Scripts sein. Bei Abfragemethode GET stehen diese im "QUERY STRING" in der Sektion [CGI], bei Abfragemethode POST URL-verschlüsselt im Content-File (vgl. cgiwin.htm#Bsp3).

Formulardaten, die üblicherweise mit POST versandt werden, werden vom Server dekodiert und aufbereitet in die Sektion [Form Literal] des CGI-Data-File gelegt. Damit könnte man wunderbar einfach auf die Inhalte der Formularfelder zugreifen, wenn da nicht zwei nennenswerte Hindernisse wären.

Problem 1 sind die deutschen Umlaute. Wenn ein Anwender beim Ausfüllen des Formulars in ein Formularfeld Text mit Umlauten (oder sonstigen Sonderzeichen mit Codenummer größer 127 oder kleiner 32) eingibt, kann der Server das ganze Feld nicht mehr URL-dekodieren. Diese Felder und deren Inhalt tauchen dann einfach nicht im Abschnitt [Form Literal] auf. Statt dessen wird der Feldname in den Abschnitt [Form External] des CGI-Data-File aufgenommen. Dahinter steht der vollständige Pfadname zu einem weiteren temporären File, das nun den undekodierten Inhalt des Feldes enthält. Das gleiche Problem gilt für mehrzeilige Felder, die die Eingabe von Enter-Tasten zulassen.

Problem 2 sind Formularfelder mit mehr als 255 Zeichen. Auch diese werden prinzipiell nie in den Abschnitt [Form Literal] sondern in [Form External] aufgenommen. Das Problem dürfte in der Praxis aber bereits wesentlich seltener auftreten.

Dritte Ausnahme sind Eingaben mit mehr als 65535 Bytes, die aber praktisch nicht vorkommen. Hier würde man den entsprechenden Hinweis in der Sektion [Form Huge] finden.

Wenn also deutsche Umlaute möglich sind oder Eingabetexte mit Enterzeichen vorkommen oder Formularfelder länger als 255 Zeichen vorhanden sind, müssen außer [Form Literal] auch die beiden anderen Sektionen ausgewertet werden. Da es zumeist aufwendiger ist, dieses Abschnitt für Abschnitt nach speziellen Vorschriften zu tun, sei empfohlen, gleich das ganze Content-File neu und nach einem einheitlichen Algorithmus zu dekodieren. Das mag für den englischen Sprachraum unnütz sein, unter deutschen Bedingungen erscheint es aber zweckmäßig.

Die Regeln für die URL-Kodierung (Section 2.2 of RFC 1738) des Content-File sind schnell erläutert:

Sonderzeichen im Text sind als Escape-Sequenz, bestehend aus dem Prozentzeichen ("%") und zwei hexadezimalen Ziffern verschlüsselt. Leerzeichen zwischen den Worten eines Formularfeldeintrages werden als Pluszeichen ("+") geliefert. Formularfeldname und Feldwert sind mit dem Gleichheitszeichen ("=") verbunden. Die einzelnen Formularfelder sind durch ein Undzeichen ("&") voneinander abgegrenzt.

Ein Dekodieralgorithmus für derartige Verschlüsselungen ist in jeder Programmiersprache mit wenigen Zeilen zu realisieren. Zweckmäßigerweise kann zur Dekodierung auch der Schlüssel "Content Length" aus dem Abschnitt [CGI] des CGI-Data-File genutzt werden.

Außer dem Content-Typ "application/x-www-form-urlencoded" gibt es gelegentlich den Typ "mutipart/form-data", der aber im Zusammenhang mit einfachen Anfrage-Formularen nicht verwendet werden muß.

Programmierung der Ausgaben

Das CGI-Programm schreibt seine Ausgaben in die vom Server als Output-File bezeichnete Datei.

Der Server ist dann für den Transport der Daten zum anfragenden Client entsprechend HTTP verantwortlich. Das bedeutet, daß der Server normalerweise den notwendigen HTTP-Kopf zum CGI-Ergebnisses hinzufügt (Beispiele siehe cgi13doc.htm#8). Es ist aber auch direkte Ausgabe an den Client möglich. Dann erzeugt das CGI-Script auch den kompletten Header mit.

Egal welche Variante gewählt wird, der Datenrumpf muß immer einem gültigen Mime-Typ entsprechen. Das wird manchmal einfach "text/plain" sein, meistens aber "text/html". Das Script muß also seine Ausgabedaten in ein HTML-Gerüst einpassen. Datenbankabfragen werden beispielsweise oft in Tabellen umgesetzt.

Für die direkte Client-Ausgabe muß das Script auch die Content-Länge des nachfolgenden Datenrumpfes mit in den Header des Output-File eintragen. Auch dafür bietet es sich an, die Ausgaben zuerst im Speicher zu puffern und sie dann im Block in die temporäre Datei zu schreiben, womit der Forderung nach speichergepufferter Ausgabe Rechnung getragen ist.

Wie sich nun ein Windows-CGI-Script im Detail erstellen läßt, ist in cgidelph.htm speziell für die Belange von Delphi dargestellt.


[ Seitenanfang ] [ Win-CGI ]

J. Hummel,   1997