Documentation

CachingHttpClient
in package
implements HttpClientInterface, ResetInterface uses AsyncDecoratorTrait, HttpClientTrait

Adds caching on top of an HTTP client (per RFC 9111).

Known omissions / partially supported features per RFC 9111:

  1. Range requests:
  • All range requests ("partial content") are passed through and never cached.
  1. stale-while-revalidate:
  • There's no actual "background revalidation" for stale responses, they will always be revalidated.
  1. min-fresh, max-stale, only-if-cached:
  • Request directives are not parsed; the client ignores them.
Tags
see
https://www.rfc-editor.org/rfc/rfc9111

Table of Contents

Interfaces

HttpClientInterface
Provides flexible methods for requesting HTTP resources synchronously or asynchronously.
ResetInterface
Provides a way to reset an object to its initial state.

Constants

CACHEABLE_METHODS  = ['GET', 'HEAD']
The HTTP methods that are always cacheable.
CACHEABLE_STATUS_CODES  = [200, 203, 204, 300, 301, 404, 410]
The status codes that are always cacheable.
CONDITIONALLY_CACHEABLE_STATUS_CODES  = [302, 303, 307, 308]
The status codes that are cacheable if the response carries explicit cache directives.
EXCLUDED_HEADERS  = ['connection' => true, 'proxy-authenticate' => true, 'proxy-authentication-info' => true, 'proxy-authorization' => true]
Headers that MUST NOT be stored as per RFC 9111 Section 3.1.
MAX_HEURISTIC_FRESHNESS_TTL  = 86400
Maximum heuristic freshness lifetime in seconds (24 hours).
RESPONSE_INFLUENCING_HEADERS  = ['accept' => true, 'accept-charset' => true, 'accept-encoding' => true, 'accept-language' => true, 'authorization' => true, 'cookie' => true, 'expect' => true, 'host' => true, 'user-agent' => true]
Headers that influence the response and may affect caching behavior.
UNSAFE_METHODS  = ['POST', 'PUT', 'DELETE', 'PATCH']
The HTTP methods that will trigger a cache invalidation.

Properties

$cache  : TagAwareCacheInterface|HttpCache
$CHUNK_SIZE  : int
$client  : HttpClientInterface
$defaultOptions  : array<string|int, mixed>
$maxTtl  : int|null
$sharedCache  : bool

Methods

__construct()  : mixed
request()  : ResponseInterface
Requests an HTTP resource.
stream()  : ResponseStreamInterface
Yields responses chunk by chunk as they complete.
withOptions()  : static
buildVariantKey()  : string
Build a variant key for caching, given an array of normalized headers and the vary fields.
calculateExpiresAt()  : int|null
Calculates the expiration time of the response given the maximum age.
createGatewayTimeoutResponse()  : MockResponse
createResponseFromCache()  : MockResponse
Creates a MockResponse object from cached data.
dechunk()  : string
determineMaxAge()  : int|null
Determine the maximum age of the response.
evaluateCacheFreshness()  : Freshness
Evaluates the freshness of a cached response based on its headers and expiration time.
generateChunkKey()  : string
getCurrentAge()  : int
Retrieves the current age of the response from the headers.
getMetadataKey()  : string
Generates a unique metadata key based on the request hash and varying headers.
getProxy()  : array<string|int, mixed>|null
Loads proxy configuration from the same environment variables as curl when no proxy is explicitly set.
getProxyUrl()  : string|null
hasExplicitExpiration()  : bool
Checks if the response has an explicit expiration.
hash()  : string
isServerResponseCacheable()  : bool
Checks if the server response is cacheable according to the HTTP 1.1 specification (RFC 9111).
jsonEncode()  : string
legacyRequest()  : ResponseInterface
mergeDefaultOptions()  : array<string|int, mixed>
mergeQueryString()  : string|null
Merges and encodes a query array with a query string.
normalizeBody()  : string|resource|Closure
normalizeHeaders()  : array<string|int, array<string|int, string>>
normalizePeerFingerprint()  : array<string|int, mixed>
parseCacheControlHeader()  : array<string, string|true>
Parse the Cache-Control header and return an array of directive names as keys and their values as values, or true if the directive has no value.
parseUrl()  : array<string|int, mixed>
Parses a URL and fixes its encoding if needed.
prepareRequest()  : array<string|int, mixed>
Validates and normalizes method, URL and options, and merges them with defaults.
removeDotSegments()  : string
Removes dot-segments from a path.
resolveUrl()  : array<string|int, mixed>
Resolves a URL against a base URI.
shouldBuffer()  : bool

Constants

CACHEABLE_METHODS

The HTTP methods that are always cacheable.

private mixed CACHEABLE_METHODS = ['GET', 'HEAD']

CACHEABLE_STATUS_CODES

The status codes that are always cacheable.

private mixed CACHEABLE_STATUS_CODES = [200, 203, 204, 300, 301, 404, 410]

CONDITIONALLY_CACHEABLE_STATUS_CODES

The status codes that are cacheable if the response carries explicit cache directives.

private mixed CONDITIONALLY_CACHEABLE_STATUS_CODES = [302, 303, 307, 308]

EXCLUDED_HEADERS

Headers that MUST NOT be stored as per RFC 9111 Section 3.1.

private mixed EXCLUDED_HEADERS = ['connection' => true, 'proxy-authenticate' => true, 'proxy-authentication-info' => true, 'proxy-authorization' => true]

MAX_HEURISTIC_FRESHNESS_TTL

Maximum heuristic freshness lifetime in seconds (24 hours).

private mixed MAX_HEURISTIC_FRESHNESS_TTL = 86400

RESPONSE_INFLUENCING_HEADERS

Headers that influence the response and may affect caching behavior.

private mixed RESPONSE_INFLUENCING_HEADERS = ['accept' => true, 'accept-charset' => true, 'accept-encoding' => true, 'accept-language' => true, 'authorization' => true, 'cookie' => true, 'expect' => true, 'host' => true, 'user-agent' => true]

UNSAFE_METHODS

The HTTP methods that will trigger a cache invalidation.

private mixed UNSAFE_METHODS = ['POST', 'PUT', 'DELETE', 'PATCH']

Properties

$defaultOptions

private array<string|int, mixed> $defaultOptions = self::OPTIONS_DEFAULTS

Methods

__construct()

public __construct(HttpClientInterface $client, TagAwareCacheInterface|StoreInterface $cache[, array<string|int, mixed> $defaultOptions = [] ][, bool $sharedCache = true ][, int|null $maxTtl = null ]) : mixed
Parameters
$client : HttpClientInterface
$cache : TagAwareCacheInterface|StoreInterface
$defaultOptions : array<string|int, mixed> = []
$sharedCache : bool = true

Indicates whether this cache is shared or private. When true, responses may be skipped from caching in presence of certain headers (e.g. Authorization) unless explicitly marked as public.

$maxTtl : int|null = null

The maximum time-to-live (in seconds) for cached responses. If a server-provided TTL exceeds this value, it will be capped to this maximum.

request()

Requests an HTTP resource.

public request(string $method, string $url[, array<string|int, mixed> $options = [] ]) : ResponseInterface

Responses MUST be lazy, but their status code MUST be checked even if none of their public methods are called.

Implementations are not required to support all options described above; they can also support more custom options; but in any case, they MUST throw a TransportExceptionInterface when an unsupported option is passed.

Parameters
$method : string
$url : string
$options : array<string|int, mixed> = []
Return values
ResponseInterface

withOptions()

public withOptions(array<string|int, mixed> $options) : static
Parameters
$options : array<string|int, mixed>
Return values
static

buildVariantKey()

Build a variant key for caching, given an array of normalized headers and the vary fields.

private static buildVariantKey(array<string, string|array<string|int, string>> $normalizedHeaders, array<string|int, string> $varyFields) : string

The key is an ampersand-separated string of "header=value" pairs, with the special case of "header=" for headers that are not present.

Parameters
$normalizedHeaders : array<string, string|array<string|int, string>>
$varyFields : array<string|int, string>
Return values
string

calculateExpiresAt()

Calculates the expiration time of the response given the maximum age.

private static calculateExpiresAt(int|null $maxAge) : int|null
Parameters
$maxAge : int|null

The maximum age of the response in seconds, or null if it cannot be determined

Return values
int|null

The expiration time of the response as a Unix timestamp, or null if the maximum age is null

createGatewayTimeoutResponse()

private static createGatewayTimeoutResponse(string $method, string $url, array<string|int, mixed> $options) : MockResponse
Parameters
$method : string
$url : string
$options : array<string|int, mixed>
Return values
MockResponse

createResponseFromCache()

Creates a MockResponse object from cached data.

private createResponseFromCache(array{next_chunk: string, status_code: int, initial_age: int, headers: array, stored_at: int} $cachedData, string $method, string $url, array<string|int, mixed> $options, string $metadataKey) : MockResponse

This function constructs a MockResponse from the cached data, including the original request method, URL, and options, as well as the cached response headers and content. The constructed MockResponse is then returned.

Parameters
$cachedData : array{next_chunk: string, status_code: int, initial_age: int, headers: array, stored_at: int}
$method : string
$url : string
$options : array<string|int, mixed>
$metadataKey : string
Return values
MockResponse

dechunk()

private static dechunk(string $body) : string
Parameters
$body : string
Return values
string

determineMaxAge()

Determine the maximum age of the response.

private determineMaxAge(array<string, string|array<string|int, string>> $headers, array<string, string|true> $cacheControl) : int|null

This method first checks for the presence of the s-maxage directive, and if present, returns its value minus the current age. If s-maxage is not present, it checks for the presence of the max-age directive, and if present, returns its value minus the current age. If neither directive is present, it checks the Expires header for a valid timestamp, and if present, returns the difference between the timestamp and the current time minus the current age.

If none of the above directives or headers are present, the method returns null.

Parameters
$headers : array<string, string|array<string|int, string>>

An array of HTTP headers

$cacheControl : array<string, string|true>

An array of parsed Cache-Control directives

Return values
int|null

The maximum age of the response, or null if it cannot be determined

evaluateCacheFreshness()

Evaluates the freshness of a cached response based on its headers and expiration time.

private evaluateCacheFreshness(array{headers: array, expires_at: int|null} $data) : Freshness

This method determines the state of the cached response by analyzing the Cache-Control directives and the expiration timestamp.

Parameters
$data : array{headers: array, expires_at: int|null}

The cached response data, including headers and expiration time

Return values
Freshness

generateChunkKey()

private static generateChunkKey() : string
Return values
string

getCurrentAge()

Retrieves the current age of the response from the headers.

private static getCurrentAge(array<string, string|array<string|int, string>> $headers) : int
Parameters
$headers : array<string, string|array<string|int, string>>

An array of HTTP headers

Return values
int

The age of the response in seconds, defaults to 0 if not present

getMetadataKey()

Generates a unique metadata key based on the request hash and varying headers.

private static getMetadataKey(string $requestHash, array<string, string|array<string|int, string>> $normalizedHeaders, array<string|int, string> $varyFields) : string
Parameters
$requestHash : string

A hash representing the request details

$normalizedHeaders : array<string, string|array<string|int, string>>

Normalized headers of the request

$varyFields : array<string|int, string>

Headers to consider for building the variant key

Return values
string

The metadata key composed of the request hash and variant key

getProxy()

Loads proxy configuration from the same environment variables as curl when no proxy is explicitly set.

private static getProxy(string|null $proxy, array<string|int, mixed> $url, string|null $noProxy) : array<string|int, mixed>|null
Parameters
$proxy : string|null
$url : array<string|int, mixed>
$noProxy : string|null
Return values
array<string|int, mixed>|null

getProxyUrl()

private static getProxyUrl(string|null $proxy, array<string|int, mixed> $url) : string|null
Parameters
$proxy : string|null
$url : array<string|int, mixed>
Return values
string|null

hasExplicitExpiration()

Checks if the response has an explicit expiration.

private hasExplicitExpiration(array<string, string|array<string|int, string>> $headers, array<string, string|true> $cacheControl) : bool

This function will return true if the response has an explicit expiration time specified in the headers or in the Cache-Control directives, false otherwise.

Parameters
$headers : array<string, string|array<string|int, string>>
$cacheControl : array<string, string|true>
Return values
bool

hash()

private static hash(string $toHash) : string
Parameters
$toHash : string
Return values
string

isServerResponseCacheable()

Checks if the server response is cacheable according to the HTTP 1.1 specification (RFC 9111).

private isServerResponseCacheable(int $statusCode, array<string, string|array<string|int, string>> $requestHeaders, array<string, string|array<string|int, string>> $responseHeaders, array<string, string|true> $cacheControl) : bool

This function will return true if the server response can be cached, false otherwise.

Parameters
$statusCode : int
$requestHeaders : array<string, string|array<string|int, string>>
$responseHeaders : array<string, string|array<string|int, string>>
$cacheControl : array<string, string|true>
Return values
bool

jsonEncode()

private static jsonEncode(mixed $value[, int|null $flags = null ][, int $maxDepth = 512 ]) : string
Parameters
$value : mixed
$flags : int|null = null
$maxDepth : int = 512
Tags
throws
InvalidArgumentException

When the value cannot be json-encoded

Return values
string

legacyRequest()

private legacyRequest(string $method, string $url[, array<string|int, mixed> $options = [] ]) : ResponseInterface
Parameters
$method : string
$url : string
$options : array<string|int, mixed> = []
Return values
ResponseInterface

mergeDefaultOptions()

private static mergeDefaultOptions(array<string|int, mixed> $options, array<string|int, mixed> $defaultOptions[, bool $allowExtraOptions = false ]) : array<string|int, mixed>
Parameters
$options : array<string|int, mixed>
$defaultOptions : array<string|int, mixed>
$allowExtraOptions : bool = false
Tags
throws
InvalidArgumentException

When an invalid option is found

Return values
array<string|int, mixed>

mergeQueryString()

Merges and encodes a query array with a query string.

private static mergeQueryString(string|null $queryString, array<string|int, mixed> $queryArray, bool $replace) : string|null
Parameters
$queryString : string|null
$queryArray : array<string|int, mixed>
$replace : bool
Tags
throws
InvalidArgumentException

When an invalid query-string value is passed

Return values
string|null

normalizeBody()

private static normalizeBody(array<string|int, mixed>|string|resource|Traversable|Closure $body[, array<string|int, mixed> &$normalizedHeaders = [] ]) : string|resource|Closure
Parameters
$body : array<string|int, mixed>|string|resource|Traversable|Closure
$normalizedHeaders : array<string|int, mixed> = []
Tags
throws
InvalidArgumentException

When an invalid body is passed

Return values
string|resource|Closure

normalizeHeaders()

private static normalizeHeaders(array<string|int, mixed> $headers) : array<string|int, array<string|int, string>>
Parameters
$headers : array<string|int, mixed>
Tags
throws
InvalidArgumentException

When an invalid header is found

Return values
array<string|int, array<string|int, string>>

normalizePeerFingerprint()

private static normalizePeerFingerprint(mixed $fingerprint) : array<string|int, mixed>
Parameters
$fingerprint : mixed
Tags
throws
InvalidArgumentException

When an invalid fingerprint is passed

Return values
array<string|int, mixed>

parseCacheControlHeader()

Parse the Cache-Control header and return an array of directive names as keys and their values as values, or true if the directive has no value.

private static parseCacheControlHeader(array<string, string|array<string|int, string>> $header) : array<string, string|true>
Parameters
$header : array<string, string|array<string|int, string>>

The Cache-Control header as an array of strings

Return values
array<string, string|true>

The parsed Cache-Control directives

parseUrl()

Parses a URL and fixes its encoding if needed.

private static parseUrl(string $url[, array<string|int, mixed> $query = [] ][, array<string|int, mixed> $allowedSchemes = ['http' => 80, 'https' => 443] ]) : array<string|int, mixed>
Parameters
$url : string
$query : array<string|int, mixed> = []
$allowedSchemes : array<string|int, mixed> = ['http' => 80, 'https' => 443]
Tags
throws
InvalidArgumentException

When an invalid URL is passed

Return values
array<string|int, mixed>

prepareRequest()

Validates and normalizes method, URL and options, and merges them with defaults.

private static prepareRequest(string|null $method, string|null $url, array<string|int, mixed> $options[, array<string|int, mixed> $defaultOptions = [] ][, bool $allowExtraOptions = false ]) : array<string|int, mixed>
Parameters
$method : string|null
$url : string|null
$options : array<string|int, mixed>
$defaultOptions : array<string|int, mixed> = []
$allowExtraOptions : bool = false
Tags
throws
InvalidArgumentException

When a not-supported option is found

Return values
array<string|int, mixed>

resolveUrl()

Resolves a URL against a base URI.

private static resolveUrl(array<string|int, mixed> $url, array<string|int, mixed>|null $base[, array<string|int, mixed> $queryDefaults = [] ]) : array<string|int, mixed>
Parameters
$url : array<string|int, mixed>
$base : array<string|int, mixed>|null
$queryDefaults : array<string|int, mixed> = []
Tags
see
https://tools.ietf.org/html/rfc3986#section-5.2.2
throws
InvalidArgumentException

When an invalid URL is passed

Return values
array<string|int, mixed>

shouldBuffer()

private static shouldBuffer(array<string|int, mixed> $headers) : bool
Parameters
$headers : array<string|int, mixed>
Return values
bool

        
On this page

Search results