HttpCache - viames/pair GitHub Wiki

Pair framework: HttpCache

Pair\Http\HttpCache provides explicit helpers for HTTP cache validators on read responses.

Use it for endpoints where clients, browsers, or proxies can safely reuse a representation until its validator changes.

Helpers

  • HttpCache::etag(mixed $value, bool $weak = false): string
  • HttpCache::lastModified(DateTimeInterface|int|string $time): string
  • HttpCache::cacheControl(int $maxAge, string $visibility = 'public', bool $mustRevalidate = false): string
  • HttpCache::headers(?string $etag = null, DateTimeInterface|int|string|null $lastModified = null, ?string $cacheControl = null): array
  • HttpCache::isNotModified(?string $etag = null, DateTimeInterface|int|string|null $lastModified = null, ?array $server = null): bool
  • HttpCache::json(mixed $payload, int $httpCode = 200, ?string $etag = null, DateTimeInterface|int|string|null $lastModified = null, ?string $cacheControl = null, ?array $server = null): ResponseInterface
  • HttpCache::notModified(?string $etag = null, DateTimeInterface|int|string|null $lastModified = null, ?string $cacheControl = null): EmptyResponse

JSON read endpoint

use Pair\Http\HttpCache;

public function showAction(): \Pair\Http\ResponseInterface
{
	$data = $this->model->readArticlePayload((int)$this->request->query('id'));
	$etag = HttpCache::etag($data);

	return HttpCache::json(
		$data,
		200,
		$etag,
		$data['updatedAt'],
		HttpCache::cacheControl(300, 'public')
	);
}

When If-None-Match or If-Modified-Since matches the supplied validators, Pair returns 304 Not Modified through EmptyResponse.

List endpoint

For list responses, include every value that affects the representation in the ETag input:

$payload = [
	'data' => $rows,
	'meta' => [
		'page' => $page,
		'perPage' => $perPage,
		'total' => $total,
	],
];

$etag = HttpCache::etag([
	'query' => $_GET,
	'payload' => $payload,
]);

return HttpCache::json($payload, 200, $etag, null, HttpCache::cacheControl(60));

Generated CRUD resources

HTTP caching should stay explicit per action or resource policy. Do not enable it globally for all CRUD responses unless the resource has stable authorization, tenant scope, filters, and serialization.

For generated JSON resources, use HttpCache::json() in custom read actions or in future resource-level cache policy hooks.

Notes

  • Conditional matching is only considered for GET and HEAD.
  • If-None-Match takes precedence over If-Modified-Since.
  • HttpCache::etag() hashes the response representation and does not expose the payload in the header.
  • Cache-Control: no-store is available for sensitive responses.
  • Never cache user-specific or tenant-specific data as public unless the representation is safe for every recipient.

See also: JsonResponse, EmptyResponse, API, CrudController.