Skip to main content
Version: CANARY 🚧

HTTP Client

Introduction​

The BowPHP HTTP client is a powerful and flexible component for making HTTP requests to APIs or remote services. It uses the cURL library to provide advanced features while keeping them simple to use.

Key features​

  1. Supported HTTP methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS.
  2. Custom header management.
  3. Support for attached files in multipart/form-data requests.
  4. Native JSON encoding of data.
  5. Definition of a base URL (base_url) to simplify managing API endpoints.
  6. Built-in authentication (Basic, Bearer, HTTP Auth).
  7. Timeout configuration and SSL verification.
  8. Error handling with specific exceptions.

Usage​

To use the HTTP client, simply create a new instance or inject it into a service or controller:

use Bow\Http\Client\HttpClient;

$client = new HttpClient();
info

The constructor accepts an optional $base_url parameter. If the base URL is set, calling endpoints becomes simpler:

$client = new HttpClient('https://api.example.com');
tip

If you did not set the base URL when creating the instance, use setBaseUrl to do it later:

$client->setBaseUrl('https://api.example.com');

HTTP methods​

get​

Performs a GET request to retrieve resources.

Parameters:

  • $url: The relative path or full URL
  • $data: Array of parameters appended to the URL as a query string

Returns: A Response instance

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client->get('/users', ['page' => 2, 'limit' => 10]);

echo $response->getContent();
// Access the JSON data
$users = $response->toArray();

post​

Performs a POST request to create or send data.

Parameters:

  • $url: The relative path or full URL
  • $data: Array of data to send (JSON or form-urlencoded depending on the configuration)

Returns: A Response instance

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client->acceptJson()->post('/users', [
'name' => 'John Doe',
'email' => 'john.doe@example.com',
'role' => 'admin'
]);

// Check for success
if ($response->isSuccessful()) {
$user = $response->toArray();
echo "User created with ID: {$user['id']}";
}

put​

Performs a PUT request to update an existing resource.

Parameters:

  • $url: The relative path or full URL
  • $data: Array of data to send for the update

Returns: A Response instance

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client->acceptJson()->put('/users/123', [
'name' => 'Jane Doe',
'email' => 'jane.doe@example.com'
]);

if ($response->isSuccessful()) {
echo "User updated successfully";
}

delete​

Performs a DELETE request to remove a resource.

Parameters:

  • $url: The relative path or full URL
  • $data: Array of optional data to send

Returns: A Response instance

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client->delete('/users/123');

if ($response->isSuccessful()) {
echo "User deleted successfully";
}

patch​

Performs a PATCH request to partially update a resource.

Parameters:

  • $url: The relative path or full URL
  • $data: Array of data to send for the partial update

Returns: A Response instance

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client->acceptJson()->patch('/users/123', [
'email' => 'newemail@example.com'
]);

if ($response->isSuccessful()) {
echo "Email updated successfully";
}

Performs a HEAD request to retrieve only the HTTP headers, without the response body. Useful for checking whether a resource exists or obtaining metadata.

Parameters:

  • $url: The relative path or full URL
  • $data: Array of parameters appended to the URL as a query string

Returns: A Response instance

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client->head('/large-file.zip');

if ($response->isSuccessful()) {
$headers = $response->getHeaders();
echo "File size: " . ($headers['download_content_length'] ?? 'unknown');
}

options​

Performs an OPTIONS request to discover the HTTP methods allowed on a resource. Often used for CORS preflight requests.

Parameters:

  • $url: The relative path or full URL

Returns: A Response instance

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client->options('/users');

// The allowed methods are usually in the Allow header
$headers = $response->getHeaders();

Advanced configuration​

addAttach​

Attaches one or more files to a multipart/form-data request.

Parameters:

  • $attach: File path (string) or array of file paths

Returns: The client instance for fluent chaining

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');

// Upload a single file
$response = $client->addAttach('/path/to/document.pdf')
->post('/upload');

// Upload multiple files
$response = $client->addAttach([
'/path/to/image1.jpg',
'/path/to/image2.jpg'
])->post('/upload-multiple');

withHeaders​

Adds custom HTTP headers to the request.

Parameters:

  • $headers: Associative array of headers

Returns: The client instance for fluent chaining

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client
->withHeaders([
'Authorization' => 'Bearer your-api-token',
'X-Custom-Header' => 'custom-value'
])
->get('/protected-endpoint');

echo $response->getContent();

setUserAgent​

Sets the User-Agent for the request.

Parameters:

  • $user_agent: String representing the user agent

Returns: The client instance for fluent chaining

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client
->setUserAgent('MyApp/1.0 (BowPHP)')
->get('/users');

echo $response->getContent();

acceptJson​

Configures the client to send and accept data in JSON format. Automatically adds the Content-Type: application/json and Accept: application/json headers.

Returns: The client instance for fluent chaining

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client
->acceptJson()
->post('/users', [
'name' => 'John Doe',
'email' => 'john@example.com'
]);

// The data will be automatically encoded as JSON
$result = $response->toArray();

withJson​

Configures the client to send data in JSON format, without enforcing the response format. Only adds the Content-Type: application/json header.

Use withJson when the remote API accepts JSON as input but returns another format (XML, HTML, plain text). Use acceptJson when the exchange is JSON in both directions.

Returns: The client instance for fluent chaining

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client
->withJson()
->post('/webhook', ['event' => 'order.created', 'order_id' => 42]);

hasHeader​

Checks whether a specific header (key and value) has already been added to the request. Handy for avoiding adding the same conditional header twice.

Parameters:

  • $key: Header name
  • $value: Expected value

Returns: bool

Example:

$client = new HttpClient('https://api.example.com');
$client->withHeaders(['X-Trace-Id' => 'abc-123']);

if (!$client->hasHeader('X-Trace-Id', 'abc-123')) {
$client->withHeaders(['X-Trace-Id' => 'abc-123']);
}

Authentication​

basicAuth​

Configures HTTP Basic authentication with Base64 encoding of the credentials.

Parameters:

  • $key: Key or username
  • $secret: Secret or password

Returns: The client instance for fluent chaining

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client
->basicAuth('api_key', 'api_secret')
->get('/protected-resource');

bearerAuth​

Configures Bearer token authentication (OAuth2, JWT, etc.).

Parameters:

  • $token: The authentication token

Returns: The client instance for fluent chaining

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client
->bearerAuth('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...')
->get('/user/profile');

auth​

Configures cURL's native HTTP authentication.

Parameters:

  • $username: Username
  • $password: Password

Returns: The client instance for fluent chaining

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client
->auth('username', 'password')
->get('/protected');

Timeouts and SSL​

timeout​

Sets the maximum time allowed for the complete execution of the request.

Parameters:

  • $seconds: Duration in seconds

Returns: The client instance for fluent chaining

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client
->timeout(30) // 30 seconds maximum
->get('/slow-endpoint');

connectTimeout​

Sets the maximum time to establish the connection to the server.

Parameters:

  • $seconds: Duration in seconds

Returns: The client instance for fluent chaining

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://api.example.com');
$response = $client
->connectTimeout(5) // 5 seconds to establish the connection
->timeout(30)
->get('/endpoint');

disableSslVerification​

Disables SSL certificate verification. Warning: use only in a development environment.

Returns: The client instance for fluent chaining

Example:

use Bow\Http\Client\HttpClient;

$client = new HttpClient('https://localhost:8443');
$response = $client
->disableSslVerification()
->get('/api/test');
warning

Never disable SSL verification in production. Doing so exposes your application to man-in-the-middle attacks.

Exception handling​

You must distinguish between two levels of error:

  1. Transport error β€” the request could not complete at all (connection refused, host not found, timeout exceeded, SSL negotiation failure). In this case, the client throws a Bow\Http\Client\HttpClientException carrying the cURL error message and code.
  2. HTTP error response β€” the request completed but the server responds with an error status (404, 500, …). No exception is thrown: you get a Response instance and inspect its status via isFailed() / getCode().
use Bow\Http\Client\HttpClient;
use Bow\Http\Client\HttpClientException;

$client = new HttpClient('https://api.example.com');

try {
$response = $client->acceptJson()->get('/users');

// The request completed: check the returned HTTP status
if ($response->isFailed()) {
// 4xx / 5xx β€” no exception, read the code
logger()->warning('API responded ' . $response->getCode());
return;
}

$users = $response->toArray();
} catch (HttpClientException $e) {
// Network / SSL / timeout failure: the request never completed
logger()->error('HTTP failure: ' . $e->getMessage(), ['code' => $e->getCode()]);
}
cURL extension required

The client relies on the curl extension. If it is not loaded, instantiating HttpClient throws a BadFunctionCallException.

The Response class​

The Response class encapsulates all the information returned by an HTTP request: content, headers, status code, and performance metrics. It provides a simple and intuitive interface for working with responses.

Main methods​

getContent​

public function getContent(): ?string

Returns the raw content of the HTTP response as a string. Returns null if no content is available.

Example:

$content = $response->getContent();
echo $content;

toJson​

public function toJson(?bool $associative = null): object|array

Decodes the JSON content of the response into a PHP object or array.

Parameters:

  • $associative: true for an associative array, false for an object (default)

Example:

// Returns an object
$user = $response->toJson();
echo $user->name;

// Returns an array
$userData = $response->toJson(true);
echo $userData['name'];

toArray​

public function toArray(): array

Alias for toJson(true). Returns the JSON content as an associative array.

Example:

$users = $response->toArray();
foreach ($users as $user) {
echo $user['name'];
}

getHeaders​

public function getHeaders(): array

Returns the metadata array produced by curl_getinfo() for the request. This array is not the raw list of HTTP response headers: it contains cURL keys such as http_code, content_type, total_time, connect_time, size_upload, size_download, download_content_length, etc.

note

If you need a specific raw HTTP header (e.g. Location, X-Request-Id), parse it via CURLOPT_HEADERFUNCTION or use the appropriate cURL configuration option on the remote server side.

getCode / statusCode​

public function getCode(): ?int
public function statusCode(): ?int

Return the HTTP status code of the response (200, 404, 500, etc.). Returns null if unavailable.

Example:

$code = $response->getCode();
// or
$code = $response->statusCode();

if ($code === 200) {
echo "Request successful";
}

isSuccessful​

public function isSuccessful(): bool

Returns true if the status code indicates success (200 or 201).

Example:

if ($response->isSuccessful()) {
$data = $response->toArray();
// Process the data
}

isFailed​

public function isFailed(): bool

Returns true if the request failed (status code other than 200 or 201).

Example:

if ($response->isFailed()) {
echo "Error: " . $response->getCode();
}

Performance metrics​

The HTTP client provides several methods to analyze request performance:

MethodDescriptionReturn
getExecutionTime()Total request execution time (cURL key total_time)mixed (usually ?float, seconds)
getConnexionTime()Connection establishment time?float (seconds)
getUploadSize()Size of the data sent?float (bytes)
getUploadSpeed()Upload speed?float (bytes/sec)
getDownloadSize()Size of the data received?float (bytes)
getDownloadSpeed()Download speed?float (bytes/sec)

Example usage:

$response = $client->get('/large-data');

echo "Execution time: " . $response->getExecutionTime() . "s\n";
echo "Downloaded size: " . $response->getDownloadSize() . " bytes\n";
echo "Speed: " . $response->getDownloadSpeed() . " bytes/s\n";

Error handling​

getErrorMessage: Returns the cURL error message if there is one, otherwise an empty string.

getErrorNumber: Returns the cURL error code.

Example:

if ($response->isFailed()) {
echo "Error #{$response->getErrorNumber()}: {$response->getErrorMessage()}";
}

Other methods​

getContentType​

public function getContentType(): ?string

Returns the MIME type of the content (e.g. application/json, text/html).

Example:

$contentType = $response->getContentType();
if ($contentType === 'application/json') {
$data = $response->toArray();
}

Is something missing?

If you run into problems with the documentation or have suggestions to improve the documentation or the project in general, please open an issue for us, or send a tweet mentioning the Twitter account @bowframework or directly on github.