Adapters

Adapters – Classes that actually perform the request

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.