phputility / async
A lightweight PHP library for asynchronous HTTP requests using curl_multi_* functions
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/phputility/async
Requires
- php: >=7.4
- ext-curl: *
Requires (Dev)
- phpstan/phpstan: ^1.0
- phpunit/phpunit: ^9.5 || ^10.0
- squizlabs/php_codesniffer: ^3.6
This package is not auto-updated.
Last update: 2025-10-17 14:43:39 UTC
README
A lightweight PHP library for asynchronous HTTP requests using native curl_multi_*
functions. No external dependencies required!
Features
- ๐ Asynchronous HTTP requests using
curl_multi_*
functions - ๐ Automatic fallback to synchronous requests if async is not available
- โก Concurrency control - limit the number of parallel requests
- ๐ฏ Simple API - clean and intuitive interface
- ๐ฆ Zero dependencies - uses only PHP built-in functions
- ๐ง Flexible configuration - custom headers, timeouts, and options
- ๐ Response objects - structured response handling
- ๐งช Well tested - comprehensive test suite included
Requirements
- PHP 7.4 or higher
- cURL extension enabled
Installation
composer require phputility/async
Or add it to your composer.json
:
{ "require": { "phputility/async": "^1.0" } }
Quick Start
Basic GET Requests
use Phputils\Async\HttpClient; $client = new HttpClient([ 'timeout' => 5, 'headers' => ['User-Agent: MyApp/1.0'] ]); $responses = $client->get([ 'https://api.github.com', 'https://httpbin.org/get', 'https://api.ransomfeed.it' ]); foreach ($responses as $url => $response) { echo "[$url] Status: " . $response['status'] . "\n"; echo "Body length: " . strlen($response['body']) . "\n\n"; }
POST Requests
$requests = [ ['url' => 'https://httpbin.org/post', 'body' => 'Hello World'], ['url' => 'https://httpbin.org/post', 'body' => '{"key": "value"}'] ]; $responses = $client->post($requests); foreach ($responses as $url => $response) { if ($response['status'] === 200) { echo "Success: $url\n"; } }
Using Request Objects
use Phputils\Async\Request; $requests = [ Request::get('https://api.example.com/data'), Request::post('https://api.example.com/create', '{"name": "test"}') ->addHeader('Content-Type', 'application/json'), Request::put('https://api.example.com/update/1', '{"status": "active"}') ]; $responses = $client->request('GET', $requests);
Advanced Usage
Concurrency Control
$client = new HttpClient([ 'concurrency' => 5, // Maximum 5 parallel requests 'timeout' => 10 ]); $urls = array_fill(0, 20, 'https://httpbin.org/delay/1'); $responses = $client->get($urls); // This will process 5 requests at a time, taking about 4 seconds total
Custom Headers and Options
$client = new HttpClient([ 'headers' => [ 'Authorization: Bearer token123', 'X-API-Version: v2' ], 'timeout' => 15 ]); // Override headers for specific requests $responses = $client->get(['https://api.example.com'], [ 'headers' => ['X-Custom: value'] ]);
Callback Function
$processedCount = 0; $callback = function ($url, $response) use (&$processedCount) { $processedCount++; echo "Processed $processedCount: $url - Status: {$response['status']}\n"; if ($response['status'] === 200) { // Process successful response $data = json_decode($response['body'], true); // ... handle data } }; $responses = $client->get($urls, ['callback' => $callback]);
Error Handling
$urls = [ 'https://httpbin.org/status/200', 'https://httpbin.org/status/404', 'https://invalid-domain.com' ]; $responses = $client->get($urls); foreach ($responses as $url => $response) { if (!empty($response['error'])) { echo "Error for $url: {$response['error']}\n"; } elseif ($response['status'] >= 400) { echo "HTTP Error for $url: {$response['status']}\n"; } else { echo "Success for $url: {$response['status']}\n"; } }
API Reference
HttpClient
Constructor
new HttpClient(array $options = [])
Options:
timeout
(int): Request timeout in seconds (default: 30)headers
(array): Default headers for all requestsconcurrency
(int): Maximum parallel requests (default: 10)callback
(callable): Callback function for each completed requestuser_agent
(string): User agent string (default: 'phputils-async/1.0')
Methods
get(array $urls, array $options = []): array
Execute GET requests asynchronously.
post(array $requests, array $options = []): array
Execute POST requests asynchronously.
request(string $method, array $requests, array $options = []): array
Execute requests with specified HTTP method.
isAsyncAvailable(): bool
Check if curl_multi_* functions are available.
Request
Static Methods
Request::get(string $url, array $headers = [], array $options = []): Request Request::post(string $url, string $body = null, array $headers = [], array $options = []): Request Request::put(string $url, string $body = null, array $headers = [], array $options = []): Request Request::delete(string $url, string $body = null, array $headers = [], array $options = []): Request
Instance Methods
$request->addHeader(string $name, string $value): Request $request->setBody(string $body): Request $request->setOption(string $key, mixed $value): Request $request->toArray(): array
Response
Properties
$status
(int|null): HTTP status code$headers
(array): Response headers$body
(string): Response body$error
(string|null): Error message$info
(array): Additional cURL info
Methods
$response->isSuccess(): bool // Check if status is 200-299 $response->toArray(): array // Convert to array format
Performance
Benchmark Example
$urls = array_fill(0, 10, 'https://httpbin.org/delay/1'); // Async execution $start = microtime(true); $asyncResponses = $client->get($urls); $asyncTime = microtime(true) - $start; // Sequential execution $start = microtime(true); $sequentialClient = new HttpClient(['concurrency' => 1]); $sequentialResponses = $sequentialClient->get($urls); $sequentialTime = microtime(true) - $start; echo "Async time: " . round($asyncTime, 2) . "s\n"; echo "Sequential time: " . round($sequentialTime, 2) . "s\n"; echo "Speed improvement: " . round($sequentialTime / $asyncTime, 2) . "x\n";
Typical results:
- Async: ~1.2 seconds
- Sequential: ~10.1 seconds
- Speed improvement: ~8.4x faster
Testing
Run the test suite:
composer test
Run with coverage:
composer test-coverage
Run code quality checks:
composer quality
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
1.0.0
- Initial release
- Async HTTP requests with curl_multi_*
- Concurrency control
- Request/Response objects
- Comprehensive test suite
- Zero external dependencies
Support
If you encounter any issues or have questions, please:
- Check the Issues page
- Create a new issue with detailed information
- For questions, use the Discussions page
Made with โค๏ธ by the Nuke{} (Ransomfeed team)