Praktikumsversuch HTTP-Protokoll
Ziel
Sie erhalten in tiefes Verständnis für HTTP, indem Sie dieses nutzen und analysieren.
Übersicht
Sie experimentieren mit diesem Protokoll per Konsole und außerdem nutzen Sie Java. Sie sollen einen Client in Java schreiben, welcher eine bestimmte Webseite per HTTP-Request von einem Server holt und auf der Konsole unformatiert (als html-Code) anzeigt. Nutzen Sie Linux auf dem Praktikumsrechner falls Sie im HTW-Labor arbeiten. Zuhause können Sie ein beliebiges Betriebssystem mit Javaunterstützung nutzen. Sehen Sie sich die Folien zum HTTP-Protokoll und zu den Sockets an (Folien Sockets und Folien Anwendungsschicht).
HTTP ist ein Protokoll nach dem Request-Response-Prinzip. In klassischen Webservern genutzte Request-Methoden sind: OPTIONS, HEAD, GET, POST. Für REST-Webservices werden weiterhin PUT, DELETE, PATCH genutzt. Das Netzwerkprotokoll WebDAV nutzt weitere Methoden.
Folgende Headertypen werden verwendet (Auswahl an Attributen):
- allgemeine Header (Connection, Date, Transfer-Encoding, Upgrade, Warning)
- Request-Header (Accept, Accept-Charset, Accept-Encoding, Accept-Language, Authorization, Cookie, Host, If-Match, If-Modified-Since, Range, Referer, User-Agent)
- Entity-Header (Allow, Content-Encoding, Content-Length, Content-Location, Content-Range, Content-Type, Last-Modified)
- Response-Header (Accept-Ranges, Age, ETag, Location, Server, Set-Cookie, Vary, WWW-Authenticate)
Response Codes
Wichtige Response-Codes sind:
- Erfolg
- 200 OK
- 201 Created
- 202 Accepted
- Weiterleitung
- 300 Multiple Choices (Content Negotiation - mehrere Optionen, Auswahl soll Client treffen)
- 301 Moved Permanently
- 302 Found
- 304 Not Modified
- Client
- 400 Bad Request
- 401 Unauthorized
- 403 Forbidden
- 404 Not Found
- 405 Method Not Allowed
- 406 Not Acceptable (Content Negotiation - Bedingung nicht erfüllbar)
- 415 Unsupported Media Type (Daten des Client nicht unterstützt)
- Server
- 500 Internal Server Error
- 501 Not Implemented
Content Negotiation
Ein wesentlicher Bestandteil von HTTP ist die Inhaltsvereinbarung (Content-Negotiation). Diese kann Server-driven oder Agent-driven sein. Bei Agent-driven sendet der Server bei Mehrdeutigkeiten eine Liste mit möglichen Parametern und entsprechenden URLs. Der Agent wählt dann aus dieser Liste aus.
Server-Driven Content Negotiation
Der Server wählt die gewünschte Ressource, basierend auf den Accept-Headern der Clients. Wenn die Bedingung nicht erfüllt werden kann, wird Code 406 gesendet. Sendet der Client keinen Accept-Header, wird die Standard-Ressource gesendet.
Agent-Driven Content Negotiation
Diese Form wird manchmal bei einer REST-API eingesetzt. Beispiel:
GET /resource HTTP/1.1
HTTP/1.1 300 Multiple Choices
Content-Type: application/vnd.api+json
{
"available_formats": [
{"type": "application/json", "url": "/resource.json"},
{"type": "application/xml", "url": "/resource.xml"}
]
}
GET /resource.json HTTP/1.1
Beispiele:
Client:
Accept: Haupttyp/Untertyp, ... , ...; Qualitätsfaktor (q=0...1)
Accept: text/html, text/*; q=0.9
Accept-Encoding: gzip, compress
Accept-Charset: UTF-8
Accept-Language: de-DE, de, en, fr;q=0.2
Server:
Content-Type: text/html; charset=UTF-8
Content-Encoding: gzip, deflate
Allow: GET, HEAD, POST
Vary: Accept-Language, Accept-Encoding
WWW-Authenticate: Basic realm="IT1"
Server: Apache/2.4.58 (Ubuntu)
Connection: keep-alive
Keep-Alive: timeout=300, max=96
HTTP-Ping
Neben der Nutzung des ICMP-Protokolls für die Prüfung einer Verbindung, kann auch direkt die Verbindung zu einem Webserver getestet werden.
Das Komandozeilentool httping
kann z.B. hierfür verwendet werden. I.d.R. wird der Test mittels eines HEAD-Requests erfolgen.
Machen Sie sich mit diesem Tool vertraut (z.B. mittels man-Page) und testen Sie die Verbindung zu verschiedenen Webservern per HTTP und HTTPS.
HTTP mittels Telnet
Als Beispiel soll die Startseite einer Website aufgerufen werden. Das HTTP-Protokoll kann auch mittels einer Telnet-Verbindung manuell genutzt werden. Überlegen Sie sich die dazu erforderlichen Schritte und geben Sie diese in der Konsole ein. Beachten Sie, dass Sie für Telnet den Port des gewünschten Anwendungsprotokolls (HTTP) angeben. Nutzen Sie für die Ermittlung eines minimalen HTTP-GET-Request die RFC für HTTP/1.1 (RFC 2616, Abschnitt 5).
Prüfen Sie beim Erhalt der Antwort bei welchem Teil es sich um den HTTP-Response (Headerzeilen) und bei welcher Teil es sich um die eigentlichen Daten (Payload) handelt. Nehmen Sie zum Testen die Website: http://checkip.dyndns.org oder http://www.informatik.htw-dresden.de. Beachten Sie, dass das Verfahren mittels Telnet nur für die unverschlüsselte Übertragung (kein https) funktioniert. Je nach Timeouteinstellung des jeweiligen HTTP-Servers haben Sie nur begrenzt Zeit (ca. 10 - 300 s) für die Eingabe. Beachten Sie, dass Sie nach der letzen Zeile zweimal die Entertaste betätigen müssen und die notwendige Leerzeile zu erzeugen. Bestimmen Sie den Timeout des Servers. Bei einem korrekten Ablauf würden folgende Informationen dargestellt.
telnet
set crlf
open checkip.dyndns.org 80
Trying 216.146.38.70...
Connected to checkip.dyndns.com.
Escape character is '^]'.
GET / HTTP/1.1
Host: dyndns.org
HTTP/1.1 200 OK
Content-Type: text/html
Server: DynDNS-CheckIP/1.0
Connection: close
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 105
<html><head><title>Current IP Check</title></head><body>Current IP Address: 141.56.131.71</body></html>
...
Connection closed by foreign host.
Probieren Sie auch andere Request-Methoden aus (HEAD, OPTIONS).
HTTPS mittels OpenSSL
Um Websites zu testen, die ausschließlich HTTPS nutzen, ist ein Werkzeug mit TLS-Unterstützung
notwendig. Dabei ist zu beachten, dass Webserver i.d.R. den standardisierten Zeilenabschluss (CR+LF)
für Kommandos fordern. Im Praktikum nutzen wir OpenSSL, die Nutzung ist möglich mittels
des Aufrufs: openssl s_client -crlf -connect domain:port
Testen Sie diverse Websites, z. B. (www.heise.de). Versuchen Sie, die Startseite der HTW-Dresden
zu empfangen.
Nachfolgend ist ein Beispiel dargestellt:
openssl s_client -crlf -connect www.heise.de:https
GET / HTTP/1.1
Host: www.heise.de
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 30 Mar 2020 16:05:48 GMT
Content-Type: text/html; charset=UTF-8
Last-Modified: Mon, 30 Mar 2020 16:05:48 GMT
Cache-Control: public, max-age=30
Age: 20
Strict-Transport-Security: max-age=15768000
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Vary: Accept-Encoding,X-Export-Format,X-Export-Agent
Accept-Ranges: bytes
Content-Length: 513971
Connection: keep-alive
<!DOCTYPE html>
<html
...
HTTP/HTTPS-Client mittels Curl
Mittels des Konsolenprogramms Curl können Sie testen, ob ein Webserver HTTP/2.0 unterstützt:
curl --http2 -sI https://www.htw-dresden.de
Bei einer erfolgreichen Verbindung ist HTTP/2 200
zu sehen.
Mittels man curl
können Sie die Parameter in Erfahrung bringen.
Wichtige CURL-Optionen:
- -I nur Header übertragen
- -X HTTP-Methode
- -d Daten in POST-Request senden, z.B.:
"a=1&b=2"
(application/x-www-form-urlencoded) --data-urlencode
Daten (für GET-Request)- -b verwaltet Cookies für Anfragen
- -H benutzerdefinierter Header, z.B.:
"Content-Type: application/json" -d '{"a":"1","b":"2"}'
- -v detaillierte Informationen
- -L folgt Weiterleitungen
- -u Zugangsdaten übergeben (username:password), Standard ist Basic Authentification
- -O Datei speichern mit Originalnamen
- -T Datei übertragen
- -e Referer setzen
- -G Parameterübertragung mittels GET statt POST
- -F Formular (multipart/form-data)
Simuliere Browser:
curl -X GET \
-H "User-Agent: Chrome/63.0.1 Safari/534.3" \
-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8" \
-H "Accept-Language: de-DE,de,en-US,en;q=0.9" \
-H "Referer: https://www.example.com" \
-H "Connection: keep-alive" \
https://example.com/resource
Zum Experimentieren mit per HTTP übertragenen Formulardaten können Sie die URL https://www.informatik.htw-dresden.de/~jvogt/it1/formdemo/form.php nutzen, welche die GET- und POST-Variablen zurückgibt. Probieren Sie beide Varianten mit jeweils 2 Variablen aus!
Probieren Sie weitere Request-Methoden aus. Was können Sie mit curl noch alles anfangen?
HTTP/HTTPS mittels Java
Nachdem Sie das HTTP-Protokoll über Telnet genutzt haben, können Sie beginnen, das Protokoll in einem Java-Programm als HTTP-Client zu nutzen.
Als Editoren stehen z.B. vim, gedit, kate oder die Entwicklungsumgebungen Eclipse bzw. IntelliJ zur Verfügung. Ein Javaprogramm muss mit der Endung .java abgespeichert werden. Der Dateiname muss dabei identisch mit dem Klassennamen sein (inklusive Groß- und Kleinschreibung).
- Die Kompilierung erfolgt mittels: javac dateiname.java
- Es entsteht eine Ausgabedatei: dateiname.class
- Das Ausführen der Datei dateiname.class erfolgt über (Achtung ohne Endung .class) java dateiname
HTTP
Die Schritte im Programm gliedern sich wie folgt:
- TCP-Socket zum entsprechenden Server öffnen (es ist sinnvoll, die Serveradresse über die Kommandozeile zu übergeben)
- Einen HTTP-Request als String anlegen
- diesem String über das Socket senden
- die Antwort als String iterativ aus dem Socket auslesen und auf der Konsole ausgeben
- der Server wird nach einem Timeout die Verbindung schließen und das Clientprogramm wird sich beenden
Folgendes ist zu beachten:
- Parameter: Host Port Pfad sind über die Kommandozeile einzugeben
- Protokoll HTTP/1.1 nutzen
- Der Zeilenabschluss der Methode println entspricht u.U. nicht dem Standard und funktioniert damit nicht auf allen Servern z.B. (www.htw-dresden.de). Verwenden Sie den korrekten Zeilenabschluss lt. RFC 2616.
Sie können das nachfolgende Listing hierfür nutzen und müssen nur den Requeststring definieren. Ermitteln Sie vorab die Funktionsweise des Programms
import java.io.*;
import java.net.*;
import javax.net.ssl.*;
public class WGet_simple {
public static Socket clientSocket = null;
public static String targethost, targetfile;
public static int targetport;
public static String request, req1, req2, res, nl;
public static void main(String[] args) {
if (args.length < 3) {
System.out.println("Aufruf: java WGet_simple host port pfad");
System.exit(-1);
}
targethost = args[0]; // url-host
targetport = Integer.parseInt(args[1]); // url-port
targetpath = args[2]; // url-path
try {
// TCP-Socket (unverschlüsselt)
clientSocket = new Socket( targethost, targetport );
// alternativ TLS-Socket (verschlüsselt)
//SSLSocketFactory sslFact = (SSLSocketFactory) SSLSocketFactory.getDefault();
//clientSocket = (SSLSocket) sslFact.createSocket( targethost, targetport );
// Bietet formatierte Textausgabe u.a. println()
PrintWriter clientOut = new PrintWriter(new BufferedOutputStream( clientSocket.getOutputStream()) );
BufferedReader clientIn = new BufferedReader(new InputStreamReader( clientSocket.getInputStream() ));
//TODO
nl = ""; // new line definition for internet protocols
req1 = ""; // request line 1
req2 = ""; // request line 2
request = ""; // total request string to send over TCP-connection
System.out.println("HTTP-Request-Header:\n-------------------");
System.out.println(request + System.lineSeparator() );
// Sende Request + Leerzeile über TCP-Stream
clientOut.print( request );
clientOut.flush();
System.out.println("HTTP-Response-Header:\n-------------------");
while ( !(res = clientIn.readLine()).equals("") ) {
System.out.println( res );
}
System.out.println("\nHTTP-Daten:\n----------------");
while ((res = clientIn.readLine()) != null) {
System.out.println(res);
}
System.out.println("\n------\nVerbindung vom Server beendet");
clientSocket.close();
}
catch (IOException ex){ System.out.println(ex);}
}
}
Nutzen Sie das Programm, um mit einem POST-Request die Variablen “a=1&b=2” per Header: application/x-www-form-urlencoded an den o.g. Server zu versenden.
HTTPS
Normalerweise könnte man für die Nutzung von HTTP in Java spezielle Klassen verwenden, die
die Kommunikation deutlich vereinfachen, z. B. HttpUrlConnection
. Hier wollen wir aber nur
die grundlegende Funktionalität auf Socketebene testen. Da die meisten Websites mittlerweile
ausschließlich mittels SSL/TLS nutzbar sind, werden wir dieses direkt nutzen. Als Startpunkt
wählen wir das Listung für HTTP und wählen das TLS-Socket.
Optional
Literatur
Fakultativ
Letzte Änderung: 26. March 2025 19:33