HttpUtils
HttpUtils | |
---|---|
Zweck / Funktion | |
Hilfsfunktionen für HTTP-Zugriffe | |
Allgemein | |
Typ | Hilfsmodul |
Details | |
Dokumentation | EN / DE |
Support (Forum) | Automatisierung |
Modulname | HttpUtils.pm |
Ersteller | rudolfkoenig (Forum / Wiki) |
Wichtig: sofern vorhanden, gilt im Zweifel immer die (englische) Beschreibung in der commandref! |
Das Modul HttpUtils(.pm) ist sowohl für Modulentwickler, als auch Endanwender gedacht um Daten via HTTP auszutauschen. Es stellt dabei eine Reihe von Funktionen zur Verfügung und wird beispielsweise vom Modul HTTPMOD intensiv genutzt.
Funktionen
Es ist zu beachten, dass bei den Funktionen
- GetHttpFile
- GetFileFromURL
- GetFileFromURLQuiet
- HttpUtils_BlockingGet
ein sogenannter "blockierender" Aufruf durchgeführt wird. Das bedeutet, dass FHEM bei einem Aufruf einer dieser Funktionen solange wartet und dabei absolut nichts macht, bis die Antwort vom HTTP-Server eintrifft und die Funktion damit beendet ist. Das kann bei Verbindungsproblemen evtl. dazu führen, dass FHEM für die gesamte Wartezeit (Timeout) steht und nichts verarbeitet. Problematisch ist das gerade bei Anwendungen oder Hardware, die eine zeitnahe Reaktion von FHEM erwarten (z.B. HomeMatic-Geräte).
Es wird daher empfohlen, die Funktionen so sparsam wie möglich zu verwenden und die Timeouts so niedrig wie möglich zu halten, um ein längeres Einfrieren von FHEM möglichst zu vermeiden.
Alternativ kann die Funktion
HttpUtils_NonblockingGet
verwendet werden, welche ein Blockieren von FHEM verhindert. Wie das genau funktioniert, wird in dem entsprechenden Kapitel beschrieben.
Die im Folgenden beschriebenen Funktionen sind für Modulentwickler/Endanwender zur direkten Nutzung gedacht.
GetHttpFile
Die Funktion GetHttpFile ist die denkbar einfachste Variante um eine URL aufzurufen.
GetHttpFile($server, $file)
Parameter | Bedeutung |
---|---|
$server
mandatory |
Der DNS-Name oder die IP-Adresse des HTTP-Servers Beispiel:
|
$file
mandatory |
Die Datei, welche auf dem HTTP-Server aufgerufen werden soll. Beispiel:
|
Funktionsergebnis ist der Inhalt der aufgerufenen Seite in Form einer Zeichenkette.
GetFileFromURL
Die Funktion GetFileFromURL ruft die HTTP-URL auf und gibt als Funktionsergebnis den Seiteninhalt zurück. Im Gegensatz zu GetHttpFile beinhaltet GetFileFromURL einige Zusatzoptionen in Form von Funktionsparametern.
Aufruf: GetFileFromURL($url, [$timeout], [$data], [$noshutdown], [$loglevel])
Parameter | Bedeutung |
---|---|
$url
mandatory |
Die HTTP-URL, welche aufgerufen werden soll. Diese kann optional Usernamen, Passwort und einen Port enthalten. Sowohl HTTP als auch HTTPS wird hierbei unterstützt. Beispiel:
|
$timeout
optional |
Die maximale Dauer in Sekunden für die HTTP-Anfrage
Standardwert: 4 Sekunden |
$data
optional |
Wenn man Daten via HTTP-POST übertragen möchte, so kann man die Nutzdaten über $data übergeben. Die Daten werden dabei als Formulardaten übertragen. Wenn man den Content-Type beeinflussen oder mehrere Formular-Felder senden möchte, sollte man zur Funktion HttpUtils_BlockingGet oder HttpUtils_NonblockingGet greifen.
|
$noshutdown
optional |
Wenn $noshutdown auf 1 gesetzt ist, wird dem HTTP-Server nicht implizit mitgeteilt, dass die Verbindung nach dem Request geschlossen werden soll. Viele Webserver schließen in solch einem Fall die Verbindung bevor sie die Antwort senden. Bei 0 wird dem Webserver mitgeteilt, dass der Sendevorgang beendet ist und nun die Antwort abgewartet wird.
|
$loglevel
optional |
Das Logleve, in dem sämtliche Logmeldungen zu dieser HTTP-Abfrage erzeugt werden sollen.
|
Funktionsergebnis ist der Inhalt der aufgerufenen Seite in Form eines Strings.
GetFileFromURLQuiet
Diese Funktion funktioniert ähnlich wie GetFileFromURL. Allerdings wird die tatsächliche URL in allen erzeugten Log-Meldungen unkenntlich gemacht um z.B. Zugangsdaten nicht preiszugeben. Die aufgerufene Seite wird ebenfalls als Funktionsergebnis zurückgegeben.
Aufruf: GetFileFromURLQuiet($url, [$timeout], [$data], [$noshutdown], [$loglevel])
Parameter | Bedeutung |
---|---|
$url
mandatory |
Die HTTP-URL, welche aufgerufen werden soll. Diese kann optional Usernamen, Passwort und einen Port enthalten. Sowohl HTTP als auch HTTPS wird hierbei unterstützt. Beispiel:
|
$timeout
optional |
Die maximale Dauer in Sekunden für die HTTP-Anfrage
Standardwert: 4 Sekunden |
$data
optional |
Wenn man Daten via HTTP-POST übertragen möchte, so kann man die Nutzdaten über $data übergeben. Die Daten werden dabei als Formulardaten übertragen. Wenn man den Content-Type beeinflussen möchte, oder mehrere Formular-Felder senden möchte, sollte man zur Funktion HttpUtils_BlockingGet oder HttpUtils_NonblockingGet greifen.
|
$noshutdown
optional |
Wenn $noshutdown auf 1 gesetzt ist, wird dem HTTP-Server nicht implizit mitgeteilt, dass die Verbindung nach dem Request geschlossen werden soll. Viele Webserver schließen in solch einem Fall die Verbindung bevor sie die Antwort senden. Bei 0 wird dem Webserver mitgeteilt, dass der Sendevorgang beendet ist und nun die Antwort abgewartet wird.
|
$loglevel
optional |
Das Loglevel, in dem sämtliche Logmeldungen zu dieser HTTP-Abfrage erzeugt werden sollen.
|
Funktionsergebnis ist der Inhalt der aufgerufenen Seite in Form eines Strings.
HttpUtils_BlockingGet
Wenn die bisher genannten Funktionen nicht ausreichen um die gewünschte Abfrage durchzuführen, so kann man diese Funktion verwenden. Aufgrund zahlreicher Parameter ermöglicht sie viele Anpassungsmöglichkeiten. Diese Funktion hat dabei nicht wie üblich eine Liste an Funktionsparametern, sondern lediglich einen Parameter, welcher eine Hashreferenz mit allen Funktionsparametern darstellt. Dieser Hash enthält sämtliche Parameter inkl. Werten.
Aufruf: HttpUtils_BlockingGet($param)
Der Parameter $param ist eine Referenz auf eine Hash-Struktur, welche die einzelnen Parameter enthält. Der Hash $param kann folgende Optionen beinhalten:
Parameter | Bedeutung |
---|---|
$param->{url}
mandatory |
Die HTTP-URL, welche aufgerufen werden soll. Diese kann optional Usernamen, Passwort und einen Port enthalten. Sowohl HTTP als auch HTTPS wird hierbei unterstützt. Beispiel:
|
$param->{timeout}
optional |
Die maximale Dauer in Sekunden für die HTTP-Anfrage
Standardwert: 4 Sekunden |
$param->{data}
optional |
Wenn man Daten via HTTP-POST übertragen möchte, so kann man die Nutzdaten über $param->{data} übergeben. Die Daten werden dabei als Formulardaten übertragen. Die Daten können dabei auf zwei Arten übergeben werden:
1. Daten als String:
2. Daten als Hash:
|
$param->{noshutdown}
optional |
Wenn $param->{noshutdown} auf 1 gesetzt ist, wird dem HTTP-Server nicht implizit mitgeteilt, dass die Verbindung nach dem Request geschlossen werden soll. Viele Webserver schließen in solch einem Fall die Verbindung bevor sie die Antwort senden. Bei 0 wird dem Webserver mitgeteilt, dass der Sendevorgang beendet ist und nun die Antwort abgewartet wird.
|
$param->{loglevel}
optional |
Das Loglevel, in dem sämtliche Logmeldungen zu dieser HTTP-Abfrage erzeugt werden sollen.
|
$param->{hideurl}
optional |
Wenn dieser Parameter den Wert 1 trägt, wird die URL in sämtlichen Log-Ausgaben unkenntlich gemacht. Dies ist nützlich um z.B. Zugangsdaten geheim zu halten.
|
$param->{ignoreredirects}
optional |
Wenn dieser Parameter den Wert 1 trägt, werden Umleitungen durch den Server ignoriert und der Request beendet. Dies kann erforderlich sein um evtl. Cookies aus der Antwort, welche eine Umleitung enthält aus dem HTTP Header zu extrahieren um diese im nächsten Request weiterzuverwenden.
|
$param->{method}
optional |
Die HTTP-Methode, welche zur Abfrage verwendet werden soll. Sofern keine Daten übertragen werden ist dies standardmäßig "GET", ansonsten "POST". Es können aber auch andere Methoden verwendet werden.
|
$param->{keepalive}
optional |
Wenn dieser Parameter auf 1 gesetzt ist, wird dem Server der Wunsch mitgeteilt, die Verbindung offen zu lassen für weitere Anfragen. Sobald die Antwort auf den jeweiligen Request eintrifft, bleibt die TCP-Verbindung bestehen (sofern der Server dies unterstützt). Anschließend kann man den Parameter-Hash mit einer neuen URL und Optionen füllen. Der Parameter "keepalive" sollte dabei weiterhin gesetzt bleiben, sofern die Verbindung auch weiterhin möglichst erhalten bleiben soll.
Um eine offene Verbindung endgültig zu schließen, muss die Funktion HttpUtils_Close aufgerufen werden. Standardwert: 0 |
$param->{header}
optional |
Eigene HTTP-Header-Zeilen können über diesen Parameter eingebracht werden. Er kann dazu genutzt werden um z.B. den Content-Type festzulegen, oder einfach nur zusätzliche Header-Felder zu setzen. Mehrere Header-Zeilen müssen dabei mit "\r\n" getrennt werden.
|
$param->{sslargs}
optional |
Eigene SSL-Optionen können über diesen Parameter eingebracht werden. Er kann dazu genutzt werden um z.B. die SSL-Zertifikats Verifikation abzuschalten. Die SSL-Optionen müssen als eigene Hash-Referenz übergeben werden. Eine Liste aller möglichen Optionen findet man in der Perl-Dokumentation zu IO::Socket::SSL.
|
$param->{httpversion}
optional |
Die HTTP-Version, welche zur Abfrage verwendet werden soll. Standardmäßig werden alle Abfragen mit HTTP/1.0 durchgeführt. Falls es jedoch notwendig ist HTTP/1.1 zu verwenden, so sollte $param->{httpversion} auf "1.1" gesetzt werden. Bei Version 1.1 wird automatisch der Header "Connection: close " implizit mitgesendet.
|
Als Rückgabewert von HttpUtils_BlockingGet wird ein Array mit 2 Rückgabewerten zurückgegeben:
($err, $data) = HttpUtils_BlockingGet( … )
Diese 2 Rückgabewerten haben folgende Bedeutung:
Rückgabewert | Bedeutung |
---|---|
$err |
Falls beim Aufruf der URL ein Fehler aufgetreten ist (z.B. Server nicht erreichbar oder Verbindungstimeout), dann ist dieser Wert mit einer Fehlermeldung gefüllt.
|
$data |
Die Ergebnisdaten, welche der HTTP-Server zurückgeliefert hat. Die Daten werden als Klartext in Form eines gesamten Strings zurückgegeben.
|
HttpUtils_NonblockingGet
Diese Funktion arbeitet ähnlich wie HttpUtils_BlockingGet. Allerdings wird das Ergebnis nicht als Funktionsergebnis zurückgegeben. Die Funktion HttpUtils_NonblockingGet initiiert den Verbindungsaufbau und übergibt alles weitere an FHEM interne Routinen. Sobald eine Antwort vom HTTP-Server eintrifft, wird eine Callback-Funktion mit verschiedenen Parametern (unter anderem auch das Ergebnis) aufgerufen, um die Antwort entgegenzunehmen und weiter zu verarbeiten.
Der Aufruf ist daher ähnlich zu HttpUtils_BlockingGet mit nur einem Parameter-Hash:
Aufruf: HttpUtils_NonblockingGet($param)
Parameter | Bedeutung |
---|---|
Alle Hash-Parameter, welche für HttpUtils_BlockingGet gelten, sind auch für HttpUtils_NonblockingGet gültig | |
$param->{callback}
mandatory |
Eine Funktion (oder eine Referenz auf eine Funktion), welche die Ergebnisdaten entgegennimmt und die Antwort entsprechend weiterverarbeitet. Die Callback-Funktion muss dabei 3 Parameter erwarten. Die Funktionsparameter der Callback-Funktion werden im nachfolgenden Abschnitt näher erläutert.
|
Benutzerdefinierte Parameter | Es können im Hash weitere benutzerdefinierte Parameter gesetzt werden, welche evtl. in der Callback-Funktion benötigt werden, um die Antwort korrekt zu verarbeiten.
Zum Beispiel bei der Modul-Programmierung währe das $hash des aktuellen Devices. Alle gesetzten Parameter sind in der Callback-Funktion direkt abrufbar und können ausgewertet werden.
|
Ein Funktionsrückgabewert von HttpUtils_NonblockingGet existiert nicht, da die eigentliche Rückgabe der Daten über die Callback-Funktion erfolgt. Die Callback-Funktion wird aufgerufen, sobdald der HTTP-Request abgeschlossen ist, oder ein Fehler aufgetreten ist. Der Funktionsaufruf erfolgt mit den folgenden Parametern:
MyCallbackFn ( $param, $err, $data )
Diese 3 Parameter haben dabei folgende Bedeutung:
Parameter | Bedeutung |
---|---|
$param |
Der Parameter-Hash, mit allen Argumenten die beim Aufruf der Funktion übergeben worden sind.
Es ist möglich, dass der Parameter-Hash nach erfolgter Abfrage zusätzliche oder veränderte Elemente enthält:
|
$err |
Falls beim Aufruf der URL ein Fehler aufgetreten ist (z.B. Server nicht erreichbar oder Verbindungstimeout), dann ist dieser Wert mit einer Fehlermeldung gefüllt.
|
$data |
Die Ergebnisdaten, welche der HTTP-Server zurückgeliefert hat. Die Daten werden als Klartext in Form eines gesamten Strings zurückgegeben. Es handelt sich hierbei ausschließlich um den HTTP-Body.
|
Die Callback-Funktion kann nun die Daten aus der HTTP-Antwort verarbeiten oder bei Fehler entsprechende Log-Meldungen ausgeben.
Beispiel für HttpUtils_NonblockingGet() für Modulprogrammierer
Das folgende Beispiel soll eine Hilfestellung für eigene Anwendungen geben
use HttpUtils; sub X_GetHttpResponse($) { my ($hash, $def) = @_; my $name = $hash->{NAME}; my $param = { url => "http://www.foo.de", timeout => 5, hash => $hash, # Muss gesetzt werden, damit die Callback funktion wieder $hash hat method => "GET", # Lesen von Inhalten header => "agent: TeleHeater/2.2.3\r\nUser-Agent: TeleHeater/2.2.3\r\nAccept: application/json", # Den Header gemäss abzufragender Daten ändern callback => \&X_ParseHttpResponse # Diese Funktion soll das Ergebnis dieser HTTP Anfrage bearbeiten }; HttpUtils_NonblockingGet($param); # Starten der HTTP Abfrage. Es gibt keinen Return-Code. } sub X_ParseHttpResponse($) { my ($param, $err, $data) = @_; my $hash = $param->{hash}; my $name = $hash->{NAME}; if($err ne "") # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist { Log3 $name, 3, "error while requesting ".$param->{url}." - $err"; # Eintrag fürs Log readingsSingleUpdate($hash, "fullResponse", "ERROR"); # Readings erzeugen } elsif($data ne "") # wenn die Abfrage erfolgreich war ($data enthält die Ergebnisdaten des HTTP Aufrufes) { Log3 $name, 3, "url ".$param->{url}." returned: $data"; # Eintrag fürs Log # An dieser Stelle die Antwort parsen / verarbeiten mit $data readingsSingleUpdate($hash, "fullResponse", $data); # Readings erzeugen } # Damit ist die Abfrage zuende. # Evtl. einen InternalTimer neu schedulen }
HttpUtils_Close
Für den Abbruch von offenen Verbindungen und noch laufenden NonBockingGet-Aufrufen gibt es die Funktion HttpUtils_Close. Diese kann z.B. beim Löschen eines Devices oder Herunterfahren des Servers aufgerufen werden, um bestehende Verbindungen zu schliessen.
Wenn man den Parameter "keepalive" beim Aufruf von HttpUtils_NonBlockingGet/HttpUtils_BlockingGet gesetzt hat, muss man HttpUtils_Close aufrufen um die Verbindung tatsächlich zu schließen, da diese noch durch den Server offen gehalten werden kann.
Aufruf: HttpUtils_Close($param)
Parameter | Bedeutung |
---|---|
$param
mandatory |
Der Hash, der beim vorherigen Aufruf an HTTPUtils Funktionen (HttpUtils_NonblockingGet oder HttpUtils_BlockingGet) übergeben wurde |