HTTPlug Tutorial
This tutorial should give you an idea how to use HTTPlug in your project. HTTPlug has two main use cases:
Usage in your project;
Usage in a reusable package.
This tutorial will start with the first use case and then explain the special considerations to take into account when building a reusable package.
We use Composer for dependency management. Install it if you don’t have it yet.
Note
If you are using a framework, check the Framework Integrations to see if there is an integration available. Framework integrations will simplify the way you set up clients, letting you focus on handling the requests.
Setting up the Project
mkdir httplug-tutorial
cd httplug-tutorial
composer init
# specify your information as you want. say no to defining the dependencies interactively
composer require php-http/guzzle6-adapter
The last command will install Guzzle as well as the Guzzle HTTPlug adapter and the required interface repositories. We are now ready to start coding.
Writing Some Simple Code
Create a file demo.php
in the root folder and write the following code:
<?php
require('vendor/autoload.php');
use Http\Discovery\HttpClientDiscovery;
use Http\Discovery\MessageFactoryDiscovery;
$client = HttpClientDiscovery::find();
$messageFactory = MessageFactoryDiscovery::find();
$homeResponse = $client->sendRequest(
$messageFactory->createRequest('GET', 'http://httplug.io')
);
var_dump($homeResponse->getStatusCode()); // 200, hopefully
$missingPageResponse = $client->sendRequest(
$messageFactory->createRequest('GET', 'http://httplug.io/missingPage')
);
var_dump($missingPageResponse->getStatusCode()); // 404
Using an Asynchronous Client
Asynchronous client accepts a PSR-7 RequestInterface
and returns a Http\Promise\Promise
:
use Http\Discovery\HttpAsyncClientDiscovery;
$httpAsyncClient = HttpAsyncClientDiscovery::find();
$promise = $httpAsyncClient->sendAsyncRequest($request);
Using the Callback System
The promise allows you to add callbacks for when the response is available or an errors happens by using the then method:
$promise->then(function (ResponseInterface $response) {
// onFulfilled callback
echo 'The response is available';
return $response;
}, function (Exception $e) {
// onRejected callback
echo 'An error happens';
throw $e;
});
This method will return another promise so you can manipulate the response and/or exception and still provide a way to interact with this object for your users:
$promise->then(function (ResponseInterface $response) {
// onFulfilled callback
echo 'The response is available';
return $response;
}, function (Exception $e) {
// onRejected callback
echo 'An error happens';
throw $e;
})->then(function (ResponseInterface $response) {
echo 'Response still available';
return $response;
}, function (Exception $e) {
throw $e
});
In order to achieve the chain callback, if you read previous examples carefully,
callbacks provided to the then
method must return a PSR-7 ResponseInterface
or throw a Http\Client\Exception
.
For both of the callbacks, if it returns a PSR-7 ResponseInterface
it will call the onFulfilled
callback for
the next element in the chain, if it throws a Http\Client\Exception
it will call the onRejected
callback.
i.e. you can inverse the behavior of a call:
$promise->then(function (ResponseInterface $response) use($request) {
// onFulfilled callback
echo 'The response is available, but it\'s not ok...';
throw new HttpException('My error message', $request, $response);
}, function (Exception $e) {
// onRejected callback
echo 'An error happens, but it\'s ok...';
return $exception->getResponse();
});
Calling the wait
method on the promise will wait for the response or exception to be available and
invoke callback provided in the then
method.
Using the promise directly
If you don’t want to use the callback system, you can also get the state of the promise with $promise->getState()
will return of one Promise::PENDING
, Promise::FULFILLED
or Promise::REJECTED
.
Then you can get the response of the promise if it’s in FULFILLED
state or trigger the exception of the promise
if it’s in REJECTED
state with $promise->wait(true)
call.
Note
Read Promise for more information about promises.
Example
Here is a full example of a classic usage when using the sendAsyncRequest
method:
use Http\Client\Exception;
use Http\Discovery\HttpAsyncClientDiscovery;
$httpAsyncClient = HttpAsyncClientDiscovery::find();
$promise = $httpAsyncClient->sendAsyncRequest($request);
$promise->then(function (ResponseInterface $response) {
echo 'The response is available';
return $response;
}, function (Exception $e) {
echo 'An error happens';
throw $e;
});
// Do some stuff not depending on the response, calling another request, etc ..
...
try {
// We need now the response for our final treatment...
$response = $promise->wait(true);
} catch (Exception $e) {
// ...or catch the thrown exception
}
// Do your stuff with the response
...
Handling Errors
TODO: explain how to handle exceptions, distinction between network exception and HttpException.