gemz / http-client
Gemz Http Client is a simple Symfony Http-Client wrapper to provide an easy development experience for most use cases.
Fund package maintenance!
Patreon
Requires
- php: ^7.2.5
- illuminate/support: ^5.8|^6.0|^7.0
- symfony/http-client: ^5.0
- symfony/mime: ^5.0
Requires (Dev)
- mockery/mockery: ^1.0
- phpstan/phpstan: ^0.12.8
- phpunit/phpunit: ^8.2
- symfony/var-dumper: ^4.3
README
Gemz Http Client is a thin Symfony Http-Client wrapper to provide an easy development experience for most use cases. Comes with easy to use asynchronous and concurrent requests.
If you need more functionality, just use Guzzle or Symfony clients.
Installation
You can install the package via composer:
composer require gemz/http-client
Basic Usage
use Gemz\HttpCLient\Client; $client = Client::create(); // get request $response = $client->get('https://myapi.com/users'); // json post request $response = $client ->payload(['name' => 'John']) ->post('https://myapi.com/users'); // query url parameters $response = $client ->queryParam('page', 20) ->get('https://myapi.com/users'); // calls https://myapi.com/users?page=20
Client Initialization
You can configure the client with initial values. Configuration options are valid for all requests made with the client object unless you override the options in the request itself.
use Gemz\HttpCLient\Client; use Gemz\HttpCLient\Config; // Basic client with no config options $client = Client::create(); $client = new Client(); // Client with config options $config = Config::make() ->header('API-KEY', 'yourkey') ->baseUri('https://myapi.com'); $response = Client::create($config)->get('users');
All possible options are identical in configuration and request. If you use the same option in config and the request, the request option will override the config option.
That is great when you have to use different options in some requests other than in the config.
$client = Client::create(Config::make()->header('X-KEY', 'yourkey')); $response = $client->header('X-KEY', 'otherkey')->get('users');
Default Settings
There are some default settings:
- Content-Type : 'application/json'
- All requests are made
asynchronous
- Max Redirects 20
- Timeout defaults to ini_get('default_socket_timeout')
- Max Duration 0 means unlimited
Configuration And Request Options
// Authentication $client->authBasic('username', 'password'); $client->authBearer('token'); // Headers $client->header('key', 'value'); $client->headers(['key' => 'value']); // User-Agent $client->userAgent('userAgent'); // Query Parameters $client->queryParam('key', 'value'); $client->queryParams(['key1' => 'value1']); // will result in ...?key=value&key1=value1 // Timeout in seconds $client->timeout(10); // Max Redirects // 0 means unlimited $client->allowRedirects(3); $client->doNotAllowRedirects(); // Max Request <-> Response Duration // in seconds $client->maxDuration(30); // Throw errors if response status code is >= 400 $client->throwErrors(); // Content-Types $client->contentType('contentType'); $client->asJson(); $client->asFormParams(); $client->asPlain(); $client->asMultipart(); // Multipart form data will automatically transformed in the correct format // throws an exception if content-type and payload does not match $client->payload(['key' => 'value']); $client->payload('my message'); // payload for multipart $client->payload([ 'key' => 'value', 'file_field' => Client::fileHandler('pathToFile') ]); // without verifing ssl // Default is verifing $client->doNotVerifySsl(); $client->verifySsl(); // Proxy $client->useProxy('tcp://...'); // Methods // Endpoint can also be an URI $client->get('users/1'); $client->get('https://myapi.com/users/1'); $client->post('users'); $client->put('users/1'); $client->patch('users/1'); $client->head('users/1'); $client->delete('users/1'); // Setting Symfony Specific Client Options $client->option('<key', '<value');
You can also pass custom data to the request that will be available on the response. This is specially useful in multiple parallel requests to identify the origin request in the response.
// can be string, array, object .... $client->customData(['id' => 182736283]); // in response $response->customData(); // outputs ['id' => 182736283]
Response
Requests are fully asynchronous unless you read the content, headers or status code of the response
$response = $client->get('users/1'); // Content Access $response->asArray(); // if content is json $response->asObject(); // if content is json $response->asCollection(); // if content is json - illuminate collection $response->asString(); $response->asStream(); // php resource $response->body(); // Status Code $response->status(); // integer $response->isOk(); // true / false 200 - 299 $response->isSuccess(); // true / false 200 - 299 $response->isRedirect(); // true / false 300 - 399 $response->isClientError(); // true / false 400 - 499 $response->isServerError(); // true / false 500 - 599 // Headers $response->header('content-type'); $response->headers(); $response->contentType(); $response->isJson(); // true / false // Request Url $response->requestUrl(); // Execution Time request <-> response $response->executionTime(); // Custom Data // Data from request custom data $response->customData(); // response infos // returns info coming from the transport layer, such as "response_headers", // "redirect_count", "start_time", "redirect_url", etc. $response->info(); // symmfony response object $response->response();
Asynchronous And Concurrent Requests
Since all requests are asynchronous, you can put requests in an array and get the response later. In this case the foreach loop get responses in order of the requests.
$client = Client::create(); $responses = []; $responses[] = $client->get('users/1'); $responses[] = $client->get('users/2')); $responses[] = $client->get('users/3'); // responses are in order of the requests foreach ($responses as $response) { echo $response->status()); }
If you do have a lot of requests, this approach is much better and
faster. The order of the responses is then independent of the request order. This is fully asynchronous
.
$client = Client::create(); $responses = []; for ($i = 1; $i < 300; $i++) { $responses[] = $client // using custom data to identify the request in the response ->customData('id:' . $i) ->get("users/{$i}"); } // Using the Stream Object to access the responses foreach ($client->stream($responses) as $response => $chunk) { Stream::from($response, $chunk) ->then(function (Response $response) { // success - do something with the response echo $response->customData() }) ->timeout(function (Response $response) { // timeout - do something with the response }) ->catch(function ($exception, Response $response) { // exception was thrown }); }
Stream Response And Chunk
Using the stream object is the fastest way to receive responses. You can listen to these events:
use Gemz\HttpClient\Stream; foreach ($client->stream($response) as $response => $chunk) { $stream = Stream::for($response, $chunk); // fulfilled // callable must use response $stream->then(/* callable */); // timeout // callable must use response $stream->timeout(/* callable */); // rejected // callable must use exception, response $stream->catch(/* callable */); }
Testing
composer test
composer phpstan
composer test-coverage
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security
If you discover any security related issues, please email stefan@sriehl.com instead of using the issue tracker.
Credits
Support us
Gemz.io is maintained by Stefan Riehl. You'll find all open source projects on Gemz.io github.
License
The MIT License (MIT). Please see License File for more information.