Skip to main content
Version: 1.x

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.

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',
] );

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:

use Mantle\Facade\Http;

Http::post( 'http://example.org/endpoint', [
'name' => 'Mantle',
] );

Sending a Body

Requests can also be made using a form body or a raw body:

use Mantle\Facade\Http;

Http::as_form()->post( 'http://example.org/endpoint', [
'name' => 'Mantle',
] );

Http::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:

use Mantle\Facade\Http;

// The actual URL will be https://example.org/query?name=mantle
Http::get( 'https://example.org/query', [
'name' => 'mantle',
] );

Headers

Headers can be added to a request using the with_header() and with_headers() methods:

Http::with_headers( [
'X-Api-Key' => 'password',
] )->post( 'https://example.org' );

Http::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:

Http::accept( 'text/plain' )->post( 'https://example.org' );
Http::accept_json()->post( 'https://example.org' );

Authentication

You can specify basic authentication and bearer token credentials with built-in helper methods:

Http::with_basic_auth( 'username', 'password' )->post( 'https://example.org' );

// Passed as Authorization: Bearer <value>
Http::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:

Http::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:

Http::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:

try {
Http::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():

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
URL Management

Configure the full URL for a request using set_url() and retrieve it with get_url():

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
HTTP Method Configuration

Set the HTTP method for the request using set_method() and retrieve it with get_method():

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

Content Type and Headers

Content Type Configuration

Configure how request data should be sent using as_form(), as_json(), and content_type() methods:

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' );
Accept Headers

Specify what content type you expect in the response using accept_json() and accept() methods:

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' );
Header Management

Add and manage HTTP headers using with_headers(), with_header(), headers(), header(), clear_headers(), and with_user_agent() methods:

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' );

Authentication

Basic Authentication

Use HTTP Basic Authentication with username and password using the with_basic_auth() method:

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' );
Bearer Token Authentication

Use Bearer token authentication using the with_token() method:

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' );

Handle cookies for stateful requests using clear_cookies(), with_cookies(), and with_cookie() methods:

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

Request Body Methods

Configure the request body content using with_body(), with_json(), body(), and body_format() methods:

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',
] );

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():

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
Error Status Checks

Check for HTTP errors using failed(), client_error(), and server_error():

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
Specific Status Checks

Check for specific HTTP status codes using unauthorized(), forbidden(), and redirect():

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
Status Code Retrieval

Get the exact HTTP status code using status():

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

Response Body Methods

Raw Body Access

Get the raw response body content using body():

use Mantle\Facade\Http;

// 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():

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
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:

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
XML Parsing

Parse XML responses with optional XPath queries using xml():

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
Collection Access

Access response data as a Mantle Collection using collect():

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
Feed Parsing

Parse RSS/Atom feeds and get a SimplePie object using feed():

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();

Header Methods

Access response headers and metadata using header() and headers():

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

Work with response cookies using cookie() and cookies():

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

Content Type Detection Methods

Text Content Detection

Detect JSON and XML content types using is_json() and is_xml():

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
Binary Content Detection

Detect file and binary content using is_file() and is_blob():

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
Feed Detection

Detect and parse RSS/Atom feeds using is_feed() and feed():

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
Error Detection

Check for WordPress errors using is_wp_error():

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

Raw Response Methods

Access underlying WordPress HTTP API response using response():

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()

Debugging Methods

Debug and inspect responses during development using dump() and dd():

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

Array Access Support

The Mantle\Http_Client\Response object implements ArrayAccess, allowing you to access JSON/XML response properties directly:

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

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:

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 );
} );

Caching

Requests can be cached using the cached method. The method can be used when chaining together your HTTP request:

use Mantle\Facade\Http;

$response = Http::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:

use Mantle\Facade\Http;

$response = Http::cached( now()->addDay() )->get( 'https://example.org' );

Purging the cache can be done using the purge method:

use Mantle\Facade\Http;

Http::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:

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' );

The cache_flexible method accepts two arguments:

  • stale: The amount of time to keep the cached response stale. Accepts a number of seconds or a DateTime instance.
  • expire: The amount of time to keep the cached response before it is considered expired. Accepts a number of seconds or a DateTime instance.

Here is an example of passing a number of seconds to the cache_flexible method:

use Mantle\Facade\Http;

$response = Http::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:

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();

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:

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();

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.