Zend_Http_Client - Verbindungsadapter
Verbindungsadapter
Zend_Http_Client basiert auf einem Design mit Verbindungsadaptern. Der
Verbindungsadapter ist das Objekt, welches für die Ausführung der aktuellen Verbindung
zum Server sowie für das Schreiben der Anfragen und Lesen von Antworten verantwortlich
ist. Dieser Verbindungsadapter kann ersetzt werden und man kann den Standard
Verbindungsadapter durch seinen eigenen Adapter erweitern, um ihn mit dem selben
Interface auf seine eigenen Bedürfnisse anzupassen, ohne dass man die gesamte HTTP
Client Klasse erweitern oder ersetzen muss.
Derzeit stellt die Zend_Http_Client Klasse zwei eingebaute Verbindungsadapter bereit:
Zend_Http_Client_Adapter_Socket (Standard)
Zend_Http_Client_Adapter_Proxy
Zend_Http_Client_Adapter_Test
Zend_Http_Client_Adapter_Curl
Der Verbindungsadapter für das Zend_Http_Client Objekt wird durch Verwendung der
'adapter' Konfigurationsoption gesetzt. Beim Instanzieren des Client Objektes kann man
die 'adapter' Konfigurationsoption setzen mit einem String, der den Adapternamen (z.B.
'Zend_Http_Client_Adapter_Socket') enthält, oder mit eine Variable, die ein
Adapterobjekt (z.B. new Zend_Http_Client_Adapter_Test) enthält. Man kann
den Adapter auch danach setzen, indem man die Zend_Http_Client->setConfig() Methode
verwendet.
Der Socket Adapter
Der Standard-Adapter von Zend_Http_Client ist der Zend_Http_Client_Adapter_Socket.
Dieser wird benutzt, wenn kein anderer angegeben wird. Der Socket Adapter benutzt die
native PHP Funktion fsockopen(), um die Verbindung aufzubauen, dafür werden keine
besonderen PHP-Extensions oder Einstellungen benötigt.
Der Socket Adapter erlaubt verschiedene zusätzliche Konfigurations Optionen die gesetzt
werden können durch Verwendung von Zend_Http_Client->setConfig()
oder deren Übergabe an den Konstruktor des Clients.
Zend_Http_Client_Adapter_Socket Konfigurations Parameter
Parameter
Beschreibung
Erwarteter Typ
Standardwert
persistent
Ob eine persistente TCP Verbindung verwendet werden soll oder nicht
boolean
false
ssltransport
SSL Transport Layer (eg. 'sslv2', 'tls')
string
ssl
sslcert
Pfad zu einem PEM verschlüsselten SSL Zertifikat
string
null
sslpassphrase
Die PassPhrase für die SSL zertifizierte Datei
string
null
Persistente TCP Verbindungen
Die Verwendung persistenter TCP Verbindungen kann HTTP Anfragen potentiell
schneller machen - aber in den meisten Fällen, wird es nur einen kleinen
positiven Effekt haben und könnte den HTTP Server überladen zu dem man sich
verbindet.
Es wird empfohlen persistente TCP Verbindungen nur dann zu verwenden wenn man
sich zu dem gleichen Server sehr oft verbindet, und man sicher ist das der
Server eine große Anzahl an gleichzeitigen Verbindungen behandeln kann. In jedem
Fall wird empfohlen das der Effekt von persistenten Verbindungen auf beiden, der
Geschwindigkeit des Clients und dem Serverload gemessen wird bevor diese Option
verwendet wird.
Zusätzlich, wenn persistente Verbindungen verwendet werden, sollte man
Keep-Alive HTTP Anfragen aktivieren wie in beschrieben - andernfalls werden
persistente Verbindungen nur wenig oder gar keinen Effekt haben.
HTTPS SSL Stream Parameter
ssltransport, sslcert und sslpassphrase sind nur
relevant wenn HTTPS für die Verbindung verwendet wird.
Wärend die Standard SSL Einstellungen für die meisten Anwendungen funktionieren,
kann es notwendig sein diese zu Ändern wenn der Server zu dem man sich verbindet
ein spezielles Client Setup benötigt. Wenn dem so ist, sollte man das Kapitel
über SSL Transport Layer und Optionen lesen das hier
zu finden ist.
Den Stream-Typen für eine HTTPS Verbindung einstellen
'Zend_Http_Client_Adapter_Socket',
'ssltransport' => 'tls'
);
// Client-Instanz erzeugen
$client = new Zend_Http_Client('https://www.example.com', $config);
// Jetzt wird der Request über eine verschlüsselte Verbindung verschickt
$response = $client->request();
]]>
Ein ähnliches Ergebnis erzielt man mit folgendem Code:
fsockopen('tls://www.example.com', 443)
Der Proxy Adapter
Der Proxy Adapter Zend_Http_Client_Adapter_Proxy verhält sich wie der
standard Zend_Http_Client_Adapter_Socket, mit dem Unterschied, dass
die Verbindung über einen Proxy-Server aufgebaut wird.
Der Proxy Adapter benötigt zusätzliche Konfigurationsvariablen, die
nachfolgend gelistet sind.
Zend_Http_Client Konfigurationsparameter
Parameter
Beschreibung
Datentyp
Beispielwert
proxy_host
Proxy-Server-Adresse
string
'proxy.myhost.com' oder '10.1.2.3'
proxy_port
TCP Port des Proxy-Servers
integer
8080 (Standardwert) oder 81
proxy_user
Benutzername für die Proxynutzung, falls nötig
string
'wulli' oder '' für keinen Namen (Standardwert)
proxy_pass
Passwort für die Proxynutzung, falls nötig
string
'geheim' oder '' für kein Passwort (Standardwert)
proxy_auth
Proxy HTTP Authentifizierungs-Typ
string
Zend_Http_Client::AUTH_BASIC (Standardwert)
proxy_host muss immer gesetzt werden, ansonsten wird der Proxy-Adapter
auf Zend_Http_Client_Adapter_Socket zurückgreifen und keinen Proxy Server
benutzen.
Wird kein Prot mit übergeben, so versucht der Proxy-Adapter sich auf den
Standardport '8080' zu verbinden.
proxy_user und proxy_pass werden nur dann benötigt, wenn der Proxy-Server
tatsächlich eine Authentifizierung erwartet. Werden diese Parameter mit
übergeben, setzt der Proxy-Adapter zusätzlich den 'Proxy-Authentication'
Header bei Anfragen. Wird keine Authentifizierung benötigt, sollten die
beiden Parameter weggelassen werden.
proxy_auth setzt den Authentifizierungs-Typ. Dies ist nur nötig, wenn der
Proxy-Server eine Authentifizierung erwartet.
Mögliche Werte entsprechen denen der Zend_Http_Client::setAuth() Methode.
Zur Zeit wird nur die BASIC-Authentifizierung
((Zend_Http_Client::AUTH_BASIC) unterstützt.
Zend_Http_Client hinter einem Proxy-Server nutzen
'Zend_Http_Client_Adapter_Proxy',
'proxy_host' => 'proxy.int.zend.com',
'proxy_port' => 8000,
'proxy_user' => 'shahar.e',
'proxy_pass' => 'bananashaped'
);
// Client-Objekt instanziieren
$client = new Zend_Http_Client('http://www.example.com', $config);
// $client kann jetzt wie gewohnt benutzt werden
]]>
Wie vorher erwähnt, nutzt der Proxy-Adapter eine einfache Socket-Verbindung,
wenn proxy_host nicht gesetzt oder leer gelassen wurde. Dies ermöglicht
die optionale Nutzung eines Proxy-Servers, abhängig von dem proxy_host
Parameter.
Der Test Adapter
Manchmal ist es sehr schwer Code tu testen, der von HTTP Verbindungen abhängig ist.
Zum Beispiel verlangt das Testen einer Applikation, die einen RSS Feed von einem fremden
Server anfordert, eine Netzwerkverbindung, die nicht immer verfügbar ist.
Aus diesem Grund wird der Zend_Http_Client_Adapter_Test Adapter bereit gestellt. Man
kann seine eigenen Applikationen schreiben, um Zend_Http_Client zu verwenden, und nur
zu Testzwecken, z.B. in der Unit Test Suite, den Standardadapter durch den Testadapter
(ein Mock Objekt) austauschen, um Tests ohne direkte Serverbindungen auszuführen.
Der Zend_Http_Client_Adapter_Test Adapter stellt die zusätzliche Methode setResponse()
bereit. Diese Methode nimmt einen Parameter entgegen, der eine HTTP Antwort entweder als
Text oder als Zend_Http_Response Objekt repräsentiert. Einmal eingerichtet, wird der
Testadapter immer diese Antwort zurückgeben, ohne tatsächlich eine HTTP Anfrage
auszuführen.
Testen gegen einen einfachen HTTP Response Stumpf
$adapter
));
// Setze die erwartete Antwort
$adapter->setResponse(
"HTTP/1.1 200 OK" . "\r\n" .
"Content-type: text/xml" . "\r\n" .
"\r\n" .
'' .
'' .
' ' .
' Premature Optimization' .
// und so weiter...
'');
$response = $client->request('GET');
// .. setze die Verarbeitung von $response fort...
]]>
Das obere Beispiel zeigt, wie man einen HTTP Client voreinstellen kann, damit er die
benötigte Antwort zurückgibt. Danach kann man mit den Testen des eigenen Codes weiter
machen, ohne von einer Netzwerkverbindung, der Serverantwort, etc. abhängig zu sein. In
diesem Fall würde der Test mit der Prüfung fortfahren, wie die Applikation das XML aus
der Antwort verarbeitet..
Manchmal erfordert ein einziger Methoden-Aufruf mehrere HTTP-Übertragungen.
Um mehrere HTTP-Antworten zu erstellen, müssen mit setResponse() die erste
und mit addResponse() die nachfolgenden Antworten gesetzt werden.
Test mit mehreren HTTP-Antworten
$adapter
));
// mit setResponse() die erste Antwort setzen
$adapter->setResponse(
"HTTP/1.1 302 Found" . "\r\n" .
"Location: /" . "\r\n" .
"Content-Type: text/html" . "\r\n" .
"\r\n" .
'' .
' Moved' .
' This page has moved.
' .
'');
// mit addResponse() nachfolgende Antworten setzen
$adapter->addResponse(
"HTTP/1.1 200 OK" . "\r\n" .
"Content-Type: text/html" . "\r\n" .
"\r\n" .
'' .
' Meine Haustierseite' .
' ...
' .
'');
// Das $client Objekt kann jetzt zu testzwecken herangezogen werden,
// indem es wie ein normales Client-Objekt benutzt wird.
]]>
Die HTTP-Antworten werden in der Reihenfolge zurückgegeben,
in der sie angelegt worden sind. Gibt es mehr Anfragen als
Antworten, so wird wieder bei der ersten Antwort angefangen.
Das oben angeführte Beispiel kann dazu benutzt werden, um die Reaktion
der eigenen Anwendung auf einen 302 Redirect (Weiterleitung) zu testen.
Abhängig von Ihrer Anwendung, kann es gewollt oder nicht gewollt sein,
dass dem Redirect gefolgt wird.
Der cURL Adapter
cURL ist eine Standard HTTP Client Bibliothek die mit vielen Betriebssystemen
ausgeliefert wird, und kann in PHP über die cURL Erweiterung verwendet werden.
Sie bietet Funktionalitäten für viele spezielle Fälle die für einen HTTP Client
auftreten können und machen sie zu einer perfekten Wahl für einen HTTP Adapter.
Sie unterstützt sichere Verbindungen, Proxies, alle Arten von Authentifizierungs-
mechanismen und glänzt in Anwendungen die große Dateien zwischen Servern bewegen
müssen.
Setzen von cURL Optionen
'Zend_Http_Client_Adapter_Curl',
'curloptions' => array(CURLOPT_FOLLOWLOCATION => true),
);
$client = new Zend_Http_Client($uri, $config);
]]>
Standardmäßig ist der cURL Adapter so konfiguriert das er sich genauso wie der
Socket Adapter verhält. Man kann die cURL Optionen entweder durch den
'curloptions' Schlüssel im Konstruktor des Adapters, oder durch den Aufruf von
setCurlOption($name, $value), verändern. Der $name
Schlüssel entspricht den CURL_* Konstanten der cURL Erweiterung.
Dateien von Hand übertragen
Man kan cURL verwenden um große Dateien über HTTP durch einen Dateihandle zu
übertragen.
setAdapter($adapter);
$adapter->setConfig(array(
'curloptions' => array(
CURLOPT_INFILE => $putFileHandle,
CURLOPT_INFILESIZE => $putFileSize
)
));
$client->request("PUT");
]]>
Einen eigenen Adapter erstellen
Es ist möglich eigene Verbindungs-Adapter zu schreiben, die spezielle
Bedürfnisse, wie persistente Sockets oder gecachte Verbindungen, abdecken.
Diese können dann, wie gewohnt mit dem Zend_Http_Client benutzt werden.
Um einen neuen Adapter zu erstellen, muss eine neue Klasse angelegt werden,
die das Zend_Http_Client_Adapter_Interface implementiert. Nachfolgend
finden Sie ein Gerüst für einen neuen Adapter. Die public-Methoden müssen
unbedingt implementiert werden.
Gerüst für einen eigenen Verbindungs-Adapter
'MyApp_Http_Client_Adapter_BananaProtocol'
));
]]>