Adapters
Overview
Adapters in HTTP_Request2 package are classes responsible for establishing the actual connection to the remote server, writing requests and reading responses. Adapter can be set either via a configuration parameter (see: Configuration) or by HTTP_Request2::setAdapter() method.
The package currently contains three adapters:
- HTTP_Request2_Adapter_Socket
This Adapter uses PHP's builtin stream_socket_client() function and does not require any special extensions or configuration. Note that this is a pure PHP implementation of HTTP protocol, it does not use
http
stream wrapper.This is the default Adapter, it will be used by HTTP_Request2 unless you explicitly set the other one.
- HTTP_Request2_Adapter_Curl
Curl adapter wraps around PHP's cURL extension and thus allows using extremely sophisticated cURL library. It is a good choice if you have cURL extension available in PHP.
- HTTP_Request2_Adapter_Mock
This adapter allows testing packages and applications using HTTP_Request2 without depending on a network connection and remote server availability.
You can replace the default adapter in HTTP_Request2 by an instance of HTTP_Request2_Adapter_Mock populated via its HTTP_Request2_Adapter_Mock::addResponse() method. The adapter will return prepared responses or throw prepared exceptions when its sendRequest() method is called.
Other adapters may be created by subclassing an abstract HTTP_Request2_Adapter class and implementing its HTTP_Request2_Adapter::sendRequest() method.
Socket Adapter Issues
Due to PHP bug
#47030 ssl_verify_host
configuration parameter is useless without
ssl_verify_peer
. When the latter is switched off no host validation
will be performed.
Curl Adapter Issues
When doing a POST
request with file uploads or reading the request body from
file, HTTP_Request2 streams files from disk to reduce memory consumption
and to allow monitoring the request progress. This is done by setting up a
CURLOPT_READFUNCTION callback. PHP does not allow setting another callback,
CURLOPT_IOCTLFUNCTION (see PHP bug #47204) so the request body can not be
"rewound" when another request should be performed. Thus a request with a non-empty
body to a resource protected by Digest authentication or to a page that does a redirect when
follow_redirects
is enabled will fail.
Since release 0.5.0 HTTP_Request2 works around this problem by reading the whole request body into memory. Of course this may be an issue when the request body is huge, so consider using Socket Adapter.
Setting strict_redirects
configuration parameter to TRUE will only have
effect on Curl Adapter if CURLOPT_POSTREDIR (see PHP bug #49571) is available in cURL extension.
It is available in PHP 5.3.2 and higher.
Using Mock adapter
HTTP_Request2_Adapter_Mock::addResponse() method can accept either a HTTP response (instance of HTTP_Request2_Response, a string, a pointer to an open file) or an Exception. The latter may be useful to test that your application degrades gracefully when the remote server is not available due to some network problems. Several responses may be added via addResponse() to simulate a HTTP transaction consisting of multiple requests and responses. They will be returned by the Adapter in the order they were added.
Since release 2.1.0 it is possible to specify a request URL to addResponse(). sendRequest() will only return responses without an explicit URL set or having the same URL as the request. It is recommended that you set explicit URLs either for all responses or for none of them, otherwise the behaviour will be difficult to predict.
Returning responses and throwing exceptions
<?php
require_once 'HTTP/Request2.php';
require_once 'HTTP/Request2/Adapter/Mock.php';
$mock = new HTTP_Request2_Adapter_Mock();
$mock->addResponse(
"HTTP/1.1 200 OK\r\n" .
"Connection: close\r\n" .
"\r\n" .
"Explicit response for example.org",
'http://example.org/'
);
$mock->addResponse(
"HTTP/1.1 200 OK\r\n" .
"Content-Length: 32\r\n" .
"Connection: close\r\n" .
"\r\n" .
"Nothing to see here, move along."
);
$mock->addResponse(
new HTTP_Request2_Exception("The server is on fire!")
);
// this request will succeed
$request1 = new HTTP_Request2(
'http://ok.example.com/', HTTP_Request2::METHOD_GET,
array('adapter' => $mock)
);
echo "Response: " . $request1->send()->getBody() . "\r\n";
// this request will fail
$request2 = new HTTP_Request2('http://burning.example.com/');
$request2->setAdapter($mock);
try {
echo "Response: " . $request2->send()->getBody() . "\r\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\r\n";
}
// The response for example.org was ignored by previous requests
$requestOrg = new HTTP_Request2(
'http://example.org/', HTTP_Request2::METHOD_GET,
array('adapter' => $mock)
);
echo "Response: " . $requestOrg->send()->getBody() . "\r\n";
?>
The above code will output:
Response: Nothing to see here, move along.
Error: The server is on fire!
Response: Explicit response for example.org
Mock Adapter also has two static helper methods HTTP_Request2_Adapter_Mock::createResponseFromString() and HTTP_Request2_Adapter_Mock::createResponseFromFile() which build HTTP_Request2_Response objects from either a string containing the complete HTTP response or a pointer to an open file with such response, respectively.