HTTP Client
Introduction
Mantle provides a fluent and expressive wrapper around the WordPress HTTP API allowing you to quickly make HTTP requests with external services. The HTTP Client combined with support for testing and faking Remote Requests provides you a full solution for making and testing external HTTP requests end-to-end.
Making Requests
The HTTP Client is installed by default with Mantle. It also supports being used outside of the framework.
- Framework Use
- Standalone Use
The Http Client is included with Mantle out of the box.
Making requests with the HTTP Client can be done using any HTTP verb. Requests
can be made using the Http facade class or by instantiating Mantle\Http_Client\Http_Client
directly:
use Mantle\Facade\Http;
$response = Http::get( 'https://example.org/' );
You can also use other HTTP methods fluently on the Http facade:
use Mantle\Facade\Http;
$response = Http::post( 'https://example.org/', [
'name' => 'Mantle',
] );
Install the Http Client package via Composer:
composer require mantle-framework/http-client
Making requests with the HTTP Client can be done using any HTTP verb. Requests
can be made by instantiating Mantle\Http_Client\Factory directly:
use Mantle\Http_Client\Factory;
$http = new Factory();
$response = $http->get( 'https://example.org/' );
// Or using a fluent interface:
$response = $http
->timeout( 10 )
->get( 'https://example.org/' );
Request Data
Many HTTP requests include some sort of a payload for POST, PUT, PATCH,
and DELETE methods. These methods access an array of data as their second
argument. By default these will be sent using JSON:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
Http::post( 'http://example.org/endpoint', [
'name' => 'Mantle',
] );
use Mantle\Http_Client\Factory;
Factory::create()->post( 'http://example.org/endpoint', [
'name' => 'Mantle',
] );
Sending a Body
Requests can also be made using a form body or a raw body:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
Http::as_form()->post( 'http://example.org/endpoint', [
'name' => 'Mantle',
] );
Http::with_body( 'raw-body' )->post( 'http://example.org/endpoint' );
use Mantle\Http_Client\Factory;
Factory::create()->as_form()->post( 'http://example.org/endpoint', [
'name' => 'Mantle',
] );
Factory::create()->with_body( 'raw-body' )->post( 'http://example.org/endpoint' );
GET Request Query Parameters
When making GET requests, you can either pass a URL with a query string
directly or pass an array of key / value pairs as the second argument:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// The actual URL will be https://example.org/query?name=mantle
Http::get( 'https://example.org/query', [
'name' => 'mantle',
] );
use Mantle\Http_Client\Factory;
// The actual URL will be https://example.org/query?name=mantle
Factory::create()->get( 'https://example.org/query', [
'name' => 'mantle',
] );
Headers
Headers can be added to a request using the with_header() and with_headers()
methods:
- Framework Use
- Standalone Use
Http::with_headers( [
'X-Api-Key' => 'password',
] )->post( 'https://example.org' );
Http::with_header( 'X-Special-Header', 'value' )->post( 'https://example.org' );
use Mantle\Http_Client\Factory;
Factory::create()->with_headers( [
'X-Api-Key' => 'password',
] )->post( 'https://example.org' );
Factory::create()->with_header( 'X-Special-Header', 'value' )->post( 'https://example.org' );
The accept method can be used to specify the content type that your
application is expecting in response:
- Framework Use
- Standalone Use
Http::accept( 'text/plain' )->post( 'https://example.org' );
Http::accept_json()->post( 'https://example.org' );
use Mantle\Http_Client\Factory;
Factory::create()->accept( 'text/plain' )->post( 'https://example.org' );
Factory::create()->accept_json()->post( 'https://example.org' );
Authentication
You can specify basic authentication and bearer token credentials with built-in helper methods:
- Framework Use
- Standalone Use
Http::with_basic_auth( 'username', 'password' )->post( 'https://example.org' );
// Passed as Authorization: Bearer <value>
Http::with_token( '<value>' )->post( 'https://example.org' );
use Mantle\Http_Client\Factory;
Factory::create()->with_basic_auth( 'username', 'password' )->post( 'https://example.org' );
// Passed as Authorization: Bearer
Factory::create()->with_token( '<value>' )->post( 'https://example.org' );
Timeout
The timeout method may be used to specify a maximum number of seconds to wait
for a response. The default is 5 seconds:
- Framework Use
- Standalone Use
Http::timeout( 10 )->post( 'https://example.org' );
use Mantle\Http_Client\Factory;
Factory::create()->timeout( 10 )->post( 'https://example.org' );
Retries
If you would like HTTP client to automatically retry the request if a client or
server error occurs, you may use the retry method. The retry method accepts
the maximum number of times the request should be attempted and the number of
milliseconds that Mantle should wait in between attempts:
- Framework Use
- Standalone Use
Http::retry( 3 )->post( 'https://example.org' );
use Mantle\Http_Client\Factory;
Factory::create()->retry( 3 )->post( 'https://example.org' );
Error Handling
By default, errors will be handled and converted into a
Mantle\Http_Client\Response object. This includes WP_Error objects that are
returned by WordPress. No exceptions are thrown by default.
Optionally, you can opt for an exception to be thrown if an error occurs:
- Framework Use
- Standalone Use
try {
Http::throw_exception()->post( 'https://example.org' );
} catch ( \Mantle\Http_Client\Http_Client_Exception $e ) {
// Handle the exception.
}
use Mantle\Http_Client\Factory;
try {
Factory::create()->throw_exception()->post( 'https://example.org' );
} catch ( \Mantle\Http_Client\Http_Client_Exception $e ) {
// Handle the exception.
}
Available Request Methods
The HTTP Client provides a comprehensive set of methods for configuring and making HTTP requests. Here's a complete reference with examples for each method:
URL and Method Configuration
Base URL Management
Set a base URL that will be prepended to all subsequent requests using set_base_url() and retrieve it with get_base_url():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Set a base URL for multiple requests
$client = Http::set_base_url( 'https://api.example.com/v1' );
// Now all requests will use this base URL
$response = $client->get( '/users' ); // Requests https://api.example.com/v1/users
// Get the current base URL
$base_url = $client->get_base_url(); // Returns: https://api.example.com/v1
use Mantle\Http_Client\Factory;
$http = new Factory();
// Set a base URL for multiple requests
$client = $http->set_base_url( 'https://api.example.com/v1' );
// Now all requests will use this base URL
$response = $client->get( '/users' ); // Requests https://api.example.com/v1/users
// Get the current base URL
$base_url = $client->get_base_url(); // Returns: https://api.example.com/v1
URL Management
Configure the full URL for a request using set_url() and retrieve it with get_url():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Set the complete URL
$client = Http::set_url( 'https://httpbin.org/get' );
// Get the configured URL
$url = $client->get_url(); // Returns: https://httpbin.org/get
use Mantle\Http_Client\Factory;
$http = new Factory();
// Set the complete URL
$client = $http->set_url( 'https://httpbin.org/get' );
// Get the configured URL
$url = $client->get_url(); // Returns: https://httpbin.org/get
HTTP Method Configuration
Set the HTTP method for the request using set_method() and retrieve it with get_method():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
use Mantle\Http_Client\Http_Method;
// Set method using enum
$client = Http::set_method( Http_Method::POST );
// Set method using string
$client = Http::set_method( 'PATCH' );
// Get the current method
$method = $client->get_method(); // Returns Http_Method enum
use Mantle\Http_Client\Factory;
use Mantle\Http_Client\Http_Method;
$http = new Factory();
// Set method using enum
$client = $http->set_method( Http_Method::POST );
// Set method using string
$client = $http->set_method( 'PATCH' );
// Get the current method
$method = $client->get_method(); // Returns Http_Method enum
Content Type and Headers
Content Type Configuration
Configure how request data should be sent using as_form(), as_json(), and content_type() methods:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Send data as form-encoded (application/x-www-form-urlencoded)
Http::as_form()->post( 'https://example.org', [
'name' => 'John Doe',
'email' => 'john@example.com',
] );
// Send data as JSON (application/json) - this is the default
Http::as_json()->post( 'https://example.org', [
'user' => [
'name' => 'John Doe',
'email' => 'john@example.com',
],
] );
// Set a custom content type
Http::content_type( 'application/xml' )->post( 'https://example.org' );
use Mantle\Http_Client\Factory;
$http = new Factory();
// Send data as form-encoded (application/x-www-form-urlencoded)
$http->as_form()->post( 'https://example.org', [
'name' => 'John Doe',
'email' => 'john@example.com',
] );
// Send data as JSON (application/json) - this is the default
$http->as_json()->post( 'https://example.org', [
'user' => [
'name' => 'John Doe',
'email' => 'john@example.com',
],
] );
// Set a custom content type
$http->content_type( 'application/xml' )->post( 'https://example.org' );
Accept Headers
Specify what content type you expect in the response using accept_json() and accept() methods:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Accept JSON responses
Http::accept_json()->get( 'https://api.example.com/data' );
// Accept specific content type
Http::accept( 'text/xml' )->get( 'https://api.example.com/xml-data' );
// Accept multiple content types
Http::accept( 'application/json, text/plain' )->get( 'https://api.example.com/data' );
use Mantle\Http_Client\Factory;
$http = new Factory();
// Accept JSON responses
$http->accept_json()->get( 'https://api.example.com/data' );
// Accept specific content type
$http->accept( 'text/xml' )->get( 'https://api.example.com/xml-data' );
// Accept multiple content types
$http->accept( 'application/json, text/plain' )->get( 'https://api.example.com/data' );
Header Management
Add and manage HTTP headers using with_headers(), with_header(), headers(), header(), clear_headers(), and with_user_agent() methods:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Add multiple headers at once
Http::with_headers( [
'X-API-Key' => 'your-api-key',
'X-Client-Version' => '1.0.0',
'Accept-Language' => 'en-US',
] )->get( 'https://api.example.com/data' );
// Add a single header
Http::with_header( 'X-Custom-Header', 'custom-value' )->get( 'https://example.org' );
// Replace an existing header (default behavior)
Http::with_header( 'User-Agent', 'My Custom Agent', true )->get( 'https://example.org' );
// Get all current headers
$headers = Http::with_header( 'X-Test', 'value' )->headers();
// Returns: ['X-Test' => 'value', ...]
// Get a specific header value
$value = Http::with_header( 'X-Test', 'value' )->header( 'X-Test' );
// Returns: 'value'
// Clear all headers
Http::with_header( 'X-Test', 'value' )->clear_headers()->get( 'https://example.org' );
// Set a custom user agent
Http::with_user_agent( 'MyApp/1.0 (https://myapp.com)' )->get( 'https://example.org' );
use Mantle\Http_Client\Factory;
$http = new Factory();
// Add multiple headers at once
$http->with_headers( [
'X-API-Key' => 'your-api-key',
'X-Client-Version' => '1.0.0',
'Accept-Language' => 'en-US',
] )->get( 'https://api.example.com/data' );
// Add a single header
$http->with_header( 'X-Custom-Header', 'custom-value' )->get( 'https://example.org' );
// Replace an existing header (default behavior)
$http->with_header( 'User-Agent', 'My Custom Agent', true )->get( 'https://example.org' );
// Get all current headers
$headers = $http->with_header( 'X-Test', 'value' )->headers();
// Returns: ['X-Test' => 'value', ...]
// Get a specific header value
$value = $http->with_header( 'X-Test', 'value' )->header( 'X-Test' );
// Returns: 'value'
// Clear all headers
$http->with_header( 'X-Test', 'value' )->clear_headers()->get( 'https://example.org' );
// Set a custom user agent
$http->with_user_agent( 'MyApp/1.0 (https://myapp.com)' )->get( 'https://example.org' );
Authentication
Basic Authentication
Use HTTP Basic Authentication with username and password using the with_basic_auth() method:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Basic auth with username and password
Http::with_basic_auth( 'username', 'password' )->get( 'https://api.example.com/protected' );
// Example with a real API
Http::with_basic_auth( 'api_user', 'secret123' )
->get( 'https://api.github.com/user/repos' );
use Mantle\Http_Client\Factory;
$http = new Factory();
// Basic auth with username and password
$http->with_basic_auth( 'username', 'password' )->get( 'https://api.example.com/protected' );
// Example with a real API
$http->with_basic_auth( 'api_user', 'secret123' )
->get( 'https://api.github.com/user/repos' );
Bearer Token Authentication
Use Bearer token authentication using the with_token() method:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Bearer token (default type)
Http::with_token( 'your-access-token' )->get( 'https://api.example.com/user' );
// Custom token type
Http::with_token( 'your-api-key', 'API-Key' )->get( 'https://api.example.com/data' );
// Sends: Authorization: API-Key your-api-key
// Example with GitHub API
Http::with_token( 'ghp_xxxxxxxxxxxx' )
->get( 'https://api.github.com/user' );
use Mantle\Http_Client\Factory;
$http = new Factory();
// Bearer token (default type)
$http->with_token( 'your-access-token' )->get( 'https://api.example.com/user' );
// Custom token type
$http->with_token( 'your-api-key', 'API-Key' )->get( 'https://api.example.com/data' );
// Sends: Authorization: API-Key your-api-key
// Example with GitHub API
$http->with_token( 'ghp_xxxxxxxxxxxx' )
->get( 'https://api.github.com/user' );
Cookie Management
Handle cookies for stateful requests using clear_cookies(), with_cookies(), and with_cookie() methods:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Set multiple cookies at once
Http::with_cookies( [
'session_id' => 'abc123',
'preference' => 'dark_mode',
'language' => 'en',
] )->get( 'https://example.org' );
// Add a single cookie using WP_Http_Cookie
$cookie = new \WP_Http_Cookie( [
'name' => 'user_session',
'value' => 'xyz789',
'domain' => '.example.com',
'path' => '/',
] );
Http::with_cookie( $cookie )->get( 'https://api.example.com/user' );
// Clear all cookies before making a request
Http::with_cookies( [
'old_session' => 'previous_value',
'temp_data' => 'some_data',
] )
->clear_cookies()
->get( 'https://example.org' ); // Request made without any cookies
use Mantle\Http_Client\Factory;
$http = new Factory();
// Set multiple cookies at once
$http->with_cookies( [
'session_id' => 'abc123',
'preference' => 'dark_mode',
'language' => 'en',
] )->get( 'https://example.org' );
// Add a single cookie using WP_Http_Cookie
$cookie = new \WP_Http_Cookie( [
'name' => 'user_session',
'value' => 'xyz789',
'domain' => '.example.com',
'path' => '/',
] );
$http->with_cookie( $cookie )->get( 'https://api.example.com/user' );
// Clear all cookies before making a request
$http->with_cookies( [
'old_session' => 'previous_value',
'temp_data' => 'some_data',
] )
->clear_cookies()
->get( 'https://example.org' ); // Request made without any cookies
Request Body Methods
Configure the request body content using with_body(), with_json(), body(), and body_format() methods:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Send raw body with content type
Http::with_body(
'{"custom": "json", "data": true}',
'application/json'
)->post( 'https://api.example.com/webhook' );
// Send XML data
Http::with_body(
'<user><name>John</name></user>',
'application/xml'
)->post( 'https://api.example.com/users' );
// Send JSON data (alternative to as_json)
Http::with_json( [
'user' => [
'name' => 'John Doe',
'email' => 'john@example.com',
],
] )->post( 'https://api.example.com/users' );
// Get the current body content
$body = Http::with_json( ['test' => 'data'] )->body();
// Set body format
Http::body_format( 'form' )->post( 'https://example.org', [
'name' => 'John',
] );
use Mantle\Http_Client\Factory;
$http = new Factory();
// Send raw body with content type
$http->with_body(
'{"custom": "json", "data": true}',
'application/json'
)->post( 'https://api.example.com/webhook' );
// Send XML data
$http->with_body(
'<user><name>John</name></user>',
'application/xml'
)->post( 'https://api.example.com/users' );
// Send JSON data (alternative to as_json)
$http->with_json( [
'user' => [
'name' => 'John Doe',
'email' => 'john@example.com',
],
] )->post( 'https://api.example.com/users' );
// Get the current body content
$body = $http->with_json( ['test' => 'data'] )->body();
// Set body format
$http->body_format( 'form' )->post( 'https://example.org', [
'name' => 'John',
] );
Request Options
Configure low-level request options using with_options(), without_verifying(), and timeout() methods:
use Mantle\Http_Client\Factory;
$http = new Factory();
// Add custom options (merged with existing)
$http->with_options( [
'sslverify' => false,
'timeout' => 30,
'user-agent' => 'Custom Agent',
], true )->get( 'https://example.org' );
// Replace all options
$http->with_options( [
'timeout' => 60,
], false )->get( 'https://example.org' );
// Disable SSL verification (useful for development)
$http->without_verifying()->get( 'https://self-signed.badssl.com/' );
// Set request timeout
$http->timeout( 30 )->get( 'https://slow-api.example.com/data' );
Redirect Handling
Control how redirects are handled using without_redirecting() and with_redirecting() methods:
use Mantle\Http_Client\Factory;
$http = new Factory();
// Disable automatic redirect following
$http->without_redirecting()->get( 'https://httpbin.org/redirect/1' );
// Will return the 3xx response instead of following the redirect
// Enable redirects with custom limit
$http->with_redirecting( 10 )->get( 'https://httpbin.org/redirect/5' );
// Will follow up to 10 redirects
// Default redirect behavior (5 redirects)
$http->with_redirecting()->get( 'https://httpbin.org/redirect/3' );
Middleware Management
Add custom middleware to modify requests and responses using middleware(), prepend_middleware(), get_middleware(), without_middleware(), and filter_middleware() methods:
use Mantle\Http_Client\Factory;
use Mantle\Http_Client\Http_Client;
use Closure;
$http = new Factory();
// Add middleware to log requests
$http->middleware( function ( Http_Client $client, Closure $next ) {
error_log( 'Making request to: ' . $client->get_url() );
$response = $next( $client );
error_log( 'Response status: ' . $response->status() );
return $response;
} )->get( 'https://httpbin.org/get' );
// Add middleware to the beginning of the stack
$http->prepend_middleware( function ( Http_Client $client, Closure $next ) {
// This runs before other middleware
$client->with_header( 'X-Request-ID', uniqid() );
return $next( $client );
} )->get( 'https://api.example.com/data' );
// Get all registered middleware
$middleware = $http->middleware( $some_middleware )->get_middleware();
// Remove specific middleware
$http->middleware( $middleware1 )
->middleware( $middleware2 )
->without_middleware( 'middleware_name' )
->get( 'https://example.org' );
// Filter middleware based on a callback
$http->middleware( $middleware1 )
->middleware( $middleware2 )
->filter_middleware( function ( $middleware ) {
return $middleware !== $unwanted_middleware;
} )
->get( 'https://example.org' );
Streaming Methods
Handle file downloads and streaming responses using stream() and dont_stream() methods:
use Mantle\Http_Client\Factory;
$http = new Factory();
// Stream response to a file
$http->stream( '/path/to/download/file.zip' )
->get( 'https://example.com/large-file.zip' );
// Stream response without saving to file (for processing)
$http->stream()->get( 'https://api.example.com/large-dataset.json' );
// Disable streaming (default behavior)
$http->stream( '/tmp/file.zip' )
->dont_stream()
->get( 'https://example.com/file.zip' );
Retry Configuration
Configure automatic request retries using the retry() method:
use Mantle\Http_Client\Factory;
$http = new Factory();
// Retry up to 3 times with no delay
$http->retry( 3 )->get( 'https://unreliable-api.example.com/data' );
// Retry up to 5 times with 1000ms delay between attempts
$http->retry( 5, 1000 )->post( 'https://api.example.com/webhook', [
'event' => 'user_signup',
] );
// Retry with exponential backoff (delay gets longer each time)
$http->retry( 3, 500 )->get( 'https://rate-limited-api.example.com/data' );
Exception Handling
Control whether exceptions are thrown on errors using throw_exception() and dont_throw_exception() methods:
use Mantle\Http_Client\Factory;
use Mantle\Http_Client\Http_Client_Exception;
$http = new Factory();
// Throw exceptions on HTTP errors
try {
$http->throw_exception()->get( 'https://httpbin.org/status/500' );
} catch ( Http_Client_Exception $e ) {
echo 'Request failed: ' . $e->getMessage();
echo 'Status code: ' . $e->getResponse()->status();
}
// Default behavior - return Response object instead of throwing
$response = $http->dont_throw_exception()->get( 'https://httpbin.org/status/404' );
if ( $response->failed() ) {
echo 'Request failed with status: ' . $response->status();
}
HTTP Request Methods
Make requests using different HTTP verbs with get(), head(), post(), put(), patch(), and delete() methods:
use Mantle\Http_Client\Factory;
$http = new Factory();
// GET request with query parameters
$response = $http->get( 'https://httpbin.org/get', [
'search' => 'mantle framework',
'limit' => 10,
] );
// GET request with query string in URL
$response = $http->get( 'https://httpbin.org/get?foo=bar' );
// HEAD request (same parameters as GET)
$response = $http->head( 'https://httpbin.org/get', [
'check' => 'headers',
] );
// POST request with data
$response = $http->post( 'https://httpbin.org/post', [
'name' => 'John Doe',
'email' => 'john@example.com',
'age' => 30,
] );
// PUT request for updates
$response = $http->put( 'https://api.example.com/users/123', [
'name' => 'Jane Doe',
'email' => 'jane@example.com',
] );
// PATCH request for partial updates
$response = $http->patch( 'https://api.example.com/users/123', [
'email' => 'newemail@example.com',
] );
// DELETE request
$response = $http->delete( 'https://api.example.com/users/123' );
// DELETE request with data
$response = $http->delete( 'https://api.example.com/posts/456', [
'reason' => 'spam',
'notify_author' => true,
] );
Responses
The HTTP client will return an instance of Mantle\Http_Client\Response, which
provides a flexible wrapper on top of the raw WordPress HTTP API response.
Available Response Methods
The Response object provides a comprehensive set of methods for inspecting and working with HTTP responses:
$response->body(): mixed
$response->client_error(): bool
$response->collect( $key = null ): \Mantle\Support\Collection
$response->cookie( string $name ): ?\WP_HTTP_Cookie
$response->cookies(): array
$response->dd()
$response->dump()
$response->failed(): bool
$response->feed(): \SimplePie
$response->forbidden(): bool
$response->header( string $header )
$response->headers(): array
$response->is_blob(): bool
$response->is_feed(): bool
$response->is_file(): bool
$response->is_json(): bool
$response->is_wp_error(): bool
$response->is_xml(): bool
$response->json( ?string $key = null, $default = null )
$response->mixed_json( ?string $key = null, $default = null )
$response->object()
$response->ok(): bool
$response->redirect(): bool
$response->response(): array
$response->server_error(): bool
$response->status(): int
$response->successful(): bool
$response->unauthorized(): bool
$response->xml( string $xpath = null, $default = null )
Status Code Methods
Success Status Checks
Check for successful HTTP responses using ok() and successful():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Check for successful responses (2xx status codes) using ok() and successful()
$response = Http::get( 'https://httpbin.org/status/200' );
$response->ok(); // true for 200 status
$response->successful(); // true for 200-299 status codes
use Mantle\Http_Client\Factory;
$http = new Factory();
// Check for successful responses (2xx status codes) using ok() and successful()
$response = $http->get( 'https://httpbin.org/status/200' );
$response->ok(); // true for 200 status
$response->successful(); // true for 200-299 status codes
Error Status Checks
Check for HTTP errors using failed(), client_error(), and server_error():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Check for error responses using failed(), client_error(), and server_error()
$response = Http::get( 'https://httpbin.org/status/404' );
$response->failed(); // true for 400-599 status codes
$response->client_error(); // true for 400-499 status codes
$response->server_error(); // true for 500-599 status codes
use Mantle\Http_Client\Factory;
$http = new Factory();
// Check for error responses using failed(), client_error(), and server_error()
$response = $http->get( 'https://httpbin.org/status/404' );
$response->failed(); // true for 400-599 status codes
$response->client_error(); // true for 400-499 status codes
$response->server_error(); // true for 500-599 status codes
Specific Status Checks
Check for specific HTTP status codes using unauthorized(), forbidden(), and redirect():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Check for specific status codes using unauthorized(), forbidden(), and redirect()
$response = Http::get( 'https://httpbin.org/status/401' );
$response->unauthorized(); // true for 401 status
$response->forbidden(); // true for 403 status
$response->redirect(); // true for 300-399 status codes
use Mantle\Http_Client\Factory;
$http = new Factory();
// Check for specific status codes using unauthorized(), forbidden(), and redirect()
$response = $http->get( 'https://httpbin.org/status/401' );
$response->unauthorized(); // true for 401 status
$response->forbidden(); // true for 403 status
$response->redirect(); // true for 300-399 status codes
Status Code Retrieval
Get the exact HTTP status code using status():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Get the exact status code using status()
$response = Http::get( 'https://httpbin.org/status/200' );
$status = $response->status(); // Returns integer status code
use Mantle\Http_Client\Factory;
$http = new Factory();
// Get the exact status code using status()
$response = $http->get( 'https://httpbin.org/status/200' );
$status = $response->status(); // Returns integer status code
Response Body Methods
Raw Body Access
Get the raw response body content using body():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Get raw response body using body()
$response = Http::get( 'https://httpbin.org/json' );
$body = $response->body(); // Returns string
use Mantle\Http_Client\Factory;
$http = new Factory();
// Get raw response body using body()
$response = $http->get( 'https://httpbin.org/json' );
$body = $response->body(); // Returns string
JSON Parsing
Parse JSON responses and access specific data using json() and object():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Parse JSON responses using json()
$response = Http::get( 'https://httpbin.org/json' );
$json = $response->json(); // Returns array
$value = $response->json( 'slideshow.author' ); // Get specific JSON path
$default = $response->json( 'nonexistent.key', 'default' ); // With default value
// Parse as object using object()
$object = $response->object(); // Returns stdClass object
use Mantle\Http_Client\Factory;
$http = new Factory();
// Parse JSON responses using json()
$response = $http->get( 'https://httpbin.org/json' );
$json = $response->json(); // Returns array
$value = $response->json( 'slideshow.author' ); // Get specific JSON path
$default = $response->json( 'nonexistent.key', 'default' ); // With default value
// Parse as object using object()
$object = $response->object(); // Returns stdClass object
Mixed JSON Parsing
Access specific JSON paths with type casting using mixed_json() which will
return the value at the specified JSON path as a
Mixed_Data instance:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Parse JSON responses using mixed_json()
$response = Http::get( 'https://httpbin.org/json' );
$mixed = $response->mixed_json( 'slideshow.slides.0.title' ); // Returns Mixed_Data
$title = $mixed->string(); // Cast to string
use Mantle\Http_Client\Factory;
$http = new Factory();
// Parse JSON responses using mixed_json()
$response = $http->get( 'https://httpbin.org/json' );
$mixed = $response->mixed_json( 'slideshow.slides.0.title' ); // Returns Mixed_Data
$title = $mixed->string(); // Cast to string
XML Parsing
Parse XML responses with optional XPath queries using xml():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Parse XML responses using xml()
$response = Http::get( 'https://httpbin.org/xml' );
$xml = $response->xml(); // Returns array
$nodes = $response->xml( '/slideshow/slide' ); // With XPath query
use Mantle\Http_Client\Factory;
$http = new Factory();
// Parse XML responses using xml()
$response = $http->get( 'https://httpbin.org/xml' );
$xml = $response->xml(); // Returns array
$nodes = $response->xml( '/slideshow/slide' ); // With XPath query
Collection Access
Access response data as a Mantle Collection using collect():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Get as Collection using collect()
$response = Http::get( 'https://httpbin.org/json' );
$collection = $response->collect(); // Returns Mantle\Support\Collection
$specific = $response->collect( 'data' ); // Collect specific key
use Mantle\Http_Client\Factory;
$http = new Factory();
// Get as Collection using collect()
$response = $http->get( 'https://httpbin.org/json' );
$collection = $response->collect(); // Returns Mantle\Support\Collection
$specific = $response->collect( 'data' ); // Collect specific key
Feed Parsing
Parse RSS/Atom feeds and get a SimplePie object using feed():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Parse RSS/Atom feeds using feed()
$response = Http::get( 'https://example.org/feed/' );
$feed = $response->feed(); // Returns SimplePie object
// Access feed data through SimplePie methods
$title = $feed->get_title();
$description = $feed->get_description();
$items = $feed->get_items();
use Mantle\Http_Client\Factory;
$http = new Factory();
// Parse RSS/Atom feeds using feed()
$response = $http->get( 'https://example.org/feed/' );
$feed = $response->feed(); // Returns SimplePie object
// Access feed data through SimplePie methods
$title = $feed->get_title();
$description = $feed->get_description();
$items = $feed->get_items();
Header Methods
Access response headers and metadata using header() and headers():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
$response = Http::get( 'https://httpbin.org/headers' );
// Get specific header using header()
$contentType = $response->header( 'Content-Type' );
$customHeader = $response->header( 'X-Custom-Header' );
// Get all headers using headers()
$headers = $response->headers(); // Returns array of all headers
use Mantle\Http_Client\Factory;
$http = new Factory();
$response = $http->get( 'https://httpbin.org/headers' );
// Get specific header using header()
$contentType = $response->header( 'Content-Type' );
$customHeader = $response->header( 'X-Custom-Header' );
// Get all headers using headers()
$headers = $response->headers(); // Returns array of all headers
Cookie Methods
Work with response cookies using cookie() and cookies():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
$response = Http::get( 'https://httpbin.org/cookies/set/session/abc123' );
// Get specific cookie using cookie()
$cookie = $response->cookie( 'session' ); // Returns WP_HTTP_Cookie or null
// Get all cookies using cookies()
$cookies = $response->cookies(); // Returns array of WP_HTTP_Cookie objects
use Mantle\Http_Client\Factory;
$http = new Factory();
$response = $http->get( 'https://httpbin.org/cookies/set/session/abc123' );
// Get specific cookie using cookie()
$cookie = $response->cookie( 'session' ); // Returns WP_HTTP_Cookie or null
// Get all cookies using cookies()
$cookies = $response->cookies(); // Returns array of WP_HTTP_Cookie objects
Content Type Detection Methods
Text Content Detection
Detect JSON and XML content types using is_json() and is_xml():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Check content types using is_json() and is_xml()
$response = Http::get( 'https://httpbin.org/json' );
$response->is_json(); // true for JSON responses
$response = Http::get( 'https://httpbin.org/xml' );
$response->is_xml(); // true for XML responses
use Mantle\Http_Client\Factory;
$http = new Factory();
// Check content types using is_json() and is_xml()
$response = $http->get( 'https://httpbin.org/json' );
$response->is_json(); // true for JSON responses
$response = $http->get( 'https://httpbin.org/xml' );
$response->is_xml(); // true for XML responses
Binary Content Detection
Detect file and binary content using is_file() and is_blob():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Check for file content using is_file() and is_blob()
$response = Http::get( 'https://httpbin.org/image/png' );
$response->is_file(); // true for file downloads
$response->is_blob(); // true for binary/file content
use Mantle\Http_Client\Factory;
$http = new Factory();
// Check for file content using is_file() and is_blob()
$response = $http->get( 'https://httpbin.org/image/png' );
$response->is_file(); // true for file downloads
$response->is_blob(); // true for binary/file content
Feed Detection
Detect and parse RSS/Atom feeds using is_feed() and feed():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Check for RSS/Atom feeds using is_feed() and feed()
$response = Http::get( 'https://example.org/feed/' );
$response->is_feed(); // true for RSS/Atom feeds
$feed = $response->feed(); // Returns SimplePie object
use Mantle\Http_Client\Factory;
$http = new Factory();
// Check for RSS/Atom feeds using is_feed() and feed()
$response = $http->get( 'https://example.org/feed/' );
$response->is_feed(); // true for RSS/Atom feeds
$feed = $response->feed(); // Returns SimplePie object
Error Detection
Check for WordPress errors using is_wp_error():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Check for WordPress errors using is_wp_error()
$response = Http::get( 'https://httpbin.org/status/404' );
$response->is_wp_error(); // true if response is a WP_Error
use Mantle\Http_Client\Factory;
$http = new Factory();
// Check for WordPress errors using is_wp_error()
$response = $http->get( 'https://httpbin.org/status/404' );
$response->is_wp_error(); // true if response is a WP_Error
Raw Response Methods
Access underlying WordPress HTTP API response using response():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
$response = Http::get( 'https://httpbin.org/get' );
// Get the raw WordPress HTTP response array using response()
$raw = $response->response(); // Returns array from wp_remote_get()
use Mantle\Http_Client\Factory;
$http = new Factory();
$response = $http->get( 'https://httpbin.org/get' );
// Get the raw WordPress HTTP response array using response()
$raw = $response->response(); // Returns array from wp_remote_get()
Debugging Methods
Debug and inspect responses during development using dump() and dd():
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
$response = Http::get( 'https://httpbin.org/json' );
// Dump response for debugging using dump()
$response->dump(); // Outputs response details and continues
// Dump and die (stops execution) using dd()
$response->dd(); // Outputs response details and stops
use Mantle\Http_Client\Factory;
$http = new Factory();
$response = $http->get( 'https://httpbin.org/json' );
// Dump response for debugging using dump()
$response->dump(); // Outputs response details and continues
// Dump and die (stops execution) using dd()
$response->dd(); // Outputs response details and stops
Array Access Support
The Mantle\Http_Client\Response object implements ArrayAccess, allowing you to access JSON/XML response properties directly:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
// Access JSON properties like an array
$response = Http::get( 'https://httpbin.org/json' );
$slideshow = $response['slideshow']; // Equivalent to $response->json('slideshow')
$author = $response['slideshow']['author']; // Nested access
use Mantle\Http_Client\Factory;
$http = new Factory();
// Access JSON properties like an array
$response = $http->get( 'https://httpbin.org/json' );
$slideshow = $response['slideshow']; // Equivalent to $response->json('slideshow')
$author = $response['slideshow']['author']; // Nested access
Base API Client
The HTTP Client can be used as a basis for a API Client for an external service.
For example, if you are making requests to https://httpbin.org and want to
include built-in authentication, you could extend Mantle\Http_Client\Factory
and implement a new_pending_request method:
use Mantle\Http_Client\Factory;
use Mantle\Http_Client\Pending_Request;
class HttpBinClient extends Factory {
protected function new_pending_request(): Pending_Request {
return ( new Pending_Request() )
->base_url( 'https://httpbin.org' )
->with_token( '<token>' );
}
This is a great pattern to use when creating clients for different APIs. Because
it extends Factory, your IDE will also pick up all the methods available to
the client. Let's see an example of using the HttpBinClient class:
// Make a POST request to https://httpbin.org/example-endpoint
$request = HttpBinClient::create()->post( '/example-endpoint', [
'name' => 'Mantle Http Client',
] );
Middleware
Requests can have middleware applied to them to allow the request and the response to be modified. One use case is to calculate a checksum header based on body of the request and pass that along with the request:
- Framework Use
- Standalone Use
use Closure;
use Mantle\Facade\Http;
$client = Http::base_url( 'https://api.github.com' )
->middleware( function ( Http_Client $client, Closure $next ) {
$client->with_header( 'Authorization', md5( $client->url() . $client->body() ) );
// You can also run the callback and then modify the response.
return $next( $client );
} );
use Closure;
use Mantle\Http_Client\Factory;
$client = Factory::base_url( 'https://api.github.com' )
->middleware( function ( Http_Client $client, Closure $next ) {
$client->with_header( 'Authorization', md5( $client->url() . $client->body() ) );
// You can also run the callback and then modify the response.
return $next( $client );
} );
Caching
Requests can be cached using the cached method. The method can be used when
chaining together your HTTP request:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
$response = Http::cached()->get( 'https://example.org' );
use Mantle\Http_Client\Factory;
$response = Factory::create()->cached()->get( 'https://example.org' );
The cached method accepts a single argument of the number of seconds to
cache the response for. It also supports a DateTime object and defaults to one
hour:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
$response = Http::cached( now()->addDay() )->get( 'https://example.org' );
use Mantle\Http_Client\Factory;
$response = Factory::create()
->cached( now()->addDay() )
->get( 'https://example.org' );
Purging the cache can be done using the purge method:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
Http::url( 'https://example.org' )->purge();
use Mantle\Http_Client\Factory;
Factory::create()->url( 'https://example.org' )->purge();
Flexible Caching (SWR)
By default, when a cached response expires the HTTP Client will make a new request and return the new response. If you would like to return the stale cached response while a new request is made in the background, you can use flexible caching (a pattern known as SWR - Stale While Revalidate).
Stale While Revalidate will reuse the stale cached response while a new request is made in the background. This can be useful when you want to ensure that your application is always responsive, even if the external service is slow or unavailable. The new request will be made after the page has been sent to the browser, so it won't impact the user experience.
To use SWR caching, use the cache_flexible() method:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
use function Mantle\Support\Helpers\now;
$response = Http::cache_flexible(
stale: now()->addMinutes( 30 ),
expire: now()->addHours( 3 ),
)->get( 'https://example.org' );
use Mantle\Http_Client\Factory;
use function Mantle\Support\Helpers\now;
$response = Factory::create()
->cache_flexible(
stale: now()->addMinutes( 30 ),
expire: now()->addHours( 3 ),
)
->get( 'https://example.org' );
The cache_flexible method accepts two arguments:
stale: The amount of time to keep the cached response stale. Accepts a number of seconds or aDateTimeinstance.expire: The amount of time to keep the cached response before it is considered expired. Accepts a number of seconds or aDateTimeinstance.
Here is an example of passing a number of seconds to the cache_flexible
method:
- Framework Use
- Standalone Use
use Mantle\Facade\Http;
$response = Http::cache_flexible(
stale: HOUR_IN_SECONDS, // 1 hour
expire: DAY_IN_SECONDS, // 24 hours
)->get( 'https://example.org' );
use Mantle\Http_Client\Factory;
$response = Factory::create()
->cache_flexible(
stale: HOUR_IN_SECONDS, // 1 hour
expire: DAY_IN_SECONDS, // 24 hours
)
->get( 'https://example.org' );
Concurrent Requests (HTTP Pooling)
Sometimes, you may wish to make multiple HTTP requests concurrently. In other words, you want several requests to be dispatched at the same time instead of issuing the requests sequentially. This can lead to substantial performance improvements when interacting with slow HTTP APIs.
Thankfully, you may accomplish this using the pool method. The pool method
accepts a closure which receives an Mantle\Http_Client\Pool instance,
allowing you to easily add requests to the request pool for dispatching:
- Framework Use
- Standalone Use
use Mantle\Http_Client\Pool;
use Mantle\Facade\Http;
$responses = Http::pool( fn ( Pool $pool ) => [
$pool->get( 'http://localhost/first' ),
$pool->post( 'http://localhost/second' )->with_json( [ 'name' => 'Mantle' ] ),
$pool->get( 'http://localhost/third' ),
] );
return $responses[0]->ok() &&
$responses[1]->ok() &&
$responses[2]->ok();
use Mantle\Http_Client\Pool;
use Mantle\Http_Client\Factory;
$responses = Factory::create()->pool( fn ( Pool $pool ) => [
$pool->get( 'http://localhost/first' ),
$pool->post( 'http://localhost/second' )->with_json( [ 'name' => 'Mantle' ] ),
$pool->get( 'http://localhost/third' ),
] );
return $responses[0]->ok() &&
$responses[1]->ok() &&
$responses[2]->ok();
As you can see, each response instance can be accessed based on the order it was
added to the pool. If you wish, you can name the requests using the as method,
which allows you to access the corresponding responses by name:
- Framework Use
- Standalone Use
use Mantle\Http_Client\Pool;
use Mantle\Facade\Http;
$responses = Http::pool( fn ( Pool $pool ) => [
$pool->as( 'first' )->get( 'http://localhost/first' ),
$pool->as( 'second' )->get( 'http://localhost/second' ),
$pool->as( 'third' )->get( 'http://localhost/third' ),
] );
return $responses['first']->ok() &&
$responses['second']->ok() &&
$responses['third']->ok();
use Mantle\Http_Client\Pool;
use Mantle\Http_Client\Factory;
$responses = Factory::create()->pool( fn ( Pool $pool ) => [
$pool->as( 'first' )->get( 'http://localhost/first' ),
$pool->as( 'second' )->get( 'http://localhost/second' ),
$pool->as( 'third' )->get( 'http://localhost/third' ),
] );
return $responses['first']->ok() &&
$responses['second']->ok() &&
$responses['third']->ok();
Pooled requests can use any of the methods available on the HTTP Client, such as
with_headers(), with_token(), timeout(), as well as cache() and
cache_flexible() for caching responses.
Testing Http Client
The Mantle Http Client was built using WordPress' built-in HTTP API. This means that it can be tested using Mantle's Remote Request testing functionality.