16.4 Das Common Gateway Interface
 
CGI (Common Gateway Interface) ist eine Beschreibung einer Schnittstelle http://cgi-spec.golux.com/, mit der externe Programme mit Informationsservern, meistens Webservern, Daten austauschen. Die aktuelle Version ist CGI/1.1. Diese ausgeführten Programme werden kurz CGI-Programme genannt und können in allen erdenklichen Programmiersprachen verfasst sein. Häufig sind es Shell-/Python- oder Perl-Skripte (oft wird dann die Bezeichnung CGI-Skripte verwendet). Die Unterscheidung zwischen Skript und Programm ist bei CGI schwammig. Traditionell ist eine kompilierte Quelldatei ein Programm, und Programme, die mit einem Interpreter arbeiten, ein Skript. Wir werden im Folgenden allerdings »Programm« und »Skript« synonym verwenden. Für uns ist es erst einmal egal, ob ein Programm oder ein Skript ausgeführt wird. Denn wir wollen diese Programme aus Java nutzen und nicht selber schreiben. Auf der Serverseite ergänzen und verdrängen Java Server Pages beziehungsweise Servlets immer stärker CGI-Programme.
Die CGI-Programme werden von einem Browser durch eine ganz normale URL angesprochen. Der Browser baut eine Verbindung zum Server auf und dieser erkennt anhand des Pfads oder anderer Kriterien (Dateiendung oder spezielle Dateiflags), ob es sich um eine ganz normale Webseite handelt oder um ein Skript. Wenn es ein Skript ist, dann führt der Server das Skript aus, welches eine HTML-Datei erzeugt. Diese wird übertragen und im Browser dargestellt. Der Aufrufer einer URL merkt keinen Unterschied (außer vielleicht in der Performance) zwischen erstellten, also dynamischen, und statischen Seiten. Die CGI-Programme sind also immer eine Angelegenheit des Servers, der uns mit aktuellen Daten versorgt.
16.4.1 Parameter für ein CGI-Programm
 
Beim Aufruf eines CGI-Programms können Parameter übergeben werden, bei einer Suchmaschine etwa der Suchbegriff. Es gibt nun zwei Möglichkeiten, wie diese Parameter zum Skript kommen und somit vom Webserver verarbeitet werden.
|
Die Parameter (auch Query-Strings genannt) werden an die URL angehängt (GET-Methode). Das Skript liest die Daten aus der CGI-Umgebungsvariablen QUERY_STRING aus. |
|
Die Daten werden zur Standardeingabe des Webservers gesendet (POST-Methode). Das Skript muss dann aus dieser Eingabe lesen. |
GET und POST unterscheiden sich auch in der Länge der übertragenen Daten. Bei vielen Systemen ist die Länge einer GET-Anfrage beschränkt auf 1024 Byte. POST-Anfragen sind längenunbegrenzt.
Daten werden nach der GET-Methode verschickt
Die Daten sind mit dem CGI-Programmnamen verbunden und gehen beide zusammen auf die Reise. Der Anfrage-String (Query-String) wird hinter ein Fragezeichen gesetzt, das Et-Zeichen »&« trennt mehrere Anfragezeichenketten. Unter Java setzen wir einfach einen Befehl ab, indem wir ein neues URL-Objekt erzeugen und anschließend den Inhalt auslesen:
meineURL = new URL( "http", "...", "cgi-bin/trallala?tri" );
Das CGI-Skript holt sich seinerseits die Daten aus der Umgebungsvariablen QUERY_STRING. Das folgende Kapitel zeigt, wie diese Abfragezeichenketten komfortabel durch die Klasse URLEncoder zusammengebaut werden. Werfen wir jedoch erst einen Blick auf die Variablen.
Daten holen mit der POST-Methode
Die Klasse URLConnection bietet die schon bekannte Methode getOutputStream() an, die eine Verbindung zur Eingabe des CGI-Scripts möglich macht (POST-Methode):
// CGI-Script schickt die Daten zurück
PrintStream o = new PrintStream( cgiConnection.getOutputStream() );
o.println( data );
o.close();
16.4.2 Kodieren der Parameter für CGI-Programme
 
Wenn aus einer HTML-Datei mit Formularen über Submit Daten an das CGI-Programm übermittelt werden, dann werden diese Daten kodiert. Dies liegt daran, dass viele Zeichen in URL nicht erlaubt sind. Betrachten wir daher folgenden Ausschnitt aus einer Webseite:
<form method="get" action="/cgi-bin/caller.cgi">
<p>Name:
<input type="text" name="name" value="">
<p>E-Mail:
<input type="text" name="email" value="">
<p>
<input type="submit" name="submit" >
</form>
Die Seite besitzt zwei Felder mit den Namen name und email. Dazu kommt noch ein Submit-Button, der, falls aktiviert, die Daten an das CGI-Programm caller.cgi weitergibt. Wenn wir die Felder mit irgendeinem Inhalt füllen und Submit drücken, sehen wir URL häufig in der Adressleiste des Browsers. Dort erscheint, ohne Zeilenumbruch, zum Beispiel:
http://oho.de/cgi-bin/caller.cgi?
name=Ulli+Ullenboom&email=ulliull@ulli.com&submit=Submit
Da in einer URL keine Leerzeichen erlaubt sind, werden sie durch Pluszeichen kodiert. Es gibt noch weitere Zeichen, die kodiert werden, so das Plus- oder das Gleichheitszeichen oder auch das Und-Symbol. Von diesen Zeichen wird die Hex-Repräsentation als ASCII übersandt, aus »Ulli + Radhia« wird dann »Ulli+%2B+Radhia«. Aus dem Leerzeichen wird ein Plus und aus dem Plus wird %2B.
Neben der Textkodierung fällt noch auf, dass in der übermittelten Zeile jeder Feldname und das Feld mit seinem Feldinhalt übermittelt wird. Somit lässt sich leicht der Inhalt eines Felds heraussuchen, denn nach dem Feldnamen ist ein Gleichheitszeichen eingefügt. Das Ende der Inhalte ist durch ein Und-Zeichen gekennzeichnet.
Wollten wir einen String dieser Art zu einer URL zusammenbauen, um etwa eine Anfrage an ein Suchprogramm zu formulieren, dann müssen wir den String nicht kodieren. Dies übernimmt die Java-Klasse URLEncoder.
Listing 16.6
URLEncodeTest.java
import java.io.*;
import java.net.*;
public class URLEncoderDemo
{
public static void main( String args[] )
{
PrintStream o = System.out;
o.println(URLEncoder.encode("String mit Leerezeichen"));
o.println(URLEncoder.encode("String%mit%Prozenten"));
o.println(URLEncoder.encode("String*mit*Sternen"));
o.println(URLEncoder.encode("String+hat+ein+Plus"));
o.println(URLEncoder.encode("String/mit/Slashes"));
o.println(URLEncoder.encode("String\"mit\"Gänsen"));
o.println(URLEncoder.encode("String:Doppelpunkten"));
o.println(URLEncoder.encode("String=ist=alles=gleich"));
o.println(URLEncoder.encode("String&String&String"));
o.println(URLEncoder.encode("String.mit.Punkten"));
}
}
Wir bekommen folgende Ausgabe:
String+mit+Leerezeichen
String%25mit%25Prozenten
String*mit*Sternen
String%2Bhat%2Bein%2BPlus
String%2Fmit%2FSlashes
String%22mit%22G%E4nsen
String%3ADoppelpunkten
String%3Dist%3Dalles%3Dgleich
String%26String%26String
String.mit.Punkten
16.4.3 Eine Suchmaschine ansprechen
 
Wir wollen nun direkt eine Suchmaschine ansprechen und so das Verhalten eines Anfrageprogramms nachbilden. Unser Programm sammelt dazu alle Suchbegriffe als Parameter auf der Kommandozeile, falls keine Parameter vorhanden sind, wird nach »Teletubbies on Tour« gesucht. Anschließend kodiert die Klasse URLEncoder den Such-String und der Inhalt wird hinter die URL des CGI-Programms gehängt, noch getrennt durch ein Fragezeichen. Dieses wird als Anfrage für die Suchmaschine Google verpackt und weggeschickt. Anschließend wird in einer Schleife die HTML-Datei zeilenweise ausgegeben.
Listing 16.7
GoogleSeeker.java
import java.io.*;
import java.net.*;
public class GoogleSeeker
{
public static void main( String args[] ) throws Exception
{
String s = "";
if ( args.length == 0 )
s = "Teletubbies On Tour";
else
for ( int i = 0; i < args.length; i++ )
s += args[i] + " ";
s.trim();
s = "q=" + URLEncoder.encode( s );
URL u = new URL( "http://www.google.com/search?" + s );
BufferedReader in = new BufferedReader(
new InputStreamReader( u.openStream() ) );
String line, response = null;
while ( (line = in.readLine()) != null )
response += line+"\n";
System.out.print( response );
}
}
|