HTTP Clients: WinInet und libCURL

In Visual Basic 6 war auch die nicht-grafische Programmierung “grafisch”. Es ist logisch, dass man einen Button oder ein Textfeld auf eine Fensterform zieht, aber dass man eine “Internetverbindung” auch wie einen Button auf einem Fenster ablegt, finde ich bis heute “merkwürdig”.

Dieses alte VB6 ActiveX “Internet Transfer Control” war nichts weiter als ein Wrapper um die WinInet Komponente, also DIE HTTP Komponente von Windows, die mit dem Internet Explorer 2 und 3 schon unter Windows NT 4 und Windows 95 eingeführt wurde.

Heute ist diese alte C-API neben dem modernen WinHTTP parallel zur libcURL unter Unix Systemen für mich die primäre Anlaufstelle, wenn Programme per HTTP(S) Daten aus dem Netzwerk laden möchten.

Um ehrlich zu sein bin ich mit überhaupt keiner API wirklich glücklich. Denn alle haben sie Seiteneffekte und Unschönheiten, die oft in umständlichen Workarounds münden.

Also fassen wir mal das Negative zusammen:

WinINET

Diese uralte Schnittstelle ist zwar stabil und bis ins vergangene Jahrtausend kompatibel, doch sie wurde eben primär für den Internet Explorer entwickelt. Das Anzeigen von Dialogen, wenn etwas nicht passt, ist hier Standard und muss oft erst per Code abgeschaltet werden.

Ein anderer lästiger Punkt sind teilweise Probleme, wenn die Schnittstelle in Service-Prozessen läuft. Denn als IE Bibliothek werden Cookies und temporäre Dateien im Profil-Verzeichnis des Benutzers abgelegt.
Doch ein Service läuft in der Regel ohne Benutzer … oder noch schlimmer, es kann im laufenden Betrieb auf den Anmeldekontext eines Benutzers wechseln.

Und somit wird es zu einer Grauzone, ob “globale” Proxy-Server Einträge oder Verbindungslimits korrekt sind, ob eine Einstellung nun geladen wird oder nicht. Und wo Dateien angelegt werden lässt sich dann ebenso nicht mehr so einfach per Code beeinflussen.

WinHTTP

WinHTTP wiederum wurde als Alternative für WinINET so um das Jahr 2000 eingeführt und sollte primär für Dienste (Services) zur Verfügung stehen.

Das ist einerseits toll für reine Dienste, führt aber dazu, dass die Bibliothek im normalen Benutzermodus wieder lückenhaft wird.

Das gilt dann für solche Spezialitäten wie die Anmeldung an Windows-Webdiensten über NTLM, wo die nützliche Zwischenspeicherung von Anmeldedaten nicht oder unvollständig funktioniert.

Die Unterstützung von älteren Proxy-Servern wie SOCKS4 fehlt auch … wobei man das heute nicht mehr als Manko anmerken kann.
Oder kennt diese uralte Protokoll über noch jemand außer mir 😀 ?

libcurl

Die libcurl wäre als portables OpenSource Projekt theoretisch der Heilsbringer unter den Bibliotheken, doch leider befriedigt auch sie mich nicht. Wegen ihrer Abhängigkeit zu zahlreichen anderen Bibliotheken ist das cURL Projekt so gut wie gar nicht als statische Bibliothek einsetzbar.

Als dynamisch geteilte Komponente muss sie auf dem Zielsystem korrekt integriert sein, so wie auch alle ihre Abhängigkeiten. Und dass sind nicht nur OpenSSL, sondern auch SSH2 und einiges mehr. Fehlt ein Teil, funktioniert der ganze Rest auch nicht.

Denn CURL ist nicht nur eine HTTP Bibliothek sondern eine Protokoll-Sammelstelle für FTP, SFTP, IMAP u.s.w.

Am störendsten empfinde ich aber den API-Aufbau, der auf Callbacks zum Empfang der Daten setzt. Damit ist es schwierig die Funktionen durch einen Stream-Wrapper zu kapseln.

Und die eigene Implementierung

Jaaaa … so schwer ist das HTTP Protokoll ja nicht, das kann man auch selbst implementieren … glaubt man anfangs.

Für Server mag das teilweise zutreffend sein, wenn man nur wenige Features braucht. Doch Clients zu programmierern, die mit allen möglichen Server-Spezialitäten konfrontiert werden, ist der größte Alptraum, und spätestens, wenn es mit Authentifizierung, Verschlüsselung und HTTP/2 losgeht, kann man sich schnell von der “coolen” Idee verabschieden, dass man es selber besser machen kann.

Fazit

Weil HTTP so eine weite und vor allem unterschiedliche Verbreitung hat, sind HTTP Client Bibliotheken alles andere als leicht zu schreiben und keine kann wirklich alles.
Auch dotNet und JAVA haben hier ihre Limits.

Folglich muss ich am Ende dennoch sagen, dass die 3 genannten Bibliotheken Meisterwerke sind, deren “seltsame” Besonderheiten erst bei speziellen Anforderungen sichtbar werden.

Natürlich hätte ich mir eine gemeinsame Übermenge gewünscht, die “alles” kann, Open-Source ist und hoch performant in allen Lebenslagen agiert, doch …
… man kann eben nicht alles haben.

Meine Entscheidung bleibt daher: WinINET für Windows, libCURL für Linux. Und alles wird am Ende dann doch noch gut ausgehen.


Wenn sich eine triviale Erkenntnis mit Dummheit in der Interpretation paart, dann gibt es in der Regel Kollateralschäden in der Anwendung.
frei zitiert nach A. Van der Bellen
... also dann paaren wir mal eine komplexe Erkenntnis mit Klugheit in der Interpretation!