The HttpClient class provides a clean cURL-based HTTP client for making outgoing requests from your application. It supports all HTTP methods, JSON and form-encoded bodies, custom headers, redirect following, timeouts, and always returns a consistent response array — never false.
- Class:
JiFramework\Core\Network\HttpClient - Access:
$app->http
Features at a glance:
- GET, POST, and generic method support —
get(),post(),request() - Form-encoded and JSON request bodies
- Custom request headers
- Response headers included in every return value
- Automatic redirect following (configurable)
- Per-request timeouts — total and connection
- Consistent return structure — always
[status_code, body, headers, error] - SSL verification enabled by default, opt-out available
$app = new App();
// GET request
$r = $app->http->get('https://api.example.com/users');
// POST with JSON body
$r = $app->http->post('https://api.example.com/users', [
'name' => 'Alice',
'email' => '[email protected]',
], ['json' => true]);
echo $r['status_code']; // 201
echo $r['body']; // raw response body string
All three methods return the same associative array regardless of whether the request succeeded or failed. You never need to check for false.
status_code— (int) HTTP status code (200, 404, 500, etc.).0when a cURL-level error occurs before a response is received.body— (string) Raw response body. Empty string on cURL error.headers— (array) Response headers as a map of lowercase header name to an array of values, e.g.['content-type' => ['application/json']].error— (string|null)nullon success. The cURL error message string on failure (e.g. timeout, DNS failure, SSL error).
$r = $app->http->get('https://api.example.com/products');
// Always safe to read these keys — no null checks needed
echo $r['status_code']; // 200
echo $r['body']; // raw JSON string
echo $r['headers']['content-type'][0]; // "application/json"
var_dump($r['error']); // NULL
// Check for success
if ($r['error'] !== null) {
// cURL-level failure (timeout, DNS, SSL, etc.)
error_log('Request failed: ' . $r['error']);
} elseif ($r['status_code'] !== 200) {
// Server responded with an error status
error_log('HTTP ' . $r['status_code']);
} else {
$data = json_decode($r['body'], true);
}
get(string $url, array $options = []): array
Performs an HTTP GET request. Query parameters should be appended to the URL directly or built with http_build_query().
$url— (string) The full URL to request.$options— (array, optional) Request options. See the Options section for all supported keys.
$http = $app->http;
// Basic GET
$r = $http->get('https://api.example.com/users');
// With query parameters
$r = $http->get('https://api.example.com/users?' . http_build_query([
'page' => 2,
'limit' => 20,
]));
// With custom header and timeout
$r = $http->get('https://api.example.com/me', [
'headers' => ['Authorization: Bearer ' . $token],
'timeout' => 10,
]);
if ($r['error'] === null && $r['status_code'] === 200) {
$user = json_decode($r['body'], true);
}
post(string $url, array $data = [], array $options = []): array
Performs an HTTP POST request. Body is form-encoded by default. Pass 'json' => true in options to send a JSON body instead.
$url— (string) The full URL to request.$data— (array, optional) Body data to send with the request.$options— (array, optional) Request options. See the Options section for all supported keys.
Form-encoded body — the default. Sends data as application/x-www-form-urlencoded.
$r = $app->http->post('https://api.example.com/login', [
'username' => 'alice',
'password' => 'secret',
]);
if ($r['status_code'] === 200) {
$result = json_decode($r['body'], true);
}
JSON body — set 'json' => true in options. The Content-Type: application/json header is added automatically unless you provide your own.
$r = $app->http->post('https://api.example.com/users', [
'name' => 'Alice',
'email' => '[email protected]',
'role' => 'editor',
], ['json' => true]);
// $r['status_code'] => 201
// $r['body'] => raw JSON response
request(string $method, string $url, array $data = [], array $options = []): array
Performs a request with any HTTP method. Use this for PUT, PATCH, DELETE, and any other verb. The method name is case-insensitive.
$method— (string) HTTP method (e.g.PUT,PATCH,DELETE). Case-insensitive.$url— (string) The full URL to request.$data— (array, optional) Body data. Form-encoded by default; JSON if'json' => trueis set in options.$options— (array, optional) Request options. See the Options section for all supported keys.
$http = $app->http;
// PUT — replace a resource
$r = $http->request('PUT', 'https://api.example.com/users/42', [
'name' => 'Alice Updated',
'email' => '[email protected]',
], ['json' => true]);
// PATCH — partial update
$r = $http->request('PATCH', 'https://api.example.com/users/42', [
'name' => 'Alice Renamed',
], ['json' => true]);
// DELETE — no body needed
$r = $http->request('DELETE', 'https://api.example.com/users/42');
if ($r['status_code'] === 204 || $r['status_code'] === 200) {
// deleted successfully
}
All three methods accept an $options array as their last parameter. All keys are optional.
headers— (array) Custom HTTP request headers. Each entry is a raw header string:['Authorization: Bearer token', 'Accept: application/json'].json— (bool) Whentrue, encodes the request body as JSON and automatically addsContent-Type: application/jsonunless already present inheaders. Default:false.timeout— (int) Maximum total time in seconds for the request to complete (CURLOPT_TIMEOUT). No limit by default.connect_timeout— (int) Maximum time in seconds to wait for the connection to be established (CURLOPT_CONNECTTIMEOUT). No limit by default.follow_redirects— (bool) Whether to follow HTTP 301/302 redirects automatically. Default:true. Up to 10 redirects are followed.ssl_verify— (bool) Whether to verify the SSL certificate and host. Default:true. Set tofalseonly in development against self-signed certificates.
$r = $app->http->post('https://api.example.com/data', $payload, [
'json' => true,
'headers' => ['Authorization: Bearer ' . $token],
'timeout' => 30,
'connect_timeout' => 5,
'follow_redirects'=> true,
'ssl_verify' => true,
]);
Common patterns for handling the response array returned by all three methods.
Decoding a JSON API response:
$r = $app->http->get('https://api.example.com/products', [
'headers' => ['Accept: application/json'],
]);
if ($r['error'] !== null) {
// Network-level failure — log and bail
$app->logger->error('HTTP request failed: {error}', ['error' => $r['error']]);
$app->abort(503, 'Could not reach external API');
}
if ($r['status_code'] !== 200) {
$app->abort($r['status_code']);
}
$products = json_decode($r['body'], true);
Reading response headers:
$r = $app->http->get('https://api.example.com/resource');
// Headers are lowercase, values are arrays
$contentType = $r['headers']['content-type'][0] ?? null;
$rateLimit = $r['headers']['x-ratelimit-remaining'][0] ?? null;
Downloading with a short timeout:
$r = $app->http->get($webhookUrl, [
'timeout' => 5,
'connect_timeout' => 2,
]);
if ($r['error'] !== null) {
// Timeout or connection refused — handle gracefully
}
Calling an API that uses self-signed SSL (dev only):
$r = $app->http->get('https://local.dev/api/ping', [
'ssl_verify' => false,
]);
setDebug(bool $debug): void
Enables cURL verbose output and prints the response array after each request. Useful for debugging connection issues during development. Disable in production.
$debug— (bool)trueto enable,falseto disable.
$http = $app->http;
$http->setDebug(true);
$r = $http->get('https://api.example.com/users');
// cURL verbose output printed to the page/CLI
// Response array also printed via print_r()
$http->setDebug(false); // turn off for subsequent requests
Debug mode prints the cURL negotiation (SSL handshake, redirects, headers sent and received) to standard output. Only enable this during local development — it will expose sensitive header values including auth tokens on screen.