Skip to content

Conversation

@adamziel
Copy link
Collaborator

@adamziel adamziel commented May 30, 2025

What this PR does

Adds a CacheMiddleware that makes the HTTP Client capable of first-class, on-disk HTTP caching. Supports:

  • Request headers: If-None-Match, If-Modified-Since
  • Response headers: Cache-Control, Expires, Vary, ETag, Last-Modified, must-revalidate, s-maxage, max-age, and status-code semantics
  • 304 responses
  • Cache invalidation
// Assuming the cache dir exists
$client = new Client(['cache_dir' => __DIR__.'/.http-cache']);

// Downloads the entire file:
$client->fetch( 'https://wordpress.org/wordpress-latest.zip' )->consume_all();

// Reuses the cached response:
$client->fetch( 'https://wordpress.org/wordpress-latest.zip' )->consume_all();

Why

Network latency is really painful when testing the Blueprints runner. With CacheMiddleware, the same Blueprint can be re-ran multiple times without waiting for the repeated downloads. It should also give the unit tests a large boost.

Implementation

  • CacheMiddleware

    • Caches successful GET/HEAD responses that are explicitly or heuristically cacheable.
    • Respects Cache-Control, Expires, Vary, ETag, Last-Modified, must-revalidate, s-maxage, max-age, and status-code semantics.
    • Stores response metadata at <cache_dir>/<sha1(url)>_<cache_key>.json
    • Stores response body at <cache_dir>/<sha1(url)>_<cache_key>.body
    • Conservative file locking—no race conditions, no tmp files left behind, interrupted responses are not reused.
  • Client wiring

    • Accepts new option cache_dir.
    • Builds the chain: CacheMiddleware → RedirectionMiddleware → HttpMiddleware.
    • Adds get_response() helper and exposes Request::$cache_key.
    • Tightens type hints (Request $request, array $options = [], etc.) and swaps some if(!is_array()) boilerplate for short syntax.

A few bug fixes caught on the way:

  • TcpServer could log undefined variables when the handler blew up; now initialises them and null-checks writes.
  • Minor docblock inaccuracies, unused import in TransportInterface, dead code in ClientTestBase removed.

Testing

Confirm CI Tests pass. One or two may be flaky on window but most runners should be green.

@adamziel adamziel marked this pull request as draft May 30, 2025 13:01
@adamziel adamziel marked this pull request as ready for review May 30, 2025 20:07
@adamziel
Copy link
Collaborator Author

Two flaky tests are failing, I'll take the risk and merge it. Let's tackle any problems as they come up in the Blueprint v2 runner and Data Liberation importers work where this Client will be used the most.

@adamziel adamziel merged commit 6222e29 into trunk May 30, 2025
19 of 21 checks passed
@github-project-automation github-project-automation bot moved this from Inbox to Done in Playground Board May 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects
Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants