Entwicklung von Electronic Business Systemen 2 FH Fulda – FB AI CGI: Common Gateway Interface Das Common Gateway Interface bezeichnet eine Schnittstelle, über die beliebige Programme im WWW, die von HTML-Dateien aus aufgerufen und ausgeführt werden können, und die selbst HTML-Code erzeugen und an einen WWW-Browser senden können. Die Verarbeitung der Programme erfolgt auf dem Serverrechner, ebenso wie die Speicherung von Daten. Die Programme können beispielsweise Formulareingaben aus HTML-Dateien verarbeiten, auf dem Serverrechner Daten speichern und dort gespeicherte Daten auslesen. WWW-Seiten werden dadurch zu Interfaces für Anwendungen, beispielsweise für elektronische Warenbestellung oder zum Abfragen von Datenbanken. Die folgende Abbildung zeigt den prinzipiellen Zusammenhang zwischen den einzelnen Komponenten. Quelle: Münz Voraussetzung ist, dass die CGI-Schnittstelle vom WWW-Server unterstützt wird. Die CGI-Schnittstelle besteht aus: einem bestimmten Verzeichnis auf dem Serverrechner, das CGI-Programme enthält (meist cgi-bin oder cgi-local). CGI-Programme oder CGI-Scripts werden dann nur ausgeführt, wenn sie in diesem Verzeichnis liegen. einer Reihe von Daten, die der WWW-Server speichert, und die ein CGI-Script auslesen und verarbeiten kann. Diese Daten speichert der WWW-Server in sogenannten CGI-Umgebungsvariablen. Die aktuelle CGI-Schnitstellendefinition ist Version 1.1. Neben der CGI-Schnittstelle gibt es noch andere Schnittstellen für ausführbare Programme, wie beispielsweise: NSAPI-Schnittstelle (Netscape), ISAPI-Schnittstelle (Microsoft). Dabei handelt es sich, wie in der Einführung beschrieben, um API´s, die für die jeweiligen Server optimiert sind. Dadurch verfügen sie allerdings über eine wesentlich bessere Performance. Der entscheidende Vorteil der CGI-Schnittstelle ist jedoch, dass es sich dabei um einen kommerziell unabhängigen, kostenlosen und produktübergreifender Standard handelt. Programmiersprache Hinsichtlich der zu verwendenden Programmiersprache gibt es keine Festlegungen für CGIProgramme. Ein CGI - Programm muß daher 68617768 Seite 1 von 6 FH Fulda – FB AI Entwicklung von Electronic Business Systemen Betriebssystem-Umgebung des Servers als ausführbares Programm kompiliert werden, oder es muß auf dem Server ein Laufzeit-Interpreter vorhanden sein, der das Programm ausführt. Die meisten CGI-Programme sind in Unix-Shell-Sprache oder in Perl geschrieben. UnixShell wird von allen Unix-Rechnern interpretiert und für Perl muß ein entsprechender Interpreter installiert sein. Perl besitzt sehr mächtige Funktionen, z.B. für Zeichenkettenoperationen oder für das Lesen und Schreiben von Daten. CGI-Aufrufe aus HTML und HTML-Ausgabe über CGI HTML und CGI kommunizieren in beide Richtungen: Richtung 1: Aus einer HTML-Datei kann ein CGI-Script aufgerufen werden Dies geschieht über einen sogenannten GET-Request im HTTP-Protokoll, d. h. der Browser fordert per Request die Verarbeitung eines CGI-Programmes an. Die Anforderung erfolgt genau wie eine normale Webseite, aber der Server erkennt, dass es sich um CGI handelt: GET /cgi-bin/test.pl HTTP/1.1 Accept: www/source Accept: text/html Accept: image/gif User-Agent: MSIE ... From: [email protected] # cgi-bin Server Konfiguration # Formate, die Browser verarbeiten kann Die vom Browser übermittelten Daten werden in Umgebungsvariablen gespeichert (Environmentvariablen). Dabei ensteht das Problem, wie CGI–Programme ihren Programm-Input (z. B. die Eingaben des Benutzers) erhalten. Grundsätzlich gibt es dafür bei CGI nur 2 Wege: über die Standardeingabe (STDIN) oder über die Umgebungsvariablen // siehe Bild Richtung 2: CGI-Programme senden ihre Ausgabe an den Browser Dazu müssen die CGI Programme ein neues HTML-Dokument erzeugen und ausgeben, ebenso Grafiken und Binärdaten zurückliefern, den Browser anweisen, das Dokument in den Cache aufzunehmen (oder auch nicht), einen HTTP-Statuskode an den Browser senden, oder den Server anweisen, ein bestehendes Dokument zurückliefern (Redirection). Die Rücklieferung der Daten an den Browser geschieht über einen Datenstrom an die Standardausgabe (STDOUT). Dieser Stream besteht aus 2 Teilen: Header, Der Header kann vollständig oder partiell sein und beschreibt zB. das Format der zurückgelieferten Daten (ein CGI-Script kann HTML oder andere Dateien an Browser übertragen). Eine Leerzeile signalisiert das Ende des Headers. Bei vollständigem Header können Daten direkt an Client geschickt werden. Üblicherweise wird jedoch ein Stream an den Server geschickt, der den Header vervollständigt. Body, Der Body enthält Daten im beschriebenen Format. Das folgende Beispiel zeigt eine HTTP-Rücksendung, die von einem CGI Programm erzeugt wurde, d. h. das CGI Programm muss diese Ausgaben realisieren. HTTP/1.1 200 OK Date: ...... 68617768 Seite 2 von 6 Entwicklung von Electronic Business Systemen FH Fulda – FB AI Server: .... MIME-version: # partieller Header enthält nur die folgende Zeile Content-type: text/html # Angebot zum Speichern, wenn nicht akzep # tiert Content-length: 2345 # Leerzeile <HTML><HEAD><TITLE>CGI Test</TITLE></HEAD> <BODY> ....... irgendwelcher HTML Text </BODY> </HTML> Dabei ist Content-type ein HTTP Header, der den Inhaltstyp beschreibt. Weitere HTTP Header sind: Content-length: Expires: Location: Pragma: Status: Länge des Ausgabestreams Datum/Uhrzeit der Ungültigkeit des Dokumentes Serverumleitung (kann nicht als Teil eines vollständigen Headers gesendet werden schaltet Documentcaching ein/aus Status der Anforderung (nicht in vollst. Header) Refresh: Set-Cookie: erneutes Laden des Dokumentes durch den Client Client speichert spezifische Daten Inhalte von CGI Programmen 1. Ein CGI-Script kann Daten verarbeiten, die von HTML-Datei beim Aufruf übergeben werden (Beispiel: Datenbank nach Suchbegriff, der über Formular eingegeben wurde durchsuchen). Die Ergebnisse werden in Form von HTML-Code zurückgegeben an Server, dann an Browser direkt an Browser 2. CGI-Scripts können Daten, die über ein Formular eingegeben wurden, auf dem Server speichern (Datei, DB) (Beispiel: Gästebücher, Nachrichtenforen). Beim Absenden des Formulars wird ein CGI-Script aufgerufen, das den Beitrag in einer Datei speichert. Ein zweites CGI-Script oder ein anderer Aufruf des CGI-Scripts kann anschließend HTML-Code mit allen gespeicherten Beiträgen an einen WWW-Browser übertragen. Ein CGI-Script kann aus einer HTML-Datei heraus auf verschiedene Arten aufgerufen werden: über ein Formular. Beispiel: <form action="/cgi-bin/dbanfrage.pl" method="get">. Der Aufruf des Scriptes erfolgt mit Absenden des Formulars. Die Anwenderdaten stehen dem CGI-Script zur Verarbeitung zur Verfügung (wird später behandelt). über Verweise. Als URL-Adresse des Verweisziels wird das ausführbare CGI-Script angegeben. Beispiel: <a href="/cgi-bin/noten.pl">Prüfungsnoten aufrufen</a>) Dies ist sinnvoll für CGI-Scripts, die keinen "Input" vom Anwender benötigen, sondern lediglich feste Datenausgaben erzeugen (z.B. Zugriffsstatistiken). über eine Grafikreferenz. Beispiel: <img src="/cgi-bin/counter.pl"> Dabei muß das CGI-Script allerdings eine Grafikdatei im GIF- oder JPEG-Format an den WWWBrowser zurücksenden (Beispiel: grafische Zugriffszähler). über eine Server Side Include Anweisung Beispiel: <!-- #exec cgi="/cgi--> Mit Hilfe eines CGI-Scripts wird dynamische Information in HTML-Datei eingebunden (z. B. textbasierte Zugriffszähler) bin/noten.pl" 68617768 Seite 3 von 6 FH Fulda – FB AI Entwicklung von Electronic Business Systemen über automatisches Laden des ausführbaren CGI-Programms. Im <meta>-Befehl wird dazu anstelle einer HTML-Datei die URL des CGI-Scripts angegeben. Beispiel: <meta http-equiv="refresh" content="0; URL=/cgi-bin/welcome.pl">. Beispiel für die Wechselwirkung zwischen HTML und CGI Formulardaten übertragen mit GET oder POST HTML-Datei mit Formular und CGI-Aufruf: <hr> <h2><font color="#000099">PERL Beispiel - Methode GET/POST</h2></font> action ruft CGI-Script auf method=post: Script bekommt Daten von der Standardeingabe als Parameter <FORM ACTION="/cgi-bin/test.pl" METHOD="POST"> # <FORM ACTION="/cgi-bin/test.pl" METHOD="GET"> <pre> Name: E-Mail: Inhalt: # Text: <INPUT TYPE=“text“ NAME="name" VALUE="" <INPUT TYPE=“text“ NAME="email" VALUE="" <INPUT TYPE=“text“ NAME="inhalt" VALUE="" <textarea rows=5 cols=34></textarea> SIZE=60> SIZE=60> SIZE=80> </pre> <INPUT TYPE="Submit" Value="Abschicken"> <INPUT TYPE="Reset" Value="Eingaben löschen"> </form> Zwei HTTP-Befehle sind im Zusammenhang mit der Übertragung von Formulardaten von Bedeutung: GET Durch die Angabe von method=get im einleitenden <form>-Tag werden die ausgefüllten Formulardaten an die Server-Software übertragen und von dieser in der Umgebungsvariablen mit dem Namen QUERY_STRING zwischenspeichert. Der Formulardatenstrom wird, getrennt durch ein Fragezeichen, direkt hinter die URL-Adresse des CGI-Programm-aufrufs gehängt. Im WWW-Browser des Anwenders ist dies nach dem Absenden des Formulars in der URL-Zeile sichtbar. Die tatsächliche Übertragung an den Server erfolgt folglich mit: GET/cgi-bin/test.pl?name=mueller&[email protected]&inhalt=dfgfdgf ...HEADER HTTP/1.1 Ein CGI-Script, das durch die Angabe action= im einleitenden Formular-Tag aufgerufen wird, muß den Inhalt dieser Umgebungsvariablen auslesen, um an die Formulardaten heranzukommen (Perl: $form_daten = $ENV{'QUERY_STRING'};). POST Durch method=post im <form>-Tag werden die ausgefüllten Formulardaten direkt an die Adresse übertragen, die bei action= angegeben ist. POST /cgi-bin/test.pl? ...HEADER HTTP/1.1 Content-length: 15 name=mueller&[email protected]&inhalt=dfgfdg Ein CGI-Script, das bei action= aufgerufen wird, muß die Standardeingabe auslesen, um an die Formulardaten heranzukommen (Perl: read(STDIN, $Daten, $ENV{'CONTENT_LENGTH'});. 68617768 Seite 4 von 6 Entwicklung von Electronic Business Systemen FH Fulda – FB AI Dazu muß die Umgebungsvariable CONTENT_LENGTH ausgelesen werden, um zu ermitteln, wie viele Zeichen es von der Standardeingabe lesen soll. (übergebener Datenstrom enthält kein Datenendekennzeichen). Grundsätzlich muß ein CGI-Script die jeweilige Methode abfragen Datenstrom bei Übertragung von Formulardaten Ein typisches HTML-Formular besteht aus verschiedenen Feldern (z.B. für Name, E-MailAdresse und Kommentartext). Daraus ergibt sich das Problem, das das CGI-Script die Felder des Formulars und die vom Benutzer eingetragenen Daten erkennen. CGI benutzt eine bestimmte Kodierungsmethode (MIM Type urlencoded), die Formularfelder und Daten trennt. Diese Kodierungsmethode benutzt folgende Regeln: Formularelemente inklusive Daten werden durch & getrennt Name und Daten eines Formularelements werden durch = getrennt Leerzeichen in den eingegebenen Daten (z.B. bei mehreren Wörtern) werden durch ein Pluszeichen + ersetzt. Alle Zeichen mit den ASCII-Werten 128 bis 255 (hexadezimal 80 bis FF) werden durch die Hexadezimaldarstellung beschrieben, eingeleitet durch ein Prozentzeichen % (z.B. ö %F6) Zeichen, die in diesen Regeln als Steuerzeichen vorkommen (also &, +, = und %) werden ebenfalls hexadezimal beschrieben (wie höherwertige ASCII-Zeichen). Ein Beispiel CGI-Script in Perl (test.pl) mit einer HTML-Ausgabe kann folgendermaßen aussehen: #!/usr/bin/perl # Daten werden von der Standardeingabe eingelesen. read(STDIN, $Daten, $ENV{'CONTENT_LENGTH'}); print "Content-type: text/html\n\n"; print "<html><head><title>CGI-Antwort</title></head>\n"; print "<body><h1>CGI-Antwort vom Programm <i>test.pl</i></h1>\n"; # splittet eingelesene Daten nach Formularfeldern getrennt in einzelne Elemente auf @Formularfelder = split(/&/, $Daten); #Dekodierung: übergebene Daten, sind nach dem Mime-Type application/x-www#form-urlencoded kodiert (Leerzeichen, Satz- sowie Sonderzeichen werden durch #hexadezimale Umschreibungen dargestellt) foreach $Feld (@Formularfelder) { ($name, $value) = split(/=/, $Feld); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ s/<!--(.|\n)*-->//g; $Formular{$name} = $name; $Formular{$value} = $value; print "$Formular{$name} = $Formular{$value}", "<br>\n"; } print "</body></html>\n"; In anderen Sprachen (z. B. C) sind die selben Aktivitäten zu realisieren: #include <stdio.h> #include <stdlib.h> #include <string.h> void main(void) { char *http_user_agent; 68617768 Seite 5 von 6 FH Fulda – FB AI Entwicklung von Electronic Business Systemen printf („Content-type: text/plain\n\n“); http-user_agent = getenv („HTTP_USER_AGENT“); if (http_user_agent == NULL) printf („Keine Angaben über Browser!“); else if (!strncmp (http_user_agent, „Mozilla“, 7) // partielle Suche nach 7 Zeichen printf („ Sie verwenden Netscape Browser!“); else printf („Sie verwenden den %s-Browser“,http_user_agent); exit(0); } *** Ende CGI *** 68617768 Seite 6 von 6