Programmierung für das Internet

Werbung
5
Hypertext Transfer Protocol
(HTTP)
Aus der Definition von HTTP/1.1 (RFC 2616):
The Hypertext Transfer Protocol (HTTP) is an
application-level protocol for distributed, collaborative,
hypermedia information systems. It is a generic, stateless,
protocol which can be used for many tasks beyond its use
for hypertext, such as name servers and distributed object
management systems, through extension of its request
methods, error codes and headers. A feature of HTTP is the
typing and negotiation of data representation, allowing
systems to be built independently of the data being
transferred.
Vorläufige Version
236
c 2003 Peter Thiemann
Beispiel für HTTP Kommunikation
Aufbau der Verbindung zum WWW-Server
[hanauma] 107 > telnet localhost www
TCP/IP Verbindung zum Rechner localhost an den Port www (80)
Antwort von Telnet
Trying 127.0.0.1...
Connected to localhost.
Escape character is ’^]’.
Anfrage (Request) an den WWW-Server
1|GET / HTTP/1.1
2|Host: localhost
3|
Request besteht nur aus Kopf (Header), der Rumpf (Body) ist leer
Vorläufige Version
237
c 2003 Peter Thiemann
Kopf (Header) der Antwort
1|HTTP/1.1 200 OK
2|Date: Wed, 03 May 2000 19:41:20 GMT
3|Server: Apache/1.3.9 (Unix)
4|Last-Modified: Wed, 20 May 1998 14:59:42 GMT
5|ETag: "4405-656-3562efde"
6|Accept-Ranges: bytes
7|Content-Length: 1622
8|Content-Type: text/html
9|
Leerzeile signalisiert das Ende des Headers
Rumpf (Body) der Antwort in diesem Fall ein HTML-Dokument
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<TITLE>Test Page for Apache Installation on Web Site</TITLE>
</HEAD>
<!-- ... -->
</HTML>
Vorläufige Version
238
c 2003 Peter Thiemann
Nach kurzer Wartezeit beendet der Server die
Verbindung.
Connection closed by foreign host.
Alternativ: weitere Requests über die gleiche Verbindung
Vorläufige Version
239
c 2003 Peter Thiemann
Format einer Anfrage
hRequest i ::= hRequest-Line i
∗
hgeneral-header i | hrequest-header i | hentity-header i hCRLF i
hCRLF i
[hmessage-body i]
Jede Zeile wird durch hCRLF i,
CR (ASCII-Kode 13) gefolgt von
LF (ASCII-Kode 10), abgeschlossen.
Vgl. Methodenaufruf
• erste Zeile (hRequest-Line i):
Name der Methode und vorgeschriebene Parameter
• Headerzeilen: weitere (optionale) Parameter, durch Schlüsselworte identifiziert
• Rumpf: optionaler Inhalt der Anfrage (Parameter)
Vorläufige Version
240
c 2003 Peter Thiemann
Erste Zeile einer Anfrage
hRequest-Line i
hMethod i
::=
hMethod i hRequest-URI i hHTTP-Version ihCRLF i
::=
GET
*
Anfordern eines Dokuments
| HEAD
*
Anfordern der Header eines Dokuments
| POST
Senden einer Anfrage
| PUT
Ablegen eines Dokuments
| DELETE
Löschen eines Dokuments
| TRACE
Anfordern der empfangenen Anfrage
| OPTIONS
*
Vorläufige Version
erforderliche Methoden
241
c 2003 Peter Thiemann
Vorläufige Version
hRequest-URI i
::=
habs path i | habsoluteURI i | . . .
hHTTP-Version i
::=
HTTP/1.1
habs path i
::=
/ [hpath i] [;hparams i] [?hquery i]
hparams i
::=
...
hquery i
::=
...
242
c 2003 Peter Thiemann
Beispiel (Minimalanfrage)
1|GET / HTTP/1.1
2|Host: www.informatik.uni-freiburg.de
3|
Vorläufige Version
243
c 2003 Peter Thiemann
Format einer Header-Zeile
hheader i ::= hkey-token i:hvalue i
Beispiel
hHost i
Vorläufige Version
::= Host: hhost i [ : hport i ]
244
c 2003 Peter Thiemann
Anfragespezifische Header
hrequest-header i
::=
hAccept i
media types
| hAccept-Language i
| hHost i
*
Hostname des Servers
| hReferer i
URL
| hUser-Agent i
..
.
*
Vorläufige Version
in jeder direkten Anfrage erforderlich
245
c 2003 Peter Thiemann
Allgemeine Header
Können in Anfragen und Antworten benutzt werden, meist optional
hgeneral-header i
::=
hConnection i
| hDate i
| hTransfer-Encoding i
+
persistent/one-shot
+!
+
+
häufig in Antworten benutzt
+!
in jeder Antwort erforderlich
Entity Header
Information über den hmessage-body i, falls vorhanden:
Content -Encoding, -Language, -Length, -Location, . . .
Vorläufige Version
246
c 2003 Peter Thiemann
Format einer Antwort
hResponse i ::= hStatus-Line i
∗
hgeneral-header i | hresponse-header i | hentity-header i hCRLF i
hCRLF i
[hmessage-body i]
Beispiel
1|HTTP/1.1 200 OK
2|Date: Wed, 03 May 2000 19:41:20 GMT
3|Server: Apache/1.3.9 (Unix)
4|Last-Modified: Wed, 20 May 1998 14:59:42 GMT
5|ETag: "4405-656-3562efde"
6|Accept-Ranges: bytes
7|Content-Length: 1622
8|Content-Type: text/html
9|
Vorläufige Version
247
c 2003 Peter Thiemann
Statuszeile
hStatus-Line i
::=
hHTTP-Version i hStatus-Code i hReason-Phrase ihCRLF i
hHTTP-Version i
::=
HTTP/1.1
hStatus-Code i
::=
hdigit ihdigit ihdigit i
hReason-Phrase i
::=
Text ohne hCRLF i
Interpretation des Status-Code
1xx Informational – Request received, continuing process
2xx Success – The action was successfully received, understood, and accepted
3xx Redirection – Further action must be taken in order to complete the request
4xx Client Error – The request contains bad syntax or cannot be fulfilled
5xx Server Error – The server failed to fulfill an apparently valid request
• Siehe RFC 1700 für alle reservierten hStatus-Code is und hReason-Phrase is
• hReason-Phrase is sind nur Empfehlungen, können von Server und Client
ignoriert und/oder geändert werden
• Im Fehlerfall enthält hmessage-body i oft weitere Erklärung
Vorläufige Version
248
c 2003 Peter Thiemann
Inhalt der Nachricht
• beliebige Folge von Oktetts
• falls hContent-Type i nicht vorhanden
– Client darf aufgrund der URI raten
– falls erfolglos application/octetstream
• hContent-Encoding i: gzip, compress, deflate
beschreiben Kodierungseigenschaften des ursprünglichen Objekts
• hTransfer-Encoding i definiert Übertragungskodierung:
chunked, gzip, compress, deflate, identity
Vorläufige Version
249
c 2003 Peter Thiemann
Transfer-Encoding: identity and chunked
identity hContent-Length i Header definiert die Länge des hmessage-body i in
octets; hmessage-body i ist Folge von octets dieser Länge
(danach folgt unvermittelt die nächste Antwort bzw Verbindungsabbruch)
chunked wird verwendet, wenn die Länge nicht a-priori feststeht.
hmessage-body i wird in chunks übertragen (verkürzt):
Chunked-Body
= *chunk
last-chunk
CRLF
chunk
chunk-size
last-chunk
chunk-data
Vorläufige Version
= chunk-size CRLF
chunk-data CRLF
= 1*HEX
= 1*("0") CRLF
= chunk-size(OCTET)
250
c 2003 Peter Thiemann
6
Common Gateway Interface
(CGI)
CGI (Common Gateway Interface) Skripte erlauben die dynamische Erzeugung von
Dokumenten auf dem Server.
Typische Anwendung: CGI-Skripte verarbeiten Eingaben aus Formularen und
erzeugen in Abhängigkeit von den Eingaben ein Antwortdokument.
Eigenschaften von CGI:
Einfachheit
Sprachunabhängigkeit
Sicherheit durch separaten Prozess
Offener Standard
Architekturunabhängigkeit
Vorläufige Version
251
c 2003 Peter Thiemann
HTTP−Request
HTTP−Client
(Browser)
HTTP−Response
HTTP−Server
stdout
stdin, env
CGI
Prozeß
Vorläufige Version
252
c 2003 Peter Thiemann
Ausführung eines CGI-Skripts
• Server erkennt CGI-Skripte an der URL
– spezielles Element im Pfad (z.B. cgi-bin), dann nächstes Pfadelement
= Name eines ausführbaren Programms in konfigurierbarem Verzeichnis
– spezielle Extension am Dateinamen (z.B. .cgi)
= Name eines ausführbaren Programms
• Server verarbeitet den Header des HTTP-Requests
• Legt Request-Information in Environment ab (Prozessumgebung)
• Generiert die Statuszeile und einige Response-Header (Date, Server,
Connection)
• Schliesst den Headerteil der Response NICHT ab
• Startet das CGI-Programm mit
– Standardausgabe ⇔ Versenden an Client/Browser
– Standardeingabe ⇔ ggf. Lesen vom Client/Browser
– Argumente ⇔ Pfadelemente nach dem Namen des CGI-Programms
– Umgebung definiert weitere Parameter der Anfrage
Vorläufige Version
253
c 2003 Peter Thiemann
Pflichten eines CGI-Programms
• Interpretation der Parameter und der Anfrage
• Drucken weiterer Headerzeilen
(Content-Length, Content-Type, Content-Encoding, . . .)
• Abschliessen des Headerteils der Response durch Leerzeile
• Generieren des Inhaltes
Sprachen zur CGI-Programmierung
• Jede geeignet, die Standardeingabe und Umgebungsvariable lesen kann, sowie
Standardausgabe schreiben kann
• Für Java ist ein wrapper Programm zum Lesen der Umgebungsvariablen
erforderlich
• Manche Webserver beinhalten Interpreter für Skriptsprachen (perl, php, etc),
um die Startzeit für einen externen Interpreter zu sparen
Beispiel: Apache Module mod perl, mod php, mod python, mod ruby, . . .
Vorläufige Version
254
c 2003 Peter Thiemann
6.1
Parameter für ein CGI-Programm
Die Einsendung eines XHTML Formulars liefert
Feldname1 =Wert1
Feldname2 =Wert2
...
Feldnamek =Wertk
wobei Feldnamen wiederholt auftreten können.
Feldnamen und Werte werden vor Übertragung vom Browser kodiert
Standardkodierung: URL Kodierung application/x-www-form-urlencoded
• Buchstaben und Zahlen bleiben erhalten
• Leerzeichen werden durch + ersetzt
• Alle weiteren Zeichen werden durch %hASCII-code i ersetzt
(in zweistelliger Hexadezimaldarstellung)
vgl.
public static String java.net.URLEncoder.encode(String s)
Vorläufige Version
255
c 2003 Peter Thiemann
6.2
Zugriffsmethoden
GET Kodierung der Anfrage in der URL durch Anhängen eines hQuerystring i der
Form ?hFeld-Wert-Liste i an die action URL
hFeld-Wert-Liste i
::=
hkodierter-Feldname i=hkodierter-Wert i
∗
&hkodierter-Feldname i=hkodierter-Wert i
Der Webserver legt den hQuerystring i in der Umgebungsvariable
QUERY STRING ab.
POST verschickt die hFeld-Wert-Liste i im hmessage-body i der Anfrage. Der
Webserver speichert die Länge (in Octets) des hmessage-body i in der
Umgebungsvariable CONTENT LENGTH. Das CGI-Programm muss genau so
viele Octets lesen und interpretieren (nicht bis Dateiende lesen!)
Durch URL Kodierung werden
• unerlaubte Zeichen in URLs vermieden
• die Zeichen = und & in Feldnamen und Werten verwendbar
Rationale für Methoden: GET beobachtet, POST ändert ggf. Zustand des Servers
Vorläufige Version
256
c 2003 Peter Thiemann
Ein Shellskript als CGI-Skript: date
Abspeichern als date.cgi oder als /cgi-bin/date.
#!/bin/sh
echo Content-type: text/html
echo
cat <<EOF
<HTML><head><title>Date and Time</title></head>
<body> <h1>Date and Time</h1>
EOF
/bin/date
cat <<EOF
<p>
<a href="/index.html">Back home</a>
</body></html>
EOF
Vorläufige Version
257
c 2003 Peter Thiemann
Dito in Haskell
import Time
main = do
putStrLn "Content-Type: text/html"
putStrLn ""
putStrLn "<HTML><head><title>Date and Time</title></head>\
\<body> <h1>Date and Time</h1>"
clkt <- getClockTime
calt <- toCalendarTime clkt
putStrLn (calendarTimeToString calt)
putStrLn "<p>\
\<a href=\"/index.html\">Back home</a>\
\</body></html>"
Vorläufige Version
258
c 2003 Peter Thiemann
Dito in WASH
import CGI
import Time
main = do
clkt <- getClockTime
calt <- toCalendarTime clkt
let str = calendarTimeToString calt
run $ standardQuery "Date and Time" $ do
text str
<p><a href="/index.html">Back home</a></p>
Vorläufige Version
259
c 2003 Peter Thiemann
RawCGI
• Teil von WASH
• Nur Dekodierung der Parameter
type CGIProgram = CGIInfo -> CGIParameters -> IO ()
-- |low level info
type CGIInfo = ...
-- |decoded parameters
type CGIParameters = [(String, String)]
-- |low level options, empty list is usually ok
type CGIOptions = [...]
-- |run a CGI program
start :: CGIOptions -> CGIProgram -> IO ()
Vorläufige Version
260
c 2003 Peter Thiemann
Simple Use of RawCGI
import RawCGI
main = start [] mycgi
-- |display all form parameters
mycgi info params = do
putStrLn "Content-Type: text/plain"
putStrLn ""
putStrLn "My parameters are:"
mapM_ oneBinding params
oneBinding (name, value) = do
putStr name
putStr " = "
putStrLn value
Vorläufige Version
261
c 2003 Peter Thiemann
6.3
Umgebungsvariablen im CGI-Skript:
test-cgi
#!/bin/sh
# disable filename globbing
set -f
echo Content-type: text/plain
echo
echo CGI/1.0 test script report:
echo
echo argc is $#. argv is "$*".
echo
echo SERVER_SOFTWARE = $SERVER_SOFTWARE
echo SERVER_NAME = $SERVER_NAME
echo GATEWAY_INTERFACE = $GATEWAY_INTERFACE
echo SERVER_PROTOCOL = $SERVER_PROTOCOL
echo SERVER_PORT = $SERVER_PORT
echo REQUEST_METHOD = $REQUEST_METHOD
echo HTTP_ACCEPT = "$HTTP_ACCEPT"
echo PATH_INFO = "$PATH_INFO"
Vorläufige Version
262
c 2003 Peter Thiemann
echo
echo
echo
echo
echo
echo
echo
echo
echo
PATH_TRANSLATED = "$PATH_TRANSLATED"
SCRIPT_NAME = "$SCRIPT_NAME"
QUERY_STRING = "$QUERY_STRING"
REMOTE_HOST = $REMOTE_HOST
REMOTE_ADDR = $REMOTE_ADDR
REMOTE_USER = $REMOTE_USER
AUTH_TYPE = $AUTH_TYPE
CONTENT_TYPE = $CONTENT_TYPE
CONTENT_LENGTH = $CONTENT_LENGTH
Aufrufendes Formular
<form action="/cgi-bin/test-cgi/extra/parameters" method="get">
<input type="text" name="text=1" value="value for text=1">
<input type="text" name="text=2" value="nothing really+&!">
<input type="submit">
</form>
Vorläufige Version
263
c 2003 Peter Thiemann
Ausgabe von test-cgi
CGI/1.0 test script report:
argc is 0. argv is .
SERVER_SOFTWARE = Apache/1.3.9 (Unix)
SERVER_NAME = hanauma.informatik.uni-freiburg.de
GATEWAY_INTERFACE = CGI/1.1
SERVER_PROTOCOL = HTTP/1.0
SERVER_PORT = 80
REQUEST_METHOD = GET
HTTP_ACCEPT = image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
PATH_INFO = extra/parameters
PATH_TRANSLATED = /usr/local/www/data/extra/parameters
SCRIPT_NAME = /cgi-bin/test-cgi
QUERY_STRING = text%3D1=value+for+text%3D1&text%3D2=nothing+really%2B%26%21
REMOTE_HOST =
REMOTE_ADDR = 127.0.0.1
REMOTE_USER =
AUTH_TYPE =
CONTENT_TYPE =
CONTENT_LENGTH =
Vorläufige Version
264
c 2003 Peter Thiemann
6.4
File Upload
Wert eines Eingabefeldes ist Inhalt einer Datei
Probleme:
• Dateigröße macht Anhängen an URL unmöglich
• Dateiinhalt überwiegend nicht-ASCII: URL Kodierung expandiert die Größe
um Faktor 3
• Übertragung von Metadaten, wie Dateiname, content type, etc
Lösung: Verwendung von (Attributen von <form>)
• method="POST"
• enctype="multipart/form-data" (neuer MIME-Typ RFC 1521)
Vorläufige Version
265
c 2003 Peter Thiemann
Beispiel
<FORM ENCTYPE="multipart/form-data" ACTION="/cgi-bin/test-cgi" METHOD=POST>
File to process: <INPUT NAME="userfile1" TYPE="file">
<INPUT TYPE="submit" VALUE="Send File">
</FORM>
Verschickt Anfrage mit Header
Content-type: multipart/form-data; boundary=hboundary-string i
hboundary-string i soll nicht in den Felddaten vorkommen
Der hmessage-body i wiederholt
--hboundary-string i
Content-Disposition: form-data; name="hFeldname i"[; filename="hDateiname i"]
Content-Type: hcontent type i
hInhalt des Feldes i
und endet mit
--hboundary-string i-Vorläufige Version
266
c 2003 Peter Thiemann
Mehrere Selektionen in einem Feld (Feld Header)
hboundary-string i
Content-Disposition: form-data; name="hFeldname i"
Content-Type: multipart/mixed; boundary=hinterner boundary-string i
hInhalt i
Inhalt eines multipart/mixed Feldes
• Wiederholung von
--hinterner boundary-string i
Content-disposition: attachment; filename="file1.txt"
Content-Type: hcontent-type i
h... Inhalt von file1.txt ... i
• Beenden mit
--hinterner boundary-string i--
Vorläufige Version
267
c 2003 Peter Thiemann
Kodierung von Nicht-ASCII Zeichen (RFC 1522) in Feldnamen
hencoded-word i
::=
=?hcharset i?hencoding i?hencoded-text i?=
hcharset i
::=
ISO-8859-1 | . . .
hencoding i
::=
B|Q
• Falls hencoding i = B, so ist hencoded-text i mit base64 (RFC 1521)
kodiert.
• Falls hencoding i = Q, so ist hencoded-text i mit quoted-printable
(RFC 1521) kodiert.
Vorläufige Version
268
c 2003 Peter Thiemann
Herunterladen