@@ -335,8 +335,8 @@ $data = await(retry(
335335
336336Fetch PHP automatically retries transient failures with exponential backoff.
337337
338- - Default: No retries enabled (set ` maxRetries ` to null by default)
339- - Default delay: 100ms base with exponential backoff (when retries configured)
338+ - Default: 1 retry attempt ( ` ClientHandler::DEFAULT_RETRIES ` ) with a 100 ms base delay
339+ - Default delay: 100 ms base with exponential backoff (when retries configured)
340340- Retry triggers:
341341 - Network/connect errors (e.g., ConnectException)
342342 - HTTP status codes: 408, 429, 500, 502, 503, 504, 507, 509, 520-523, 525, 527, 530 (customizable)
@@ -569,15 +569,14 @@ $response = $handler->get('https://api.example.com/users');
569569
570570``` php
571571$handler->withCache(null, [
572- 'ttl ' => 3600, // Default TTL in seconds (overridden by Cache-Control)
573- 'respect_headers ' => true, // Respect Cache-Control headers (default: true)
574- 'is_shared_cache' => false, // Act as shared cache (respects s-maxage)
575- 'stale_while_revalidate' => 60, // Serve stale for 60s while revalidating
576- 'stale_if_error' => 300, // Serve stale for 300s if backend fails
572+ 'default_ttl ' => 3600, // Default TTL in seconds (overridden by Cache-Control)
573+ 'respect_cache_headers ' => true, // Honor Cache-Control headers (default: true)
574+ 'is_shared_cache' => false, // Act as shared cache (respects s-maxage)
575+ 'stale_while_revalidate' => 60, // Serve stale for 60s while revalidating
576+ 'stale_if_error' => 300, // Serve stale for 300s if backend fails
577577 'vary_headers' => ['Accept', 'Accept-Language'], // Headers to vary cache by
578- 'cache_methods' => ['GET', 'HEAD'], // Cacheable HTTP methods
579- 'cache_status_codes' => [200, 301], // Cacheable status codes
580- 'force_refresh' => false, // Bypass cache and force fresh request
578+ 'cache_methods' => ['GET', 'HEAD'], // Cacheable HTTP methods
579+ 'cache_status_codes' => [200, 301], // Cacheable status codes
581580]);
582581```
583582
@@ -595,6 +594,23 @@ $response = $handler->withOptions(['cache' => ['ttl' => 600]])
595594// Custom cache key
596595$response = $handler->withOptions(['cache' => ['key' => 'custom:users']])
597596 ->get('https://api.example.com/users');
597+
598+ // Cache POST/PUT payloads (requires allowing the method globally)
599+ $handler->withCache(null, [
600+ 'cache_methods' => ['GET', 'HEAD', 'POST'],
601+ ]);
602+ $report = $handler->withOptions([
603+ 'cache' => [
604+ 'ttl' => 120,
605+ 'cache_body' => true, // include the JSON body in the cache key
606+ ],
607+ ])->post('https://api.example.com/reports', ['range' => 'weekly']);
608+
609+ Useful patterns:
610+
611+ - **Force refresh**: set `force_refresh => true` on the request to ignore stored entries.
612+ - **Cache POST/PUT**: allow the verb in `cache_methods` via `withCache()` and set `cache_body => true` so the request body participates in the cache key.
613+ - **Static assets**: pin a custom `key` for predictable lookups regardless of URL params.
598614```
599615
600616## Connection Pooling & HTTP/2
@@ -614,9 +630,12 @@ $handler->withConnectionPool([
614630 'enabled' => true,
615631 'max_connections' => 50, // Total connections across all hosts
616632 'max_per_host' => 10, // Max connections per host
617- 'connection_ttl' => 60, // Connection lifetime in seconds
618- 'idle_timeout' => 30, // Idle connection timeout in seconds
633+ 'max_idle_per_host' => 5, // Idle sockets kept per host
634+ 'keep_alive_timeout' => 60, // Connection lifetime in seconds
635+ 'connection_timeout' => 5, // Dial timeout in seconds
619636 'dns_cache_ttl' => 300, // DNS cache TTL in seconds
637+ 'connection_warmup' => false,
638+ 'warmup_connections' => 0,
620639]);
621640```
622641
@@ -638,7 +657,7 @@ $handler->withHttp2([
638657``` php
639658// Get pool statistics
640659$stats = $handler->getPoolStats();
641- // Returns: connections_created, connections_reused, total_requests, total_latency_ms
660+ // Returns: connections_created, connections_reused, total_requests, average_latency, reuse_rate
642661
643662// Close all active connections
644663$handler->closeAllConnections();
@@ -678,34 +697,45 @@ $handler->withLogLevel('info'); // default: debug
678697
679698$response = $handler->get('https://api.example.com/users');
680699
681- // Get debug info from last request
682- $debug = $handler->getLastDebugInfo();
700+ // Preferred: read per-response debug snapshot
701+ $responseDebug = $response->getDebugInfo();
702+
703+ // Legacy fallback for BC: handler-level snapshot (may lag in concurrent flows)
704+ $lastDebug = $handler->getLastDebugInfo();
683705```
684706
685707## Testing Support
686708
687709Fetch PHP includes built-in testing utilities for mocking HTTP responses:
688710
689711``` php
712+ use Fetch\Testing\MockServer;
690713use Fetch\Testing\MockResponse;
691- use Fetch\Testing\MockResponseSequence;
692714
693715// Mock a single response
694- $handler = fetch_client()->getHandler();
695- $handler->mock(MockResponse::make(['id' => 1, 'name' => 'John'], 200));
716+ MockServer::fake([
717+ 'GET https://api.example.com/users/1' => MockResponse::json([
718+ 'id' => 1,
719+ 'name' => 'Ada Lovelace',
720+ ]),
721+ ]);
696722
697- $response = $handler->get('https://api.example.com/users/1');
698- // Returns mocked response without making actual HTTP request
723+ $response = fetch('https://api.example.com/users/1');
724+ // Returns mocked response without making an actual HTTP request
725+ MockServer::assertSent('GET https://api.example.com/users/1');
699726
700727// Mock a sequence of responses
701- $sequence = new MockResponseSequence([
702- MockResponse::make(['id' => 1], 200),
703- MockResponse::make(['id' => 2], 200),
704- MockResponse::make(null, 404),
728+ MockServer::fake([
729+ 'https://api.example.com/users/*' => MockResponse::sequence([
730+ MockResponse::json(['id' => 1]),
731+ MockResponse::json(['id' => 2]),
732+ MockResponse::notFound(),
733+ ]),
705734]);
706735
707- $handler->mock($sequence);
708- // Each subsequent request returns the next response in sequence
736+ fetch('https://api.example.com/users/alpha'); // gets id 1
737+ fetch('https://api.example.com/users/beta'); // gets id 2
738+ fetch('https://api.example.com/users/omega'); // 404 from sequence
709739```
710740
711741## Advanced Response Features
@@ -764,7 +794,7 @@ $handler->resetPool();
764794
765795// Get pool statistics
766796$stats = $handler->getPoolStats();
767- // Returns: connections_created, connections_reused, total_requests, total_latency_ms
797+ // Returns: connections_created, connections_reused, total_requests, average_latency, reuse_rate
768798```
769799
770800## Async Notes
0 commit comments