Getting Started
Installation¶
Install the package via Composer:
You also need at least one supported HTTP library. The default driver uses PHP's built-in cURL extension, so if cURL is available you can start immediately. For other drivers, install the corresponding package:
# Guzzle
composer require guzzlehttp/guzzle
# Symfony HttpClient
composer require symfony/http-client
Requirements¶
- PHP 8.2 or higher
- JSON extension
- cURL extension (included by default in most PHP installations)
Sending Your First Request¶
Using the HTTP client involves three steps: create a client, build a request, and read the response.
use Cognesy\Http\Data\HttpRequest;
use Cognesy\Http\HttpClient;
$client = HttpClient::default();
$response = $client->send(new HttpRequest(
url: 'https://api.example.com/health',
method: 'GET',
headers: ['Accept' => 'application/json'],
body: '',
options: [],
))->get();
echo $response->statusCode(); // 200
echo $response->body(); // {"status":"ok"}
HttpClient::default() creates a client with the default cURL driver. The send() method returns a PendingHttpResponse, which is lazy -- the network call does not happen until you call get() or stream().
Choosing a Driver¶
If you want a specific driver, use a preset name or pass an HttpClientConfig:
Or construct the config explicitly:
use Cognesy\Http\Config\HttpClientConfig;
use Cognesy\Http\HttpClient;
$client = HttpClient::fromConfig(new HttpClientConfig(driver: 'guzzle'));
Or use the builder for more control:
use Cognesy\Http\Config\HttpClientConfig;
use Cognesy\Http\Creation\HttpClientBuilder;
$client = (new HttpClientBuilder())
->withConfig(new HttpClientConfig(
driver: 'symfony',
connectTimeout: 5,
requestTimeout: 30,
))
->create();
Error Handling¶
HTTP requests can fail for many reasons. Wrap your calls in a try-catch block:
use Cognesy\Http\Exceptions\HttpRequestException;
try {
$response = $client->send($request)->get();
} catch (HttpRequestException $e) {
echo "Request failed: {$e->getMessage()}\n";
if ($e->getResponse()) {
echo "Status: {$e->getResponse()->statusCode()}\n";
}
}
The exception hierarchy gives you granular control:
| Exception | When |
|---|---|
HttpRequestException |
Base class for all HTTP errors |
NetworkException |
Network-level failures |
ConnectionException |
Could not connect to the host |
TimeoutException |
Connect or request timeout exceeded |
HttpClientErrorException |
HTTP 4xx response (when failOnError is true) |
ServerErrorException |
HTTP 5xx response (when failOnError is true) |
CircuitBreakerOpenException |
Circuit breaker is open for the target host |
When failOnError is set to true in the config, the client throws typed exceptions for 4xx and 5xx responses automatically. When it is false (the default), you need to check the status code yourself.
Testing with Mocks¶
For tests, use the builder's withMock() method to supply predefined responses without making real HTTP calls:
use Cognesy\Http\Creation\HttpClientBuilder;
use Cognesy\Http\Data\HttpResponse;
$client = (new HttpClientBuilder())
->withMock(function ($mock) {
$mock->addResponse(
HttpResponse::sync(200, ['Content-Type' => 'application/json'], '{"ok":true}'),
url: 'https://api.example.com/health',
method: 'GET',
);
})
->create();
$response = $client->send(new HttpRequest(
url: 'https://api.example.com/health',
method: 'GET',
headers: [],
body: '',
options: [],
))->get();
echo $response->body(); // {"ok":true}
The mock driver matches responses by URL and method, making it straightforward to verify that your application sends the right requests.
What's Next¶
Now that you have a working client, explore the rest of the documentation:
- Making Requests -- learn about request construction, HTTP methods, headers, and bodies.
- Handling Responses -- read buffered content, inspect headers, and decode JSON.
- Streaming Responses -- consume chunked data as it arrives.
- Middleware -- add retry logic, circuit breakers, and custom behaviors.