Netzprogrammierung: Dynamische Web-Seiten Robert Tolksdorf und Peter Löhr Überblick 1. 2. 3. 4. Dynamische Web-Inhalte Common Gateway Interface - CGI Formular-Verarbeitung Servlets Robert Tolksdorf und Peter Löhr 3 5 27 33 2 Dynamische Web-Inhalte Robert Tolksdorf und Peter Löhr Statische und dynamische Inhalte • Statische Inhalte liegen vorgefertigt auf dem Server und werden unverändert ausgeliefert und dargestellt. • Dynamische Inhalte bewirken vor der Auslieferung und/oder bei der Darstellung Effekte auf Inhalt oder Darstellung durch Ausführung von Code • ... vor der Auslieferung beim Server: • • • • Vereinfachung der Inhaltserstellung Erzeugung/Konvertierung von Inhalt Anpassung/Personalisierung von Inhalt Ergebnis anderer Berechnungen • ... bei der Darstellung durch den Browser: • Erzeugung einer Darstellung • Anpassung einer Darstellung • Interaktion mit dem Benutzer Robert Tolksdorf und Peter Löhr 4 Common Gateway Interface - CGI http://www.w3.org/CGI/ http://hoohoo.ncsa.uiuc.edu/cgi/overview.html http://www.cgi101.com/ Robert Tolksdorf und Peter Löhr Dynamische Dokumenten-Erzeugung Merke: Dynamische Zusammenstellung eines auszuliefernden Dokuments durch den Server ist technisch trivial. Beispiel: Einflicken des aktuellen Datums in einen aus einer Datei entnommenen HMTL-Text. Aber: Für jede Ressource wird spezifischer Code benötigt! Daher: Die URL identifiziert nicht ein vorliegendes Dokument, sondern ein Programm, das ein Dokument erzeugt: CGI-Programm Robert Tolksdorf und Peter Löhr 6 Beispiel Beispiel: Ausgabe von Datum und Uhrzeit durch Perl-Programm date.pl #!/usr/bin/perl $date = localtime time; print "Content-type: text/html\n"; # Kopfzeile print "\n"; # Leerzeile print "<html><head>\n"; # HTML-Text ... print "<title>Datum</title>"; print "</head>\n"; print "<body>Heutiges Datum: $date</body>\n"; print "</html>\n"; Robert Tolksdorf und Peter Löhr 7 Voraussetzungen • Datei date.pl enthält ein ausführbares Programm. • Schutzstatus der Datei date.pl erlaubt die Ausführung. • Datei liegt in demjenigen Verzeichnis, das gemäß den Konfigurationsdaten des Servers für CGI-Programme vorgesehen ist. • Beispiel Apache mit Standard-Konfiguration: cgi-bin bezieht sich auf cgi-bin oder CGI-Executables im Apache-Verzeichnis. • Andere Konfigurationen sind möglich, vor allem für persönliche CGI-Programme von Benutzern; das Handbuch des jeweiligen Web Servers gibt Auskunft. • (Dateierweiterung ist nicht festgelegt; typisch ist .cgi .) Robert Tolksdorf und Peter Löhr 8 Funktionsweise CGI-Prozess HTTP-Anfrage Web Server CGI-Programm HTTP-Antwort Dokumente CGI-Programme Robert Tolksdorf und Peter Löhr 9 Fehlfunktion Ein Laufzeitfehler des CGI-Programms führt zur Fehlermeldung 500 Internal Server Error ..... die vom Browser geeignet angezeigt wird. Robert Tolksdorf und Peter Löhr 10 CGI und Perl Skript date.pl einfacher auch wie folgt: #!/usr/bin/perl $date = localtime time; print <<EOD Content-type: text/html <html><head> <title>Datum</title> </head> <body>Heutiges Datum: $date</body> </html> EOD CGI mit Perl: http://www.cs.tut.fi/~jkorpela/perl/cgi.html Robert Tolksdorf und Peter Löhr 11 Alternativen für Skript date.pl • Skript date.cgi als Alternative für date.pl: #!/bin/sh echo Content-type: text/html echo echo "<html><head>" echo "<title>Datum</title>" echo "</head><body>" echo Heutiges Datum: date echo "</body></html>“ • Programm date als Alternative - mit folgendem Quellcode: #include <time.h> main() { printf("Content-type: text/html\n\n"); printf("<html><head><title>Datum</title></head>"); printf("<body>Heutiges Datum: "); time_t now; time(&now); printf("%s", ctime(&now)); printf("</body></html>\n"); } Robert Tolksdorf und Peter Löhr 12 Eingabe für CGI-Programme ... Eingabe wird mit Trennzeichen ? an den URL angehängt, z.B. http://www.dot.com/cgi-bin/oracle?querystring und steht dem CGI-Programm in der Umgebungsvariablen QUERY_STRING als Zeichenkette zur Verfügung. Beispiel: Robert Tolksdorf und Peter Löhr 13 URL-Codierung der Eingabe Die auf ? folgende Eingabe wird für die Übertragung URL-codiert, damit bedeutungstragende Zeichen wie =, &, ... übertragen werden können: Leerzeichen -> + & -> %26 @ -> %40 etc. Beispiel: %&" "+#äß -> %25%26%22+%22%2B%23%E4%DF Medientyp der Nachricht ist application/x-www-form-urlencoded. Robert Tolksdorf und Peter Löhr 14 URL-Codierung in Java • java.net.URLEncoder: • public static String encode(String s, String enc) throws UnsupportedEncodingException • enc ist registrierte Zeichensatzbenennung wie “ISO-8859-1“ • java.net.URLDecoder: • public static String decode(String s, String enc) throws UnsupportedEncodingException Robert Tolksdorf und Peter Löhr 15 ... und hinter den Kulissen ... Eine von vielen Möglichkeiten für die Datei echo: #!/bin/sh cd /Users/lohr/fu/lehre/alp5/WS-08/code/cgi java Echo $QUERY_STRING mit import java.io.*; public class Echo { public static void main (String arg[]) throws IOException { String message = arg[0]; String answer = message.replace('i','o'); System.out.println("Content-type: text/html"); System.out.println(); System.out.println("<html>"); System.out.println("<head><title>Echo</title></head><body>"); System.out.println("<br><b>Ruf war: </b>" + message + "<br>"); System.out.println("<br><b>Echo ist: </b>“ + answer + "<br>"); System.out.println("</body></html>"); } } Robert Tolksdorf und Peter Löhr 16 ... passiert dies • Web Server erhält GET /cgi-bin/echo?igittigitt HTTP/1.1 Accept-Language: de-de Accept-Encoding: gzip, deflate ....... • ... und startet Prozess mit QUERY_STRING = igittigitt und CGI-Programm echo. • Problematisch: die Eingabe ist völlig unstrukturiert; der Server weiß nichts von eventuell mehreren in der Eingabe enthaltenen Parametern noch von deren Typen. Die Zeichenkette wird unbesehen an das CGI-Programm weitergegeben. Robert Tolksdorf und Peter Löhr 17 Umgebungsvariable des CGI • Die Schnittstelle CGI - Common Gateway Interface - zwischen Web Server und CGI-Programm wird durch einen festgelegten Satz von Umgebungsvariablen bestimmt. • Shell: $QUERY_STRING, $REQUEST_METHOD, ..... • Perl: die vordefinierte Variable $ENV ist die Tabelle aller Umgebungsvariablen mit ihren Werten. Beispiel: #!/usr/bin/perl print "Content-type: text/html\n"; # Kopfzeile print "\n"; # Leerzeile print "<html><head>"; # HTML-Text print "<title>Ich erkenne Sie</title>"; print "</head>"; print "<body>Sie benutzen diesen Browser:<br>"; print $ENV{"HTTP_USER_AGENT"}; print "</body></html>"; Robert Tolksdorf und Peter Löhr 18 Umgebungsvariable • SERVER_NAME • • • • • • • Der Name des Servers, wie er in der URL des CGI-Programms auftritt. SERVER_PORT Die Nummer des Ports, über den die Anfrage geschickt wurde. SERVER_PROTOCOL Das Protokoll, mit dem die Anfrage geschickt wurde, als Zeichenkette der Form Protokoll/Version. Z.B. HTTP/1.1 SERVER_SOFTWARE Server, der das CGI-Programm startet, als metaName/Version. Beispiel: NCSA/1.4.2. GATEWAY_INTERFACE Version der CGI-Spezifikation, der der Server folgt, als CGI/Version. Z.B.: CGI/1.1. REQUEST_METHOD Methode, die bei der Anfrage verwendet wurde: GET oder POST (s.u.) SCRIPT_URI Vollständiger URI des CGI-Programms SCRIPT_NAME Der Name des CGI-Programms in der URI, z.B. /cgi-bin/env.cgi Robert Tolksdorf und Peter Löhr 19 Umgebungsvariable • QUERY_STRING • • • • • • • • Die Eingabe/Anfrage an das CGI-Programm REMOTE_HOST Der Name des Rechners, von dem die Anfrage kam REMOTE_ADDR Die Internetadresse des Rechners, von dem die Anfrage kam REMOTE_USER Der Benutzername, für den das Passwort eingegeben wurde REMOTE_IDENT Benutzerkennung des anfordernden Benutzers, falls ermittelbar AUTH_TYPE Name des Verfahrens, mit dem das Passwort kodiert ist CONTENT_TYPE Bei Verwendung der POST-Methode steht hier der Medientyp des Inhalts, der an der Standardeingabe gelesen werden kann CONTENT_LENGTH Die Länge des Inhalts bei der POST-Methode HTTP_ACCEPT Die Medienarten, die der Browser akzeptieren will Robert Tolksdorf und Peter Löhr 20 Umgebungsvariable • Eventuell gibt es auch andere Variable, abhängig vom Server. • Ein kleines Skript env.cgi zur Ermittlung aller Variablen: #!/usr/bin/perl print "Content-type: text/plain\n\n"; foreach $var (sort keys %ENV) { $val = $ENV{$var}; print "$var = $val\n"; } Test: Robert Tolksdorf und Peter Löhr 21 Umgebungsvariable Robert Tolksdorf und Peter Löhr 22 CGI, Perl und HTML #!/usr/bin/perl use CGI; $cgi = new CGI; print $cgi->header(), $cgi->start_html('Echo'), $cgi->h3('Echo der Eingabe:'), $cgi->pre($ENV{'QUERY_STRING'}), $cgi->end_html(); (Hilfreich ist wiederum http://www.cs.tut.fi/~jkorpela/perl/cgi.html ) Robert Tolksdorf und Peter Löhr 23 Standardeingabe des CGI-Programms • Wird für die Anfrage die Methode POST statt GET verwendet, so wird der Inhalt der Anfrage nicht über QUERY_STRING, sondern über die Standardeingabe vermittelt. • Ein einfaches Perl-Skript echo.cgi, das sowohl mit GET als auch mit POST aufgerufen werden kann: #!/usr/bin/perl print "Content-type: text/plain\n"; # Kopfzeile print "\n"; # Leerzeile $method = $ENV{'REQUEST_METHOD'}; if ($method eq "GET") { $buffer = $ENV{'QUERY_STRING'}; } elsif ($method eq "POST") {read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'} print $buffer; Robert Tolksdorf und Peter Löhr 24 Standardausgabe des CGI-Programms • Ausgaben des CGI-Programms über StandardausgabeKanal werden als Antwort an den Klienten geschickt. • Notwendig: Content-Type-Kopfzeile • Möglich: Beliebige Medienarten, z.B. auch Bilder • Beispiel Postscript: (http://www.ntecs.de/old-hp/uu9r/lang/html/postscript.de.html) #!/usr/bin/perl print "Content-type: application/postscript\n\n"; print <<EOD %!PS-Adobe-4.0 /Courier findfont 20 scalefont setfont 50 700 moveto (Dies ist ein Postscript-Dokument.) show showpage EOD Robert Tolksdorf und Peter Löhr 25 CGI bei www.inf.fu-berlin.de • Ihre Homepage hat die URL • http://www.inf.fu-berlin.de/~<benutzer> Im Dateisystem bei • UNIX: /web/page.mi.fu-berlin.de/web-home/<benutzer> • Windows: \\web.mi.fu-berlin.de\page.mi.fu-berlin.de\<benutzer> • Darin gibt es zwei Verzeichnisse • …/<benutzer>/public_html • Ihr Webspace mit index.html als Startseite, von außen sichtbar • Skripte können nicht darin schreiben • …/<benutzer>/data-rw • von außen nicht sichtbar • Skripte können darin schreiben • Ein eigenes CGI-Programm, z.B. /web/page.mi.fu-berlin.de/ • web-home/lohr/public_html/cgi-bin/example.cgi mit URL http://www.inf.fu-berlin.de/~lohr/cgi-bin/example.cgi wird mit der Autorisierung des Eigners (hier lohr) ausgeführt! Details: https://www.mi.fu-berlin.de/w/Tec/UserPages Robert Tolksdorf und Peter Löhr 26 Formular-Verarbeitung http://www.w3.org/TR/html401/interact/forms.html http://www.w3schools.com/html/html_forms.asp Robert Tolksdorf und Peter Löhr Formular wird ausgefüllt Ein Web-Formular: (oder Eingabe-Taste) Robert Tolksdorf und Peter Löhr 28 Ergebnis des Formularverarbeitung Effekt: ein CGI-Programm wird gestartet: Der QUERY_STRING ist URL-codiert (siehe S. 14), d.h. mit Ersetzung gewisser Sonderzeichen durch andere: firstname=Adam+W.&lastname=Smith&age=23 &email=smith%40inf.fu-berlin.de&sex=Male Robert Tolksdorf und Peter Löhr 29 Das Formular in HTML Datei gothic.html: <!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en"> <HTML><TITLE>Welcome to the Gothic Club</TITLE> <h2>Welcome to the Gothic Club!</h2> Check your eligibility for membership:<br><br> <FORM action="http://localhost/cgi-bin/alp5/gothic.cgi" method="GET"> First name:<INPUT type="text" name="firstname" size=10> Last name:<INPUT type="text" name="lastname"><br> Age: <INPUT type="text" name="age" size=2><br> email: <INPUT type="text" name="email"><br> Sex: <INPUT type="radio" name="sex" value="Male"> male <INPUT type="radio" name="sex" value="Female"> female <br><br> <INPUT type="submit" value="Send"> <INPUT type="reset"> </FORM> </HTML> Übung: geeignetes gothic.cgi schreiben! (-> http://hoohoo.ncsa.uiuc.edu/cgi/forms.html http://www.cs.tut.fi/~jkorpela/perl/cgi.html ) Robert Tolksdorf und Peter Löhr 30 Formulare, Perl und HTML Echo einer Eingabe (vergleiche mit S. 23): #!/usr/bin/perl use CGI; $cgi = new CGI; print $cgi->header(), $cgi->start_html('Echo'), $cgi->h3('Echo der Eingabe:'), $cgi->pre($cgi->param('Eingabe')), $cgi->end_html(); Robert Tolksdorf und Peter Löhr 31 ... und mit POST statt GET Datei gothic.html: <!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en"> <HTML><TITLE>Welcome to the Gothic Club</TITLE> <h2>Welcome to the Gothic Club!</h2> Check your eligibility for membership:<br><br> <FORM action="http://localhost/cgi-bin/alp5/gothic.cgi" method="POST"> First name:<INPUT type="text" name="firstname" size=10> Last name:<INPUT type="text" name="lastname"><br> Age: <INPUT type="text" name="age" size=2><br> email: <INPUT type="text" name="email"><br> Sex: <INPUT type="radio" name="sex" value="Male"> male <INPUT type="radio" name="sex" value="Female"> female <br><br> <INPUT type="submit" value="Send"> <INPUT type="reset"> </FORM> </HTML> ... denn das CGI-Programm erhält die Daten über die Standardeingabe. Robert Tolksdorf und Peter Löhr 32 Java Servlets http://java.sun.com/javaee/5/docs/api/javax/servlet/package-summary.html Robert Tolksdorf und Peter Löhr Servlets • Servlets: • CGI-Programme können in Java geschrieben werden (s.S.12) • Wenn der Web Server selber auf einer JVM läuft - kann er dann nicht einfach eine „Java-CGI-Komponente“ in einem Thread ausführen anstatt einen schwergewichtigen Prozess zu erzeugen? • Ja - Java Servlets sind solche Komponenten. • Unterschiede zu CGI (und Applets): • Ein/Ausgabe läuft nicht über Umgebungsvariable bzw. Standard-Ein/Ausgabe, sondern über Java-Schnittstelle • Servlets als Komponente in JVM eines Servers geladen • (Applets als Komponente in JVM eines Browsers geladen) • Schnittstelle: • Erweitern der Klasse javax.servlet.http.HttpServlet • Überschreiben von doGet bzw. doPost Robert Tolksdorf und Peter Löhr 34 Beispiel Gothic Club Statt gothic.cgi wird folgende Klasse bereitgestellt: import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class GothicServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res ) throws ServletException, IOException { String sex = req.getParameter("sex"); String age = req.getParameter("age"); boolean eligible = sex=="Male" && age.compareTo("70")>0 || sex=="Female" && age.compareTo("75")>0; String firstname = req.getParameter("firstname"); ... Robert Tolksdorf und Peter Löhr 35 Beispiel Gothic Club ... res.setContentType("text/html"); PrintWriter out = res.getWriter(); out.println("<html>"); out.println("<head><title>Reply</title></head>"); out.println("<body>"); if (!eligible) { out.println("<br><i>Sorry</i>, "); out.println(firstname.split(" ")[0]); out.println(", you are not eligible."); } else ..... out.println("</body>"); out.println("</html>"); } } Robert Tolksdorf und Peter Löhr 36 Eingabe • Über das HttpServletRequest-Objekt kann man die angelieferten Daten komfortabler als mit einem CGIProgramm erfragen, z.B. • getRemoteHost() • getMethod() • getServletPath() GET oder POST oder ... • Query-String • getQueryString() • getParameter(String name) • getParameterValues(String name) evtl. null evtl. null evtl. null • Kopfzeilen • getHeaderNames() • getHeader(String name) Robert Tolksdorf und Peter Löhr evtl. null 37 Ausgabe • Über das HttpServletResponse-Objekt können Statuscode und Kopfzeilen komfortabel gesetzt werden, z.B. • setStatus(int sc) • setHeader(String name, String value) • setContentType(String ct) • ... oder fertige Antworten geschickt werden, z.B. • sendError(int sc) • Konfiguration von Servlets (z.B. Bindung eines ServletObjekts an ein URL): Siehe entsprechenden Webserver • Apache tomcat: http://tomcat.apache.org/ Robert Tolksdorf und Peter Löhr 38 Einschlägige Web Server • Achtung: nur Java-basierte Web Server verfügen über einen Container für Servlets! („Web/Servlet Container“) und unterstützen damit das Servlet-Konzept. • Unterstützung von Servlets: • Sun Java System Web Server http://www.sun.com/software/products/web_srvr/ • Apache Tomcat - http://tomcat.apache.org • JBoss - http://www.jboss.com (verschiedene Plattformen) • ..... • Keine Unterstützung von Servlets: • Apache HTTP Server - http://httpd.apache.org • AOLServer - http://aolserver.sourceforge.net • MS IIS - http://www.iis.net Robert Tolksdorf und Peter Löhr 39 Servlets versus CGI • Portabilität • CGI führt weitere Sprache ein, oft extra Bibliothek nötig. • Servlets sind Teil der Java-Welt und sind sauberer strukturiert. • Leistungspotential • CGI ist eine isolierte Ad-hoc-Lösung für beim Server generierte dynamische Inhalte. • Servlets haben Anschluss an die gesamte Java-Welt, einschließlich Sicherheitsarchitektur. • Effizienz • Für die Ausführung eines CGI-Programms wird jedes Mal ein neuer Prozess gestartet. (Ausnahme: FastCGI-Mechanismus). • Servlets bleiben in der JVM geladen. Robert Tolksdorf und Peter Löhr 40 Zusammenfassung • CGI • Dynamische Erzeugung von Inhalten durch CGI-Programme • Beliebige Sprache - verbreitet sind Skript-Sprachen • Skriptsprachen wie Perl u.a. vereinfachen die Erzeugung von HTML • Formularverarbeitung • Parameterübergabe vom Klienten an den CGI-Prozess über Umgebungsvariable (GET) oder Standardeingabe (POST) • Skriptsprachen wie Perl u.a. vereinfachen die Entnahme der Parameter aus dem query string. • Servlets • Rahmenwerk für „CGI-ähnliche Komponenten“ in Java • Threads anstelle schwergewichtiger Prozesse • Ein/Ausgabe über komfortable Schnittstellen Robert Tolksdorf und Peter Löhr 41 Literatur • Heiko Wöhr: Web-Technologien. dpunkt 2004. • CGI Specification: • http://www.w3.org/CGI • http://hoohoo.ncsa.uiuc.edu/cgi • http://www.cgi101.com • Formularverarbeitung: • • http://www.w3.org/TR/html401/interact/forms.html • http://www.w3schools.com/html/html_forms.asp Servlets: http://java.sun.com/ javaee/5/docs/api/javax/servlet/package-summary.html • ... und etliche Bücher zu speziellen Themen (CGI etc.) Robert Tolksdorf und Peter Löhr 42