[ zurück ]

Das Windows CGI 1.3a Interface

gekürzte sinngemäße Übersetzung aus dem Englischen (v. J. Hummel)
Original siehe http://website.ora.com/wsdocs/32demo/windows-cgi.html
(Datum der Originalfassung: 18-Feb-96)


Inhaltsübersicht

Überblick

Eine große Anzahl von World-Wide-Web-Anwendungen werden am Besten ausgeführt, indem sie externe Programme benutzen, die von einem Webserver gesteuert werden. Die zunehmende Akzeptanz von RAD-Entwicklungstools wie Visual-Basic oder Delphi haben Anlaß gegeben, diese Werkzeuge webfähig zu machen. Das weitverbreitete Common-Gateway-Interface (CGI) benutzt aber Techniken, die gut für Unix-Umgebungen geeignet sind. Um Windows-RAD-Tools für CGI zu nutzen, ist ein anderes Interface notwendig. Es ist die Zweckbestimmung dieser Spezifikation, solch eine Schnittstelle zu definieren.

I/O Spooling

Ein Schlüsselkennzeichen von Windows-CGI ist gespulter (spooled) Datenaustausch zwischen dem Server und dem CGI-Programm. Es ist unentbehrlich, daß der Server eine effiziente Übertragung der Daten zwischen den Spool-Dateien und dem Netzwerk unterstützt. Das bedeutet, daß der Server speichergepufferte Techniken unterstützen sollte und die Zahl der tatsächlichen I/O-Netzwerkzugriffe minimieren sollte.

HTML-Formulardaten-Dekodierung

Windows-CGI erfordert, daß der Webserver die in einer POST-Anforderung gegebenenfalls vorhandenen Formulardaten dekodiert. Es ist nicht erforderlich, daß der Server diese Daten dekodiert, wenn sie im QUERY-STRING der anfordernden URL auftreten.

Es gibt zwei Varianten, wie Formulardaten durch einen Browser zum Server gesandt werden können:

URL-kodiert: Das ist das gebräuchlichste Formulardatenformat. Die Inhalte der Formulardaten sind nach den Regeln der HTML 1.0 Spezifikation umgesetzt und mit "&"-Zeichen verkettet. Diese URL-kodierten Daten werden als Strom mit der Typangabe "application/x-www-form-urlencoded" zum Server gesendet.

Multipart Formulardaten: Diese Format wurde eingeführt, um ein effektives Dateiübertragen mit Formularen zu ermöglichen. Es kann aber auch ohne das Dateiübertragen von Formularfeldern benutzt werden. Die Inhalte der Formularfelder werden als mehrteilige MIME-Nachrichten gesendet. Jedes Feld ist mit einem eigenen Teil enthalten. Als Inhaltstyp wird vom Browser "multipart/form-data" angegeben.

Brauchbare Server müssen beide Formulardatentypen dekodieren können.

Starten des CGI-Programms

Der Server nutzt den "CreateProcess()"-Dienst, um das CGI-Programm zu starten. Der Server hält auch die Synchronisation mit dem CGI-Programm aufrecht, sodaß er erkennen kann, wann das CGI-Programm endet. Das wird über die Win32-Routine "WaitForSingleObject()" erreicht die darauf wartet, daß das CGI-Prozeß-Handle das Programmende angezeigt bekommt. Der Server muß keine Shell benutzen, um das CGI-Programm auszuführen. Das kann ernsthafte Sicherheitsrisiken erzeugen.

Beachte: Das CGI-Programmhandle bekommt die Nachricht bevor der Prozeßabschluß komplett ist. Vertrauen in den Abschluß des Dateischließens, der Freigabe der Handles usw. kann die Ursache für unerklärliche Synchronisationsprobleme sein.

Die Kommandozeile

Der Server muß die CGI-Programmanforderung erledigen durch Ausführen eines "CreateProcess()"-Aufrufs mit einer Kommandozeile in der folgenden Form:

   WinCGI-exe CGI-data-file 

WinCGI-exe: Der komplette Pfad zum ausführbaren CGI-Programm. Der Server benutzt nicht das aktuelle Verzeichnis oder die Pfadangaben. Man beachte, daß das ausführbare Programm keine .EXE-Datei sein muß. Es kann auch ein Dokument sein, vorausgesetzt eine Verbindung mit einem dazugehörigen Programm ist gesichert.

CGI-data-file: Der komplette Pfad zur CGI-Datendatei

Startmethode

Der Server erzeugt den "CreateProcess()"-Prozeß so, daß der herauskommende Prozeß ein verborgenes Hauptfenster hat. Der gestartete Prozeß sollte seinerseits keine Veränderung eines Fensters oder der Z-Ordnung der Fenster auf dem Desktop veranlassen. Der Server unterstützt einen Debug-Modus für CGI-Programme/Scripts. Wenn dieser Modus aktiv ist wird das CGI-Programm so gestartet, daß sein Fenster sichtbar und aktiv ist. Das kann beim Entwanzen der CGI-Applikation helfen.

Dokumentenverbindung

Der Server muß Dokumentenverbindungen beherrschen. Wenn das Ziel einer Windows-CGI-Anfrage ein Dokument ist (keine ausführbares Programm), muß der Server versuchen die zum Dokument zugehörige Anwendung zu finden und diese so zu starten daß das Dokument läuft.

Die CGI-Datendatei

Der Server übergibt Daten an das CGI-Programm durch eine Windows-"private profile"-Datei im "Schlüssel-Wert"-Format. Das CGI-Programm kann dann die Standard Windows-API-Aufrufe zum Aufzählen und Abrufen der "Schlüssel-Wert"-Paare in der Datendatei nutzen.

Die CGI-Datendatei beinhaltet folgende Abschnitte:

Der [CGI]-Abschnitt

Dieser Abschnitt beinhaltet die meisten der CGI-Datenelemente (Accept-Typen, Content und Extra-Headers sind in separaten Sektionen definiert). Jedes Element ist als eine Zeichenkette (String) bereitgestellt. Falls der Wert ein Leerstring ist, wird der Schlüssel ausgelassen. Die Schlüsselworte sind im Folgenden aufgelistet:

Request Protocol: Name und Version des Informationsprotokolls, mit dem die Anfrage eintraf (Format: Protokoll/Version, Beispiel: "HTTP/1.0").

Request Method: Methode, mit der die Anfrage erfolgte. Für HTTP können das "GET", "HEAD" oder "POST" usw. sein.

Executable Path: Logischer Pfad zum CGI-Programm, falls er für Eigenreferenzen gebraucht wird. Diese Angabe kann variieren, falls der Server Mehrfachbeheimatung (multi-homing) mit getrennten logischen Pfadbereichen unterstützt.

Document Root: Physischer Pfad zum logischen Hauptverzeichnis "/". Diese Angabe kann variieren, falls der Server Mehrfachbeheimatung (multi-homing) mit getrennten logischen Pfadbereichen unterstützt.

Logical Path: Eine Anfrage kann den Pfad zu einer weiteren Ressource zur vollständigen Ausführung der Anfrage benötigen. Dieser Punkt beinhaltet den Pfadnamen, so wie er vom Server empfangen wurde, ohne jegliche logisch-zu-physisch Umwandlung.

Physical Path: Wenn die Anfrage logische Pfadinformationen enthält, stellt der Server den Pfad in physischer Form, so wie die normale Zugriffssyntax des Betriebssystems ist, bereit. Diese Angabe kann variieren, falls der Server Mehrfachbeheimatung (multi-homing) mit getrennten logischen Pfadbereichen unterstützt.

Query String: Information, die dem "?" in der die Anfrage erzeugenden URL folgt. Der Server liefert diese Angabe ohne jegliche Dekodierung oder Übersetzung immer dann zur Endanwendung, wenn sie in der aufrufenden URL vorhanden ist.

Request Range: Byte-Umfangsangabe, falls sie mit der Anfrage empfangen wurde. Siehe für mehr Informationen auch derzeitiger Internet-Beschluß (oder RFC), der die Byte-Umfangsangabe-Erweiterung beschreibt. Der Server muß dazu die CGI-Programm-Bestimmung in Bezug auf Byte-Umfangsangabe unterstützen, um mit dieser Spezifikation konform zu sein.

Referer: URL des Dokuments, das den Verweis auf das CGI-Programm enthält. Zu beachten ist, daß in einigen Browsern die Umsetzung dieses Punktes unterbrochen ist.

From: eMail-Adresse des Browser-Nutzers. Zu beachten ist, daß das zwar in der HTTP-Spezifikation enthalten aber nicht in allen Browsern realisiert ist.

User Agent: Namensbeschreibung der Klientsoftware, nicht von allen Browsern erzeugt.

Content Type: Bei Anfragen, die mit Daten behaftet sind, ist das der MIME-Inhaltstyp dieser Daten (Format: Typ/Untertyp).

Content Length: Für Anfragen, die mit Daten behaftet sind, ist das die Länge des Inhalts in Byte.

Content File: Bei Anfragen, die mit Daten behaftet sind, macht der Server die Daten dem CGI-Programm durch Einschreiben in diese Datei verfügbar. Der Wert dieses Punktes ist der komplette Pfadname zu dieser Datei.

Server Software: Name und Version der Informationsserver-Software, die die Anfrage beantwortet (und das CGI-Programm abarbeitet). (Format: Name/Version)

Server Name: Der Netzwerks-Wirtsname oder Deckname des Servers, wie er für selbstreferenzierende URLs benötigt wird. Dieser kann (in Kombination mit dem Serverport) benutzt werden, um die vollständige URL zum Server zu erstellen. Diese Angabe kann variieren, falls der Server Mehrfachbeheimatung (multi-homing) unterstützt. Der Wert dieses Punktes muß der Wirtsname des Hosts sein, auf dem die aktuelle Anfrage empfangen wurde.

Server Port: Netzwerk-Port-Nummer, auf der der Server empfängt. Das wird auch für selbstreferenzierende URLs benötigt.

Server Admin: eMail-Adresse des Serveradministrators. Sie wird in Fehlermeldungen und zum Senden von MAPI-Post an den Administrator und zum Bilden von "mailto:"-URLs in den generierten Dokumenten benutzt.

CGI Version: Version der CGI-Spezifikation, zu der der Server paßfähig ist (Format: CGI/Version, für diese Version: "CGI/1.2(Win)").

Remote Host: Netzwerks-Wirtsname des Klientsystems (Anfordernder), falls verfügbar. Dieser Eintrag wird zum Anmelden benutzt.

Remote Address: Netzwerks-(IP)-Adresse des Klientsystems. Dieser Eintrag wird zum Anmelden benutzt, falls der Wirtsname nicht verfügbar ist.

Authentication Method: In der Anforderung angegebene protokollspezifische Beglaubigungsmethode. Falls vorhanden, ist der Wert normalerweise "Basic". Der Server muß diese Angabe bereitstellen, ganz gleich ob er diese Angabe selbst für Beglaubigungen nutzt oder nicht.

Authentication Realm: In der Anforderung angegebener methoden-spezifischer Gültigkeitsraum. Falls in der Anfrage vorhanden muß der Server diese Angabe bereitstellen, ganz gleich ob er die Angabe selbst für Beglaubigungen nutzt oder nicht.

Authenticated Username: Benutzername, den der Klient beim Beglaubigungsversuch benutzt, falls in der Anforderung angegeben. Falls in der Anfrage vorhanden muß der Server diese Angabe bereitstellen, ganz gleich ob er die Angabe selbst für Beglaubigungen nutzt oder nicht.

Authenticated Password: Paßwort, das der Klient beim Beglaubigungsversuch benutzt, falls in der Anforderung angegeben. Falls in der Anfrage vorhanden muß der Server diese Angabe bereitstellen, ganz gleich ob er die Angabe selbst für Beglaubigungen nutzt oder nicht.

Beachte: Bestehende Praxis auf dem O'Reilly-WebSite-Server ist es, daß der CGI-Programmname mit einem Dollarzeichen "$" beginnen muß, um die Paßwortversorgung durch das CGI-Interface zu haben. Das ist nach dieser Spezifikation nicht gefordert. Es ist aber empfohlen, weil es den CGI-Programmierer nötigt, Spezielles zu unternehmen weil die Paßwortinformationen in die Serverumgebung übertragen wurden.

[Accept] Abschnitt

Dieser Abschnitt beinhaltet die vom Klienten akzeptierten Datentypen wie sie im Anforderungskopf gefunden wurden (Accept: Typ/Untertyp {Parameter}). Wenn Parameter (z.B. "q=0.100") vorhanden sind, sind sie Bestandteil des Wertes zum Eintrag. Wenn keine Parameter da sind, ist der Wert "Yes".

Beachte: Die akzeptierten Typen können einfach durch das CGI-Programm über einen Aufruf von "GetPrivateProfileString()" mit "NULL" als Schlüsselname aufgezählt werden. Damit werden alle Schlüssel in der Sektion als nullterminierter String mit doppeltem Nulltrennzeichen zurückgegeben.

[System] Abschnitt

Dieser Abschnitt beinhaltet Punkte, die spezifisch für die Windows-Umsetzung von CGI sind. Die folgenden Schlüssel werden benutzt:

GMT Offset: Anzahl der Sekunden, die zur GMT addiert werden müssen um die Ortszeit zu erhalten. Für Pazifik-Standard-Zeit ist die Zahl -28800. Nützlich zum Errechnen der GMT.

Debug Mode: Ist "No" bis der Servermodus "CGI/script tracing" ausgewählt ist, dann ist es "Yes". Nützlich zum bedingten Suchen im CGI-Programm.

Output File: Voller Pfadname der Datei, in der der Server die CGI-Programmergebnisse zu empfangen erwartet.

Content File: Voller Pfadname der Datei, die die Dateninhalte (sofern vorhanden) der ankommenden Anforderung enthält.

[Extra Headers] Abschnitt

Diese Sektion beinhaltet die Extra-Köpfe, die in der Anforderung eingeschlossen sind in "Schlüssel=Wert"-Form. Der Server muß Beides (Schlüssel und Wert) zuvor URL-dekodieren um sie in die CGI-Datendatei zu schreiben.

Beachte: Die extra Köpfe können leicht durch das CGI-Programm über einen Aufruf von "GetPrivateProfileString()" mit "NULL" als Schlüsselname aufgezählt werden. Damit werden alle Schlüssel in der Sektion als nullterminierter String mit doppeltem Nulltrennzeichen zurückgegeben.

[Form Literal] Abschnitt

Falls die Anfrage eine HTTP-POST-Anforderung von einem HTTP-Formular ist (mit Inhaltstyp "application/x-www-form-urlencoded" oder "multipart/form-data"), wird der Server die Formulardaten dekodieren und sie in den [Form Literal]-Abschnitt plazieren.

Für URL-kodierte Formulardaten, deren Rohform "Schlüssel=Wert&Schlüssel=Wert&..." mit URL-kodierten Wertteilen ist, wird der Server die "Schlüssel-Wert"-Paare am "&"-Zeichen trennen, dann die Schlüssel von den Werten am "="-Zeichen teilen, die Wertausdrücke URL-dekodieren und die Ergebnisse in "Schlüssel=dekodierter Wert"-Form in den [Form Literal]-Abschnitt setzen.

Für Multipart-Formulardaten deren Roheingabeform ein mehrteiliges MIME-Stil-Format mit separaten Teilen für jedes Feld ist, wird der Server die Feldnamen und Werte aus jedem Teil herausziehen und die Ergebnisse in der "Schlüssel=Wert"-Form in den den [Form Literal]-Abschnitt setzen.

Wenn das Formular einige Mehfachauswahlelemente beinhaltet, werden einige Schlüssel mehrfach auftreten. In diesem Fall wird der Server ein normales "Schlüssel=Wert"-Paar für das erste Auftreten erzeugen und wird die Folgezahl der mehrmaligen Vorkommen anhängen. Es ist Sache des CGI-Programms über diese Möglichkeit Bescheid zu wissen und die bezeichneten Schlüssel anständig wiederzuerkennen.

[Form External] Abschnitt

Wenn der dekodierte Wertausdruck länger als 254 Zeichen ist oder wenn der dekodierte Wertausdruck irgendwelche Steuerzeichen oder doppelte Anführungszeichen beinhaltet wird der Server die dekodierten Werte in eine externe temporäre Datei legen und das Feld im [Form External]-Abschnitt auflisten (Format: "Schlüssel=Pfadname Länge", wobei "Pfadname" der Pfad und Name zu der die dekodierten Wertausdrücke enthaltenden temporären Datei und "Länge" die Länge des dekodierten Wertstrings in Byte ist).

Beachte: Man öffne die Datei besser im Binärmodus bis man sicher ist, daß die Formulardaten auch wirklich Text sind.

[Form Huge] Abschnitt

Wenn der ursprüngliche Wertausdruck länger als 65535 Bytes lang ist, wird der Server ihn nicht dekodieren, wohl aber das Schlüsselwort ermitteln und die Lage und Größe des Wertes in der Inhaltsdatei markieren. Der Server listet das Riesenfeld in der [Form Huge]-Sektion (Format: "Schlüssel=Offset Länge", wobei "Offset" der Abstand vom Beginn der Inhaltsdatei ist, in der der Ursprungswert für diesen Schlüssel enthalten ist und "Länge" die Länge des Ursprungsstrings in Bytes ist) auf. Man kann den Offset benutzen, um eine Suche nach dem Beginn der Ursprungsstrings auszuführen und die Länge, um zu erkennen wann der Ursprungswert in den eigenen Dekoder eingelesen ist.

Beachte: Man öffne die Datei besser im Binärmodus bis man sicher ist, daß die Formulardaten auch wirklich Text sind.

[Form File] Abschnitt

Wenn die Anforderung im "multipart/form-data"-Format ist, kann sie eine oder mehrere Dateiübertragungen beinhalten. In diesem Fall wird jede Dateiübertragung in eine externe temporäre Datei ähnlich wie die Form-External-Daten plaziert. Jede dieser Dateiübertragungen ist im [Form File]-Abschnitt aufgelistet.

Format: "Schlüssel=[Pfadname] Länge Typ Xfer [Dateiname]", wobei "Pfadname" der Pfadname der externen temporären, die übertragene Datei enthaltenden Datei, "Länge" die Länge der übertragenen Datei in Bytes, "Typ" der MIME-Inhaltstyp der übertragenen Datei, "Xfer" die Übertragungskodierung der Datei und "Dateiname" der Originalname der gesandten Datei ist. Die eckigen Klammern müssen enthalten sein. Sie werden zur Abgrenzung der Datei- und Pfadnamen benutzt, die Leerzeichen enthalten können.

Beispiel für Formular-Dekodierung

Im folgenden Beispiel enthält das Formular ein kleines Feld, eine Mehfachauswahl mit 2 kleinen Optionen, ein Feld mit 300 Textzeichen, eines mit Zeilenvorschub und ein 230Kbyte großes Feld.
    [Form Literal]
    smallfield=123 Main St. #122
    multiple=first selection
    multiple_1=second selection

    [Form External]
    field300chars=C:\TEMP\HS19AF6C.000 300
    fieldwithlinebreaks=C:\TEMP\HS19AF6C.001 43

    [Form Huge]
    field230K=C:\TEMP\HS19AF6C.002 276920

CGI-Ergebnisaufbereitung

Das CGI-Programm gibt seine Ergebnisse zum Server als einen das Ziel der Anfrage darstellenden Datenstrom zurück. Der Server ist verantwortlich für das Verpacken des Datenstromes entsprechend von HTTP und für die Benutzung von HTTP zum Transport des Datenstromes zum anfragenden Klient. Das bedeutet, daß der Server normalerweise den notwendigen HTTP-Kopf zum CGI-Programmergebnisses hinzufügt.

Der Datenstrom besteht aus zwei Teilen: Dem Kopf und dem Körper. Der Kopf besteht aus einer oder mehreren Textzeilen und ist vom Körper durch eine Leerzeile getrennt. Der Körper beinhaltet MIME-entsprechende Daten, deren Inhaltstyp sich im Kopfteil widerspiegeln muß.

Der Server wird den Körper in keiner Weise interpretieren oder verändern. Es ist wesentlich, daß der Klient exakt die Daten empfängt, die die Endanwendung erzeugt hat.

Spezielle Kopfzeilen

Der Server realisiert die folgenden Kopfzeilen im Ergebnisdatenstrom:

Content-Type: 

Zeigt an, daß der Körper Daten des angegebenen MIME-Inhaltstyps beinhaltet. Der Wert muß ein MIME-Inhaltstyp/Untertyp sein.

URL: <Wert> (Wert eingeschlossen in spitze Klammern) 

Der Wert ist entweder eine vollständige URL oder lokale Dateireferenz oder ein Wert welcher auf ein Objekt anstelle eines Körpers zur Rückgabe zum Klient zeigt. Wenn der Wert eine lokale Datei ist, wird der Server sie als das Ergebnis der Anfrage senden als ob der Klient ein GET für dieses Objekt erzeugte. Wenn der Wert eine vollständige URL ist, wird der Server ein "401 umleiten" zum Klient zurückgeben, um das angegebene Objekt direkt aufzurufen.

Location: 

Gleich wie URL nur diese Form ist neuerdings unerwünscht. Der Wert muß bei dieser Form nicht in spitze Klammern eingeschlossen sein.

Andere Köpfe

Einige andere Köpfe im Ergebnisstrom werden (unverändert) vom Server an den Klient durchgereicht. Es ist die Zuständigkeit des CGI-Programms zu vermeiden, daß Köpfe eingeschlossen werden, die mit diesen unter Anwendung von HTTP kollidieren.

Direkte Rückgabe

Der Server unterstützt für die Endanwendung die Rückgabe der Ergebnisse direkt zum Klient unter Umgehung der Serververpackung des Datenstromes in sein Informationsprotokoll. In diesem Fall liegt es in der Zuständigkeit des CGI-Programms, die komplette nach HTTP gepackte Nachricht zu erzeugen.

Der Server schaut in die Ausgabedatei und wenn diese mit der ersten Zeile "HTTP/1.0" startet vermutet er, daß das Ergebnis eine komplette HTTP-Antwort enthält und sendet das Ergebnis ohne Verpackung zum Klient.

Beispiele:

Das folgende Beispiel stellt eine Antwort dar, die von einem CGI-Programm erzeugt wurde, das durch einen HTTP-Server aufgerufen wurde und aus einem HTML-formatierten Körper besteht:

Content-type: text/html           <== MIME-Typ des Körpers
                                  <== Kopf-Körper-Trennung
<HTML>                            <== Körper beginnt hier
<HEAD>
<TITLE>Sample Document</TITLE>
</HEAD>
<BODY>
<H1>Sample Document</H1>
[... etc.]
</BODY>
<HTML>

Dieses Beispiel stellt eine umgeleitete Reaktion dar, wo der Server den Klient dazu lenkt, das durch eine URL aufgezeigte Objekt abzuholen:

Location: ftp://ftp.netcom.com/pub/www/object.dat  <== URL des Objekts
                                                   <== Leerzeile

Dieses Beispiel stellt eine direkt zurückgegebene Reaktion eines durch einen HTTP-Server aufgerufenen CGI-Scripts dar, wobei das Ergebnis eine komplette HTTP-Reaktion enthält:

HTTP/1.0 200 OK                   <== Start des HTTP-Kopfes
Date: Tuesday, 31-May-94 19:04:30 GMT
Server: WebSite 1.0
Content-type: text/html
Last-modified: Sunday, 15-May-94 02:12:32 GMT
Content-length: 4109
                                  <== Kopf-Körper-Trennung
<HTML> <HEAD>
<TITLE>A document</TITLE>
[... etc.]

[ Seitenanfang ] [ zurück ]

J. Hummel,   Apr. 1997