HttpUtils: Unterschied zwischen den Versionen

Aus FHEMWiki
K (Änderungen von Ph1959de (Diskussion) wurden auf die letzte Version von BerndArnold zurückgesetzt)
K (tippfehler incrementalTimout ausgebessert)
 
(35 dazwischenliegende Versionen von 8 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
= Allgemein =
{{Infobox Modul
|ModPurpose=Hilfsfunktionen für HTTP-Zugriffe
|ModType=u
|ModForumArea=Automatisierung
|ModTechName=HttpUtils.pm
|ModOwner=rudolfkoenig ({{Link2FU|8|Forum}} / [[Benutzer Diskussion:Rudolfkoenig|Wiki]])
}}


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 bereit, auf die in diesem Artikel näher eingegangen werden soll.
Das Modul [[HttpUtils]](.pm) ist sowohl für Modulentwickler als auch für 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.
 
Erstellt wurde HttpUtils.pm von Rudolf König.
 
== Die Funktionen im Einzelnen ==


== Primäre Funktionen (HTTP) ==
Es ist zu beachten, dass bei den Funktionen
Es ist zu beachten, dass bei den Funktionen
* <code>GetHttpFile()</code>
* <code>GetFileFromURL</code>
* <code>GetFileFromURLQuiet</code>
* <code>HttpUtils_BlockingGet</code>
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). In der Zeit, in der auf eine HTTP Antwort gewartet wird, steht FHEM dabei komplett.


* GetHttpFile
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.
* 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 so etwas 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 verhindern.
 
 
Alternativ kann man die Funktion
 
* HttpUtils_NonblockingGet
 
verwenden, welche ein Blockieren von FHEM verhindert. Wie das genau funktioniert, wird in dem entsprechenden Kapitel beschrieben.
 
 
Folgende Funktionen sind für Modulentwickler/Endanwender zur direkten Nutzung gedacht:


Um eine Blockierung zu vermeiden wird generell die Verwendung von
:<code>HttpUtils_NonblockingGet</code>
empfohlen. Diese führt den HTTP-Request asynchron durch, wodurch ein Blockieren von FHEM verhindert wird. Wie das genau funktioniert, wird in dem entsprechenden Kapitel beschrieben.


=== GetHttpFile ===
=== GetHttpFile ===
Die Funktion GetHttpFile ist die denkbar einfachste Variante um eine URL aufzurufen.  
Die Funktion GetHttpFile ist die denkbar einfachste Variante um eine URL aufzurufen.  
 
:<code>GetHttpFile($server, $file)</code>
 
'''Aufruf: <code>GetHttpFile($server, $file)</code>'''
 
{| class="wikitable"
{| class="wikitable"
|-
|-
! Parameter!! Bedeutung
! Parameter!! Bedeutung
|-
|-
| style="vertical-align:top" | '''<code>$server</code>'''
| style="vertical-align:top" | '''<code>$server</code>'''


''mandatory''
''mandatory''
|| Der DNS-Name oder die IP-Adresse des HTTP-Servers<br><br>
|| Der DNS-Name oder die IP-Adresse des HTTP-Servers<br>
Beispiel:
Beispiel:


Zeile 49: Zeile 39:
* ''<nowiki>192.168.0.10</nowiki>''
* ''<nowiki>192.168.0.10</nowiki>''
|-
|-
| style="vertical-align:top" | '''<code>$file</code>'''  
| style="vertical-align:top" | '''<code>$file</code>'''  


''mandatory''
''mandatory''
|| Die Datei, welche auf dem HTTP-Server aufgerufen werden soll.<br><br>
|| Die Datei, welche auf dem HTTP-Server aufgerufen werden soll.<br>
Beispiel:
Beispiel:
* ''/''
* ''/''
Zeile 59: Zeile 49:
|}
|}


Funktionsergebnis ist der Inhalt der aufgerufenen Seite in Form eines Strings.
Funktionsergebnis ist der Inhalt der aufgerufenen Seite in Form einer Zeichenkette.


=== GetFileFromURL ===
=== 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.
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: <code>GetFileFromURL($url, ''[$timeout], [$data], [$noshutdown], [$loglevel]'')</code>'''
'''Aufruf: <code>GetFileFromURL($url, ''[$timeout], [$data], [$noshutdown], [$loglevel]'')</code>'''
Zeile 72: Zeile 60:
! Parameter!! Bedeutung
! Parameter!! Bedeutung
|-
|-
| style="vertical-align:top" | '''<code>$url</code>'''
| style="vertical-align:top" | '''<code>$url</code>'''


''mandatory''
''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.<br><br>
|| 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.<br>
Beispiel:
Beispiel:


Zeile 81: Zeile 69:
* ''<nowiki>https://www.myhost.com/</nowiki>''
* ''<nowiki>https://www.myhost.com/</nowiki>''
* ''<nowiki>http://www.myhost.com:8080/</nowiki>''
* ''<nowiki>http://www.myhost.com:8080/</nowiki>''
* ''<nowiki>http://foo:bar@www.myhost.com/</nowiki>''
* ''<nowiki>http://user:password@www.myhost.com/</nowiki>''
 
'''WICHTIG:''' Falls ein Username sowie Passwort übergeben werden, so müssen diese vorher jeweils mittels [[#urlEncode|urlEncode()]] in URL-kompatible Form umgewandelt werden um Probleme mit evtl. enthaltenen Sonderzeichen zu vermeiden.
|-
|-
| style="vertical-align:top" | '''<code>$timeout</code>'''
| style="vertical-align:top" | '''<code>$timeout</code>'''


''optional''
''optional''
|| Die maximale Dauer in Sekunden für die HTTP-Anfrage
|| Die maximale Dauer in Sekunden für die HTTP-Anfrage


Beispiel: 5 ''(Sekunden)''
Beispiel: 5 ''(Sekunden)''
Zeile 97: Zeile 86:
''optional''
''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.
|| 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.


Standardwert: ''[leer]''
Standardwert: ''[leer]''


|-
|-
| style="vertical-align:top" | '''<code>$noshutdown</code>'''  
| style="vertical-align:top" | '''<code>$noshutdown</code>'''  


''optional''
''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.
|| 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.
 


Standardwert: 1
Standardwert: 1
|-
|-
| style="vertical-align:top" | '''<code>$loglevel</code>'''
| style="vertical-align:top" | '''<code>$loglevel</code>'''


''optional''
''optional''
|| Das Logleve, in dem sämtliche Logmeldungen zu dieser HTTP-Abfrage erzeugt werden sollen.
|| Das [[verbose|Loglevel]], in dem sämtliche Logmeldungen zu dieser HTTP-Abfrage erzeugt werden sollen.
 


Standardwert: 4
Standardwert: 4
Zeile 122: Zeile 108:


=== GetFileFromURLQuiet ===
=== 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.
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: <code>GetFileFromURLQuiet($url, ''[$timeout], [$data], [$noshutdown], [$loglevel]'')</code>'''
'''Aufruf: <code>GetFileFromURLQuiet($url, ''[$timeout], [$data], [$noshutdown], [$loglevel]'')</code>'''
Zeile 132: Zeile 116:
! Parameter!! Bedeutung
! Parameter!! Bedeutung
|-
|-
| style="vertical-align:top" | '''<code>$url</code>'''
| style="vertical-align:top" | '''<code>$url</code>'''


''mandatory''
''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.<br><br>
|| 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.<br>
Beispiel:
Beispiel:


Zeile 141: Zeile 125:
* ''<nowiki>https://www.myhost.com/</nowiki>''
* ''<nowiki>https://www.myhost.com/</nowiki>''
* ''<nowiki>http://www.myhost.com:8080/</nowiki>''
* ''<nowiki>http://www.myhost.com:8080/</nowiki>''
* ''<nowiki>http://foo:bar@www.myhost.com/</nowiki>''
* ''<nowiki>http://user:password@www.myhost.com/</nowiki>''
 
'''WICHTIG:''' Falls ein Username sowie Passwort übergeben werden, so müssen diese vorher jeweils mittels [[#urlEncode|urlEncode()]] in URL-kompatible Form umgewandelt werden um Probleme mit evtl. enthaltenen Sonderzeichen zu vermeiden.
|-
|-
| style="vertical-align:top" | '''<code>$timeout</code>'''
| style="vertical-align:top" | '''<code>$timeout</code>'''


''optional''
''optional''
|| Die maximale Dauer in Sekunden für die HTTP-Anfrage
|| Die maximale Dauer in Sekunden für die HTTP-Anfrage


Beispiel: 5 ''(Sekunden)''
Beispiel: 5 ''(Sekunden)''
Zeile 153: Zeile 138:
Standardwert: 4 Sekunden
Standardwert: 4 Sekunden
|-
|-
| style="vertical-align:top" | '''<code>$data</code>'''
| style="vertical-align:top" | '''<code>$data</code>'''


''optional''
''optional''
|| Wenn man Daten via HTTP-POST übertragen möchte, so kann man die Nutzdaten über <code>$data</code> ü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.
|| Wenn man Daten via HTTP-POST übertragen möchte, so kann man die Nutzdaten über <code>$data</code> ü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.


Standardwert: ''[leer]''
Standardwert: ''[leer]''


|-
|-
| style="vertical-align:top" | '''<code>$noshutdown</code>'''  
| style="vertical-align:top" | '''<code>$noshutdown</code>'''  


''optional''
''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.
|| 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.
 


Standardwert: 1
Standardwert: 1
|-
|-
| style="vertical-align:top" | '''<code>$loglevel</code>'''
| style="vertical-align:top" | '''<code>$loglevel</code>'''


''optional''
''optional''
|| Das Loglevel, in dem sämtliche Logmeldungen zu dieser HTTP-Abfrage erzeugt werden sollen.
|| Das Loglevel, in dem sämtliche Logmeldungen zu dieser HTTP-Abfrage erzeugt werden sollen.


Standardwert: 4
Standardwert: 4
Zeile 182: Zeile 164:


=== HttpUtils_BlockingGet ===
=== 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.  
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 ein Hash mit allen Funktionsparametern darstellt. Dieser Hash enthält sämtliche Parameter inkl. Werten.  
 


'''Aufruf: <code>HttpUtils_BlockingGet($param)</code>'''
'''Aufruf: <code>HttpUtils_BlockingGet($param)</code>'''


Der Hash $param kann folgende Optionen beinhalten:
Der Parameter $param ist eine Referenz auf eine Hash-Struktur, welche die einzelnen Parameter enthält. Der Hash $param kann folgende Optionen beinhalten:


{| class="wikitable"
{| class="wikitable"
Zeile 197: Zeile 177:


''mandatory''
''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.<br><br>
  || 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.<br>
Beispiel:
Beispiel:


Zeile 203: Zeile 183:
* ''<nowiki>https://www.myhost.com/</nowiki>''
* ''<nowiki>https://www.myhost.com/</nowiki>''
* ''<nowiki>http://www.myhost.com:8080/</nowiki>''
* ''<nowiki>http://www.myhost.com:8080/</nowiki>''
* ''<nowiki>http://foo:bar@www.myhost.com/</nowiki>''
* ''<nowiki>http://user:password@www.myhost.com/</nowiki>''


'''WICHTIG:''' Alternativ können die Zugangsdaten auch in <code>$param->{user}</code> und <code>$param->{pwd}</code> übergeben werden. Falls  Username und Passwort in der URL übergeben werden, so müssen diese vorher jeweils mittels [[#urlEncode|urlEncode()]] in URL-kompatible Form umgewandelt werden um Probleme mit evtl. enthaltenen Sonderzeichen (z.B. ":" und "@") zu vermeiden, da sonst die URL nicht mehr einer validen Syntax entspricht.
|-
|-
| style="vertical-align:top" |'''<code>$param->{timeout}</code>'''
| style="vertical-align:top" |'''<code>$param->{timeout}</code>'''


''optional''
''optional''
|| Die maximale Dauer in Sekunden für die HTTP-Anfrage
|| Die maximale Dauer in Sekunden bis der Server eine Antwort liefern muss. Andernfalls wird der Request mit einer Fehlermeldung abgebrochen.
 


Beispiel: 5 ''(Sekunden)''
Beispiel: 5 ''(Sekunden)''
Zeile 216: Zeile 196:
Standardwert: 4 Sekunden
Standardwert: 4 Sekunden
|-
|-
| style="vertical-align:top" |'''<code>$param->{data}</code>'''
| style="vertical-align:top" |'''<code>$param->{data}</code>'''


''optional''
''optional''
|| Wenn man Daten via HTTP-POST übertragen möchte, so kann man die Nutzdaten über <code>$param{data}</code> übergeben. Die Daten werden dabei als Formulardaten übertragen. Die Daten können dabei auf zwei Arten übergeben werden:
|| Wenn man Daten via HTTP-POST übertragen möchte, so kann man die Nutzdaten über <code>$param->{data}</code> übergeben. Die Daten werden dabei als Formulardaten übertragen. Die Daten können dabei auf zwei Arten übergeben werden:
 
1. Daten als Zeichenkette:
:* Die Daten werden komplett als gesamte Zeichenkette in <code>$param->{data}</code> abgelegt (z.B.: <code>$param->{data} = "Jede Menge tolle Daten"</code>).
2. Daten als Hash-Struktur:
:* Die Daten werden als Hash mit Key-Value-Pairs übergeben (z.B.: <code>$param->{data}{field1} = "value1", $param{data}{field2} = "value2", ...</code> ). Die Daten werden dann als Formulardaten mit mehrfachen Datenfeldern übertragen.
 
Standardwert: ''[leer]''


1. Daten als String:
|-
:* Die Daten werden komplett als gesamter String in <code>$param{data}</code> abgelegt (z.B.: $param{data} = "Jede Menge tolle Daten").
| style="vertical-align:top" | '''<code>$param->{user}</code>'''
2. Daten als Hash:
:* Die Daten werden als Hash mit Key-Value-Pairs übergeben (z.B.: $param{data}{field1} = "value1", $param{data}{field2} = "value2", ... ). Die Daten werden dann als Formulardaten mit mehrfachen Datenfeldern übertragen.


''optional''
||Im Falle einer notwendigen HTTP-Authentifizierung, der zu benutzende Username um sich gegenüber dem Server zu identifizieren. Alternativ kann der Username und das Passwort auch direkt in der URL mitgegeben werden (siehe jedoch <code>$param->{hideurl}</code>).


Standardwert: ''[leer]''
Standardwert: ''[leer]''
|-
| style="vertical-align:top" | '''<code>$param->{pwd}</code>'''


''optional''
||Im Falle einer notwendigen HTTP-Authentifizierung, das zu benutzende Passwort um sich gegenüber dem Server zu identifizieren. Alternativ kann der Username und das Passwort auch direkt in der URL mitgegeben werden (siehe jedoch <code>$param->{hideurl}</code>).
Standardwert: ''[leer]''
|-
|-
| style="vertical-align:top" | '''<code>$param->{noshutdown}</code>'''  
| style="vertical-align:top" | '''<code>$param->{noshutdown}</code>'''  


''optional''
''optional''
||Wenn <code>$param->{noshutdown}</code> 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.
||Wenn <code>$param->{noshutdown}</code> 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.
 


Standardwert: 1
Standardwert: 1
|-
|-
| style="vertical-align:top" | '''<code>$param->{loglevel}</code>'''
| style="vertical-align:top" | '''<code>$param->{loglevel}</code>'''


''optional''
''optional''
|| Das Loglevel, in dem sämtliche Logmeldungen zu dieser HTTP-Abfrage erzeugt werden sollen.
|| Das Loglevel, in dem sämtliche Logmeldungen zu dieser HTTP-Abfrage erzeugt werden sollen.


Standardwert: 4
Standardwert: 4
|-
|-
| style="vertical-align:top" | '''<code>$param->{hideurl}</code>'''
| style="vertical-align:top" | '''<code>$param->{hideurl}</code>'''


''optional''
''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.
|| Wenn dieser Parameter den Wert 1 trägt, wird die gesamte URL in sämtlichen Log-Ausgaben unkenntlich gemacht. Dies notwendig, wenn z.B. Zugangsdaten direkt in der URL angegeben wurden, oder die URL ein geheimes Token oder andere schützenswerte Informationen enthält.
 
Standardwert: 0
|-
| style="vertical-align:top" | '''<code>$param->{ignoreredirects}</code>'''


''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.


Standardwert: 0
Standardwert: 0
|-
|-
| style="vertical-align:top" | '''<code>$param->{method}</code>'''
| style="vertical-align:top" | '''<code>$param->{method}</code>'''


''optional''
''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.
||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.


Standardwert: "GET"
|-
| style="vertical-align:top" | '''<code>$param->{keepalive}</code>'''


Standardwert: "GET"
''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#HttpUtils_Close|HttpUtils_Close]] aufgerufen werden.
 
Standardwert: 0
|-
|-
| style="vertical-align:top" | '''<code>$param->{header}</code>'''
| style="vertical-align:top" | '''<code>$param->{header}</code>'''


''optional''
''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.
|| 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. Es gibt zwei Möglichkeiten, diesen Parameter zu befüllen.


# Als '''Zeichenkette'''. Mehrere Header-Zeilen müssen dabei mit "\r\n" getrennt werden.
# Als '''Hash-Struktur'''. Hierbei findet eine Zuordnung von Header-Bezeichnung zum Wert als Key-Value-Pair statt.


Beispiel:
Beispiel:
* <code>User-Agent: Mozilla/1.22'''<u>\r\n</u>'''Content-Type: application/xml</code>
* <code>"User-Agent: Mozilla/1.22'''<u>\r\n</u>'''Content-Type: application/xml"</code>
* <code>Content-Type: application/xml</code>
* <code>"Content-Type: application/xml"</code>
* <code>{ "User-Agent" =>  "Mozilla/1.22", "Content-Type" => "application/xml" }</code>
* <code>{ "Content-Type" => "application/xml" }</code>


Standardwert: ''[leer]''
|-
| style="vertical-align:top" | '''<code>$param->{sslargs}</code>'''


Standardwert: ''[leer]''
''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 [http://search.cpan.org/~sullr/IO-Socket-SSL-2.016/lib/IO/Socket/SSL.pod#Description_Of_Methods IO::Socket::SSL].
 
Beispiel:
* <code>$param->{sslargs} = { SSL_verify_mode => 0, sslOpt2 => 'sslVal2' }</code>
 
Standardwert: ''{ }''
|-
|-
| style="vertical-align:top" | '''<code>$param->{httpversion}</code>'''
| style="vertical-align:top" | '''<code>$param->{httpversion}</code>'''


''optional''
''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 <code>$param->{httpversion}</code> auf "1.1" gesetzt werden. Bei Version 1.1 wird automatisch der Header "<code>Connection: close</code>" implizit mitgesendet.
|| 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 <code>$param->{httpversion}</code> auf "1.1" gesetzt werden. Bei Version 1.1 wird automatisch der Header "<code>Connection: close</code>" implizit mitgesendet.


Standardwert: "1.0"
|-
| style="vertical-align:top" | '''<code>$param->{digest}</code>'''


Standardwert: "1.0"
''optional''
|}
|| Wenn dieser Parameter den Wert 1 trägt, wird bei vorhandenen Authentifizierungsdaten (Username+Passwort) eine Authentifizierung via Digest-Verfahren nach RFC 2617<ref name="rfc2617">RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication</ref> erwartet. Die Anmeldedaten werden dann nur verwendet, wenn dieser explizit eine HTTP Digest Authentifizierung einleitet. Ist dieser Parameter nicht gesetzt (Wert: 0), wird bei vorhandenen Authentifizierungsdaten immer eine HTTP Basic<ref name="rfc2617" /> Authentifizierung im Request mitgeschickt.


Standardwert: 0
|-
| style="vertical-align:top" | '''<code>$param->{compress}</code>'''


Als Rückgabewert von HttpUtils_BlockingGet wird ein Array mit 2 Rückgabewerten zurückgegeben:
''optional''
|| Wenn dieser Parameter den Wert 1 trägt, wird dem Server die Verwendung von Komprimierung in Form GZIP oder alternativ Deflate<ref>RFC 1951 - DEFLATE Compressed Data Format Specification version 1.3</ref> zur Übertragung der Antwort ermöglicht. Die komprimierte Antwort wird dabei direkt durch HttpUtils.pm wieder dekomprimiert. Wird dieser Parameter auf den Wert 0 gesetzt, so wird keine Komrpimierung ermöglicht.


($err, $data) = HttpUtils_BlockingGet( … )
'''WICHTIG''': Die Verwendung von Komprimierung in HttpUtils.pm kann mit dem globalen Attribut "httpcompress" (Standardwert: 1) durch setzen auf 0 für die gesamte FHEM Installation durch den Nutzer deaktiviert werden. In diesem Fall ist der Parameter <code>$param->{compress} = 1</code> wirkungslos.


Diese 2 Rückgabewerten haben folgende Bedeutung:
Standardwert: 1
|}
 
Als Rückgabewert von HttpUtils_BlockingGet wird ein Array mit zwei Rückgabewerten zurückgegeben:
:<code>($err, $data) = HttpUtils_BlockingGet( … )</code>
Diese zwei Rückgabewerte haben folgende Bedeutung:


{| class="wikitable"
{| class="wikitable"
Zeile 296: Zeile 325:
|-
|-
| style="vertical-align:top" | '''<code>$err</code>'''|| 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.  
| style="vertical-align:top" | '''<code>$err</code>'''|| 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.  


Wenn kein Fehler aufgetreten ist, ist dieser Wert mit einem Leerstring gefüllt (<code>$err = ""</code>)
Wenn kein Fehler aufgetreten ist, ist dieser Wert mit einem Leerstring gefüllt (<code>$err = ""</code>)
|-
|-
| style="vertical-align:top" | '''<code>$data</code>'''|| Die Ergebnisdaten, welche der HTTP-Server zurückgeliefert hat. Die Daten werden als Klartext in Form eines gesamten Strings zurückgegeben.
| style="vertical-align:top" | '''<code>$data</code>'''|| Die Ergebnisdaten, welche der HTTP-Server zurückgeliefert hat. Die Daten werden als Klartext in Form eines gesamten Strings zurückgegeben.


Falls ein Fehler aufgetreten ist, ist dieser Wert mit einem Leersting gefüllt (<code>$data = ""</code>)
Falls ein Fehler aufgetreten ist, ist dieser Wert mit einem Leersting gefüllt (<code>$data = ""</code>)
Zeile 307: Zeile 334:


=== HttpUtils_NonblockingGet ===
=== HttpUtils_NonblockingGet ===
{{Randnotiz|RNText=Die Funktion HttpUtils_NonblockingGet ist nicht komplett durchgehend "non-blocking". DNS-Abfragen sind nachwievor blockierend. Insbesondere wenn der DNS-Name nicht aufgelöst werden kann.}}
{{Randnotiz|RNText=Die Funktion HttpUtils_NonblockingGet ist nicht komplett durchgehend "non-blocking". DNS-Abfragen sind weiterhin blockierend. Insbesondere wenn der DNS-Name nicht aufgelöst werden kann.}}
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.
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:
Der Aufruf ist daher ähnlich zu HttpUtils_BlockingGet mit nur einem Parameter-Hash:
Zeile 319: Zeile 345:
! style="width:175px" | Parameter !! style="width:auto" | Bedeutung
! style="width:175px" | Parameter !! style="width:auto" | Bedeutung
|-
|-
| colspan="2" style="text-align:center" | '''''<br>Alle Hash-Parameter, welche für HttpUtils_BlockingGet gelten, sind auch für HttpUtils_NonblockingGet gültig'''''<br><br>
| colspan="2" style="text-align:center" | '''''<br>Alle Hash-Parameter, welche für HttpUtils_BlockingGet gelten, sind auch für HttpUtils_NonblockingGet gültig'''''<br>
|-
|-
| style="vertical-align:top" | '''<code>$param->{callback}</code>'''  
| style="vertical-align:top" | '''<code>$param->{callback}</code>'''  


''mandatory''
''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.
|| 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.


Beispiel:  
Beispiel:  
* <code>$param->{callback} = \&MyCallbackFn</code> — ''(Referenzzeiger auf Funktionsname)''
* <code>$param->{callback} = \&MyCallbackFn</code> — ''(Referenzzeiger auf Funktionsname)''
* <code>$param->{callback} = sub($$$){ … }</code> —  ''(direkte Funktionsdefinition)''
* <code>$param->{callback} = sub(){ … }</code> —  ''(direkte Funktionsdefinition)''
|-
| style="vertical-align:top;white-space:nowrap;" | '''<code>$param->{incrementalTimeout}</code>'''
 
''optional''
|| Sofern gesetzt (Wert: <code>1</code>), wird der Timeout nach jedem Empfang von Teil-Daten wieder zurückgesetzt. So können größere Datenmengen von langsamen Sendern empfangen werden, ohne den Parameter <code>timeout</code> zu erhöhen und dadurch tatsächliche Verbindungsprobleme erst spät zu erkennen.
 
Standardwert: 0
|-
|-
| style="vertical-align:top" | ''Benutzerdefinierte Parameter''  
| style="vertical-align:top" | ''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.
|| 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.
Zum Beispiel im Rahmen der Modul-Programmierung wäre das <code>$hash</code> der aktuellen Definition. Alle gesetzten Parameter sind in der Callback-Funktion wieder über <code>$param</code> direkt abrufbar und können ausgewertet werden.
 


Beispiel:  
Beispiel:  
Zeile 342: Zeile 373:


|}  
|}  


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:
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:


<code> ''MyCallbackFn'' ( $param, $err, $data )</code>
<code> ''MyCallbackFn'' ( $param, $err, $data )</code>


Diese 3 Parameter haben dabei folgende Bedeutung:
Diese 3 Parameter haben dabei folgende Bedeutung:
Zeile 363: Zeile 392:
* '''<code>$param->{path}</code>''' - Der Pfad, welcher auf dem HTTP-Server angefragt wurde.
* '''<code>$param->{path}</code>''' - Der Pfad, welcher auf dem HTTP-Server angefragt wurde.
* '''<code>$param->{host}</code>''' - Der Name oder die IP-Adresse des HTTP-Servers.
* '''<code>$param->{host}</code>''' - Der Name oder die IP-Adresse des HTTP-Servers.
* '''<code>$param->{httpheader}</code>''' - Der gesamte HTTP Header, welcher der Server bei der letzten Antwort zurücklieferte.
* '''<code>$param->{code}</code>''' - Der HTTP-Statuscode, mit dem die Anfrage vom Server beantwortet wurde.
* '''<code>$param->{code}</code>''' - Der HTTP-Statuscode, mit dem die Anfrage vom Server beantwortet wurde.
* '''<code>$param->{addr}</code>''' - Die HTTP-URL ohne Pfad und evtl. Authentifizerungsinformationen des HTTP-Servers (z.B. "<nowiki>http://myserver.com:8080</nowiki>").
* '''<code>$param->{addr}</code>''' - Die HTTP-URL ohne Pfad und evtl. Authentifizerungsinformationen des HTTP-Servers (z.B. "<nowiki>http://myserver.com:8080</nowiki>").
* '''<code>$param->{auth}</code>''' - Der Authentifizierungs-String, welcher verwendet wurde um sich gegenüber dem HTTP-Server zu authentifizieren (nur wenn Authentifizierung benutzt wurde).
* '''<code>$param->{auth}</code>''' - Ein Flag (0/1) ob Zugangsdaten für den Request zur Verfügung standen (durch Angabe in der URL oder direkt in <code>$param</code>).
|-
|-
| style="vertical-align:top" | '''<code>$err</code>'''|| 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.  
| style="vertical-align:top" | '''<code>$err</code>'''|| 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.  


Wenn kein Fehler aufgetreten ist, ist dieser Wert mit einem Leerstring gefüllt (<code>$err = ""</code>)
Wenn kein Fehler aufgetreten ist, ist dieser Wert mit einem Leerstring gefüllt (<code>$err = ""</code>)
|-
|-
| style="vertical-align:top" | '''<code>$data</code>'''|| 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.  
| style="vertical-align:top" | '''<code>$data</code>'''|| 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.  


Falls ein Fehler aufgetreten ist, ist dieser Wert mit einem Leersting gefüllt (<code>$data = ""</code>)
Falls ein Fehler aufgetreten ist, ist dieser Wert mit einem Leersting gefüllt (<code>$data = ""</code>)
|}
|}


Die Callback-Funktion kann nun die Daten aus der HTTP-Antwort verarbeiten oder bei Fehler entsprechende Log-Meldungen ausgeben.
Die Callback-Funktion kann nun die Daten aus der HTTP-Antwort verarbeiten oder bei Fehlern entsprechende Log-Meldungen ausgeben.
 
 
==== Programmierbeispiel für HttpUtils_NonblockingGet() ====


==== Beispiel für HttpUtils_NonblockingGet() für Modulprogrammierer ====
Das folgende Beispiel soll eine Hilfestellung für eigene Anwendungen geben
Das folgende Beispiel soll eine Hilfestellung für eigene Anwendungen geben


<pre>use HttpUtils;
<syntaxhighlight lang="perl">use HttpUtils;
sub X_GetHttpResponse($)
sub X_PerformHttpRequest($)
{
{
     my ($hash, $def) = @_;
     my ($hash, $def) = @_;
     my $name = $hash->{NAME};
     my $name = $hash->{NAME};
     my $param = {
     my $param = {
                     url        => "http://www.foo.de",
                     url        => "http://www.foo.de/",
                     timeout    => 5,
                     timeout    => 5,
                     hash      => $hash,                                                                                 # Muss gesetzt werden, damit die Callback funktion wieder $hash hat
                     hash      => $hash,                                                                                 # Muss gesetzt werden, damit die Callback funktion wieder $hash hat
                     method    => "GET",                                                                                 # Lesen von Inhalten
                     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
                     header    => "User-Agent: TeleHeater/2.2.3\r\nAccept: application/json",                           # Den Header gemäß abzufragender Daten ändern
                     callback  => \&X_ParseHttpResponse                                                                  # Diese Funktion soll das Ergebnis dieser HTTP Anfrage bearbeiten
                     callback  => \&X_ParseHttpResponse                                                                  # Diese Funktion soll das Ergebnis dieser HTTP Anfrage bearbeiten
                 };
                 };
                         
 
     HttpUtils_NonblockingGet($param);                                                                                     # Starten der HTTP Abfrage. Es gibt keinen Return-Code.  
     HttpUtils_NonblockingGet($param);                                                                                   # Starten der HTTP Abfrage. Es gibt keinen Return-Code.  
   
}
}


sub X_ParseHttpResponse($)
sub X_ParseHttpResponse($)
{
{
     my ($param, $err, $data) = @_;
     my ($param, $err, $data) = @_;
     my $hash = $param->{hash};
     my $hash = $param->{hash};
     my $name = $hash->{NAME};
     my $name = $hash->{NAME};


     if($err ne "")                                                                                                         # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist
     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
         Log3 $name, 3, "error while requesting ".$param->{url}." - $err";                                               # Eintrag fürs Log
         readingsSingleUpdate($hash, "fullResponse", "ERROR");                                                             # Readings erzeugen
         readingsSingleUpdate($hash, "fullResponse", "ERROR", 0);                                                       # Readings erzeugen
     }
     }


     elsif($data ne "")                                                                                                     # wenn die Abfrage erfolgreich war ($data enthält die Ergebnisdaten des HTTP Aufrufes)
     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
         Log3 $name, 3, "url ".$param->{url}." returned: $data";                                                         # Eintrag fürs Log


         # An dieser Stelle die Antwort parsen / verarbeiten mit $data
         # An dieser Stelle die Antwort parsen / verarbeiten mit $data


         readingsSingleUpdate($hash, "fullResponse", $data);                                                               # Readings erzeugen
         readingsSingleUpdate($hash, "fullResponse", $data, 0);                                                         # Readings erzeugen
     }
     }
      
      
     # Damit ist die Abfrage zuende.
     # Damit ist die Abfrage zuende.
     # Evtl. einen InternalTimer neu schedulen
     # Evtl. einen InternalTimer neu schedulen
}</pre>
}</syntaxhighlight>
 
=== 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: <code>HttpUtils_Close($param)</code>'''
 
{| class="wikitable"
|-
! style="width:175px" | Parameter !! style="width:auto" | Bedeutung
|-
| style="vertical-align:top" | '''<code>$param</code>'''
 
''mandatory''
|| Der Hash, der beim vorherigen Aufruf an HTTPUtils Funktionen (HttpUtils_NonblockingGet oder HttpUtils_BlockingGet) übergeben wurde
 
|}
 
== Hilfsfunktionen ==
 
=== urlEncode ===
 
:<syntaxhighlight lang="perl">
$encoded = urlEncode($string);
</syntaxhighlight>
Die Funktion urlEncode() wandelt die übergebene Zeichenkette <code>$string</code> in eine URL-kompatible<ref name="rfc3986-2.1">[https://tools.ietf.org/html/rfc3986#section-2.1 RFC 3989] - Abschnitt 2.1 "Percent-Encoding"</ref> Zeichenkette um. Der Rückgabewert <code>$encoded</code> ist eine Zeichenkette welche innerhalb einer URL verwendet werden kann, bspw. als Wert eines GET-Parameters.
 
Parameter:
{| class="wikitable"
|-
! Parameter !! Bedeutung
|-
| style="vertical-align:top" | '''<code>$string</code>'''
 
''mandatory''
|| Die Zeichenkette, welche in eine URL-kompatible Form umgewandelt werden soll.
|}
 
Rückgabewerte:
{| class="wikitable"
|-
! Rückgabewert !! Bedeutung
|-
| style="vertical-align:top" | '''<code>$encoded </code>''' || Die URL-kompatible Version der übergebenen Zeichenkette. Problematische Zeichen sind in diesem Wert durch ein Prozentzeichen gefolgt von der Hexadezimaldarstellung des Zeichens dargestellt.
 
Bsp:
* "a: b" => "a%3a%20b"
* "a/b" => "a%2fb"
|}
 
=== urlDecode ===
 
 
:<syntaxhighlight lang="perl">
$string = urlDecode($encoded);
</syntaxhighlight>
Die Funktion urlDecode () normalisiert die übergebene Zeichenkette <code>$encoded</code> und ersetzt dabei sämtliche Hexadezimaldarstellungen<ref name="rfc3986-2.1" /> (eingeleitet mit einem Prozentzeichen) durch die entsprechenden Zeichen. Der Rückgabewert <code>$string</code> ist eine Zeichenkette welche keinerlei Hexadezimaldarstellungen mehr aufweist.
 
Parameter:
{| class="wikitable"
|-
! Parameter !! Bedeutung
|-
| style="vertical-align:top" | '''<code>$encoded</code>'''
 
''mandatory''
|| Eine Zeichenkette, welche URL-kombatible Hexadezimaldarstellungen enthält.
|}
 
Rückgabewerte:
{| class="wikitable"
|-
! Rückgabewert !! Bedeutung
|-
| style="vertical-align:top" | '''<code>$string</code>''' || Die normale Version der übergebenen Zeichenkette. Sämtliche Hexadezimalddarstellungen sind in ihre entsprechenden Zeichen umgewandelt.
 
Bsp:
* "a%3a%20b" => "a: b"
* "a%2fb" => "a/b"
|}
 
== Referenzen ==


<references />


[[Kategorie:Development]]
[[Kategorie:Development]]

Aktuelle Version vom 8. April 2021, 07:38 Uhr

HttpUtils
Zweck / Funktion
Hilfsfunktionen für HTTP-Zugriffe
Allgemein
Typ Utilities
Details
Dokumentation siehe Forum
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 für 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.

Primäre Funktionen (HTTP)

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). In der Zeit, in der auf eine HTTP Antwort gewartet wird, steht FHEM dabei komplett.

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.

Um eine Blockierung zu vermeiden wird generell die Verwendung von

HttpUtils_NonblockingGet

empfohlen. Diese führt den HTTP-Request asynchron durch, wodurch ein Blockieren von FHEM verhindert wird. Wie das genau funktioniert, wird in dem entsprechenden Kapitel beschrieben.

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:

  • www.myhost.com
  • 192.168.0.10
$file

mandatory

Die Datei, welche auf dem HTTP-Server aufgerufen werden soll.

Beispiel:

  • /
  • /index.html
  • /directory/image.jpg

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:

  • http://www.myhost.com/directory/
  • https://www.myhost.com/
  • http://www.myhost.com:8080/
  • http://user:password@www.myhost.com/

WICHTIG: Falls ein Username sowie Passwort übergeben werden, so müssen diese vorher jeweils mittels urlEncode() in URL-kompatible Form umgewandelt werden um Probleme mit evtl. enthaltenen Sonderzeichen zu vermeiden.

$timeout

optional

Die maximale Dauer in Sekunden für die HTTP-Anfrage

Beispiel: 5 (Sekunden)

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.

Standardwert: [leer]

$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.

Standardwert: 1

$loglevel

optional

Das Loglevel, in dem sämtliche Logmeldungen zu dieser HTTP-Abfrage erzeugt werden sollen.

Standardwert: 4

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:

  • http://www.myhost.com/directory/
  • https://www.myhost.com/
  • http://www.myhost.com:8080/
  • http://user:password@www.myhost.com/

WICHTIG: Falls ein Username sowie Passwort übergeben werden, so müssen diese vorher jeweils mittels urlEncode() in URL-kompatible Form umgewandelt werden um Probleme mit evtl. enthaltenen Sonderzeichen zu vermeiden.

$timeout

optional

Die maximale Dauer in Sekunden für die HTTP-Anfrage

Beispiel: 5 (Sekunden)

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.

Standardwert: [leer]

$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.

Standardwert: 1

$loglevel

optional

Das Loglevel, in dem sämtliche Logmeldungen zu dieser HTTP-Abfrage erzeugt werden sollen.

Standardwert: 4

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:

  • http://www.myhost.com/directory/
  • https://www.myhost.com/
  • http://www.myhost.com:8080/
  • http://user:password@www.myhost.com/

WICHTIG: Alternativ können die Zugangsdaten auch in $param->{user} und $param->{pwd} übergeben werden. Falls Username und Passwort in der URL übergeben werden, so müssen diese vorher jeweils mittels urlEncode() in URL-kompatible Form umgewandelt werden um Probleme mit evtl. enthaltenen Sonderzeichen (z.B. ":" und "@") zu vermeiden, da sonst die URL nicht mehr einer validen Syntax entspricht.

$param->{timeout}

optional

Die maximale Dauer in Sekunden bis der Server eine Antwort liefern muss. Andernfalls wird der Request mit einer Fehlermeldung abgebrochen.

Beispiel: 5 (Sekunden)

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 Zeichenkette:

  • Die Daten werden komplett als gesamte Zeichenkette in $param->{data} abgelegt (z.B.: $param->{data} = "Jede Menge tolle Daten").

2. Daten als Hash-Struktur:

  • Die Daten werden als Hash mit Key-Value-Pairs übergeben (z.B.: $param->{data}{field1} = "value1", $param{data}{field2} = "value2", ... ). Die Daten werden dann als Formulardaten mit mehrfachen Datenfeldern übertragen.

Standardwert: [leer]

$param->{user}

optional

Im Falle einer notwendigen HTTP-Authentifizierung, der zu benutzende Username um sich gegenüber dem Server zu identifizieren. Alternativ kann der Username und das Passwort auch direkt in der URL mitgegeben werden (siehe jedoch $param->{hideurl}).

Standardwert: [leer]

$param->{pwd}

optional

Im Falle einer notwendigen HTTP-Authentifizierung, das zu benutzende Passwort um sich gegenüber dem Server zu identifizieren. Alternativ kann der Username und das Passwort auch direkt in der URL mitgegeben werden (siehe jedoch $param->{hideurl}).

Standardwert: [leer]

$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.

Standardwert: 1

$param->{loglevel}

optional

Das Loglevel, in dem sämtliche Logmeldungen zu dieser HTTP-Abfrage erzeugt werden sollen.

Standardwert: 4

$param->{hideurl}

optional

Wenn dieser Parameter den Wert 1 trägt, wird die gesamte URL in sämtlichen Log-Ausgaben unkenntlich gemacht. Dies notwendig, wenn z.B. Zugangsdaten direkt in der URL angegeben wurden, oder die URL ein geheimes Token oder andere schützenswerte Informationen enthält.

Standardwert: 0

$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.

Standardwert: 0

$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.

Standardwert: "GET"

$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. Es gibt zwei Möglichkeiten, diesen Parameter zu befüllen.
  1. Als Zeichenkette. Mehrere Header-Zeilen müssen dabei mit "\r\n" getrennt werden.
  2. Als Hash-Struktur. Hierbei findet eine Zuordnung von Header-Bezeichnung zum Wert als Key-Value-Pair statt.

Beispiel:

  • "User-Agent: Mozilla/1.22\r\nContent-Type: application/xml"
  • "Content-Type: application/xml"
  • { "User-Agent" => "Mozilla/1.22", "Content-Type" => "application/xml" }
  • { "Content-Type" => "application/xml" }

Standardwert: [leer]

$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.

Beispiel:

  • $param->{sslargs} = { SSL_verify_mode => 0, sslOpt2 => 'sslVal2' }

Standardwert: { }

$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.

Standardwert: "1.0"

$param->{digest}

optional

Wenn dieser Parameter den Wert 1 trägt, wird bei vorhandenen Authentifizierungsdaten (Username+Passwort) eine Authentifizierung via Digest-Verfahren nach RFC 2617[1] erwartet. Die Anmeldedaten werden dann nur verwendet, wenn dieser explizit eine HTTP Digest Authentifizierung einleitet. Ist dieser Parameter nicht gesetzt (Wert: 0), wird bei vorhandenen Authentifizierungsdaten immer eine HTTP Basic[1] Authentifizierung im Request mitgeschickt.

Standardwert: 0

$param->{compress}

optional

Wenn dieser Parameter den Wert 1 trägt, wird dem Server die Verwendung von Komprimierung in Form GZIP oder alternativ Deflate[2] zur Übertragung der Antwort ermöglicht. Die komprimierte Antwort wird dabei direkt durch HttpUtils.pm wieder dekomprimiert. Wird dieser Parameter auf den Wert 0 gesetzt, so wird keine Komrpimierung ermöglicht.

WICHTIG: Die Verwendung von Komprimierung in HttpUtils.pm kann mit dem globalen Attribut "httpcompress" (Standardwert: 1) durch setzen auf 0 für die gesamte FHEM Installation durch den Nutzer deaktiviert werden. In diesem Fall ist der Parameter $param->{compress} = 1 wirkungslos.

Standardwert: 1

Als Rückgabewert von HttpUtils_BlockingGet wird ein Array mit zwei Rückgabewerten zurückgegeben:

($err, $data) = HttpUtils_BlockingGet( … )

Diese zwei Rückgabewerte 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.

Wenn kein Fehler aufgetreten ist, ist dieser Wert mit einem Leerstring gefüllt ($err = "")

$data Die Ergebnisdaten, welche der HTTP-Server zurückgeliefert hat. Die Daten werden als Klartext in Form eines gesamten Strings zurückgegeben.

Falls ein Fehler aufgetreten ist, ist dieser Wert mit einem Leersting gefüllt ($data = "")

HttpUtils_NonblockingGet

Info green.pngDie Funktion HttpUtils_NonblockingGet ist nicht komplett durchgehend "non-blocking". DNS-Abfragen sind weiterhin blockierend. Insbesondere wenn der DNS-Name nicht aufgelöst werden kann.

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.

Beispiel:

  • $param->{callback} = \&MyCallbackFn(Referenzzeiger auf Funktionsname)
  • $param->{callback} = sub(){ … }(direkte Funktionsdefinition)
$param->{incrementalTimeout}

optional

Sofern gesetzt (Wert: 1), wird der Timeout nach jedem Empfang von Teil-Daten wieder zurückgesetzt. So können größere Datenmengen von langsamen Sendern empfangen werden, ohne den Parameter timeout zu erhöhen und dadurch tatsächliche Verbindungsprobleme erst spät zu erkennen.

Standardwert: 0

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 im Rahmen der Modul-Programmierung wäre das $hash der aktuellen Definition. Alle gesetzten Parameter sind in der Callback-Funktion wieder über $param direkt abrufbar und können ausgewertet werden.

Beispiel:

  • $param->{hash} = $hash
  • $param->{command} = "on"

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:

  • $param->{redirects} - Die Anzahl an Umleitungen die erfolgte, bis die Anfrage beantwortet wurde.
  • $param->{url} - Die URL, die nach erfolgter Umleitung die Anfrage beantwortet hat.
  • $param->{protocol} - Das verwendete Protokoll, welches zur Abfrage verwendet wurde ("http" oder "https").
  • $param->{path} - Der Pfad, welcher auf dem HTTP-Server angefragt wurde.
  • $param->{host} - Der Name oder die IP-Adresse des HTTP-Servers.
  • $param->{httpheader} - Der gesamte HTTP Header, welcher der Server bei der letzten Antwort zurücklieferte.
  • $param->{code} - Der HTTP-Statuscode, mit dem die Anfrage vom Server beantwortet wurde.
  • $param->{addr} - Die HTTP-URL ohne Pfad und evtl. Authentifizerungsinformationen des HTTP-Servers (z.B. "http://myserver.com:8080").
  • $param->{auth} - Ein Flag (0/1) ob Zugangsdaten für den Request zur Verfügung standen (durch Angabe in der URL oder direkt in $param).
$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.

Wenn kein Fehler aufgetreten ist, ist dieser Wert mit einem Leerstring gefüllt ($err = "")

$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.

Falls ein Fehler aufgetreten ist, ist dieser Wert mit einem Leersting gefüllt ($data = "")

Die Callback-Funktion kann nun die Daten aus der HTTP-Antwort verarbeiten oder bei Fehlern 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_PerformHttpRequest($)
{
    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     => "User-Agent: TeleHeater/2.2.3\r\nAccept: application/json",                            # Den Header gemäß 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", 0);                                                        # 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, 0);                                                          # 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

Hilfsfunktionen

urlEncode

$encoded = urlEncode($string);

Die Funktion urlEncode() wandelt die übergebene Zeichenkette $string in eine URL-kompatible[3] Zeichenkette um. Der Rückgabewert $encoded ist eine Zeichenkette welche innerhalb einer URL verwendet werden kann, bspw. als Wert eines GET-Parameters.

Parameter:

Parameter Bedeutung
$string

mandatory

Die Zeichenkette, welche in eine URL-kompatible Form umgewandelt werden soll.

Rückgabewerte:

Rückgabewert Bedeutung
$encoded Die URL-kompatible Version der übergebenen Zeichenkette. Problematische Zeichen sind in diesem Wert durch ein Prozentzeichen gefolgt von der Hexadezimaldarstellung des Zeichens dargestellt.

Bsp:

  • "a: b" => "a%3a%20b"
  • "a/b" => "a%2fb"

urlDecode

$string = urlDecode($encoded);

Die Funktion urlDecode () normalisiert die übergebene Zeichenkette $encoded und ersetzt dabei sämtliche Hexadezimaldarstellungen[3] (eingeleitet mit einem Prozentzeichen) durch die entsprechenden Zeichen. Der Rückgabewert $string ist eine Zeichenkette welche keinerlei Hexadezimaldarstellungen mehr aufweist.

Parameter:

Parameter Bedeutung
$encoded

mandatory

Eine Zeichenkette, welche URL-kombatible Hexadezimaldarstellungen enthält.

Rückgabewerte:

Rückgabewert Bedeutung
$string Die normale Version der übergebenen Zeichenkette. Sämtliche Hexadezimalddarstellungen sind in ihre entsprechenden Zeichen umgewandelt.

Bsp:

  • "a%3a%20b" => "a: b"
  • "a%2fb" => "a/b"

Referenzen

  1. 1,0 1,1 RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication
  2. RFC 1951 - DEFLATE Compressed Data Format Specification version 1.3
  3. 3,0 3,1 RFC 3989 - Abschnitt 2.1 "Percent-Encoding"