diff --git a/system/Cache/ResponseCache.php b/system/Cache/ResponseCache.php index d0f15fdff184..636f250f5b5e 100644 --- a/system/Cache/ResponseCache.php +++ b/system/Cache/ResponseCache.php @@ -86,7 +86,7 @@ public function generateCacheKey($request): string ? $uri->getQuery(is_array($this->cacheQueryString) ? ['only' => $this->cacheQueryString] : []) : ''; - return md5((string) $uri->setFragment('')->setQuery($query)); + return md5($request->getMethod() . ':' . $uri->setFragment('')->setQuery($query)); } /** diff --git a/system/HTTP/Method.php b/system/HTTP/Method.php index 5a08aa87387e..ee3a09ec4b0d 100644 --- a/system/HTTP/Method.php +++ b/system/HTTP/Method.php @@ -19,57 +19,81 @@ class Method { /** + * Safe: No + * Idempotent: No + * Cacheable: No + * * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/CONNECT */ public const CONNECT = 'CONNECT'; /** - * Idempotent + * Safe: No + * Idempotent: Yes + * Cacheable: No * * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE */ public const DELETE = 'DELETE'; /** - * Safe, Idempotent, Cacheable + * Safe: Yes + * Idempotent: Yes + * Cacheable: Yes * * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET */ public const GET = 'GET'; /** - * Safe, Idempotent, Cacheable + * Safe: Yes + * Idempotent: Yes + * Cacheable: Yes * * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD */ public const HEAD = 'HEAD'; /** - * Safe, Idempotent + * Safe: Yes + * Idempotent: Yes + * Cacheable: No * * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS */ public const OPTIONS = 'OPTIONS'; /** + * Safe: No + * Idempotent: No + * Cacheable: Only if freshness information is included + * * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH */ public const PATCH = 'PATCH'; /** + * Safe: No + * Idempotent: No + * Cacheable: Only if freshness information is included + * * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST */ public const POST = 'POST'; /** - * Idempotent + * Safe: No + * Idempotent: Yes + * Cacheable: No * * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT */ public const PUT = 'PUT'; /** - * Safe, Idempotent + * Safe: Yes + * Idempotent: Yes + * Cacheable: No * * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/TRACE */ diff --git a/tests/system/Cache/ResponseCacheTest.php b/tests/system/Cache/ResponseCacheTest.php index e04162c05b35..b973bff2c2d1 100644 --- a/tests/system/Cache/ResponseCacheTest.php +++ b/tests/system/Cache/ResponseCacheTest.php @@ -169,6 +169,26 @@ public function testCachePageIncomingRequestWithCacheQueryString() $this->assertNull($cachedResponse); } + public function testCachePageIncomingRequestWithHttpMethods() + { + $pageCache = $this->createResponseCache(); + + $request = $this->createIncomingRequest('foo/bar'); + + $response = new Response($this->appConfig); + $response->setBody('The response body.'); + + $return = $pageCache->make($request, $response); + + $this->assertTrue($return); + + // Check cache with a request with the same URI path and different HTTP method + $request = $this->createIncomingRequest('foo/bar')->withMethod('POST'); + $cachedResponse = $pageCache->get($request, new Response($this->appConfig)); + + $this->assertNull($cachedResponse); + } + public function testCachePageCLIRequest() { $pageCache = $this->createResponseCache(); diff --git a/user_guide_src/source/changelogs/v4.5.0.rst b/user_guide_src/source/changelogs/v4.5.0.rst index 79e6feda7190..52c49500fe91 100644 --- a/user_guide_src/source/changelogs/v4.5.0.rst +++ b/user_guide_src/source/changelogs/v4.5.0.rst @@ -348,6 +348,9 @@ Others existing CSP directives. See :ref:`csp-clear-directives`. - **HTTP:** Added ``Message::addHeader()`` method to add another header with the same name. See :php:meth:`CodeIgniter\\HTTP\\Message::addHeader()`. +- **Web Page Caching:** ``ResponseCache`` has been improved to include the request + HTTP method in the cache key. This means that the same URI will be cached separately + if the HTTP method is different. Message Changes *************** diff --git a/user_guide_src/source/general/caching.rst b/user_guide_src/source/general/caching.rst index 4d2426e30c26..23856561b0c0 100644 --- a/user_guide_src/source/general/caching.rst +++ b/user_guide_src/source/general/caching.rst @@ -20,11 +20,17 @@ How Does Caching Work? ====================== Caching can be enabled on a per-page basis, and you can set the length -of time that a page should remain cached before being refreshed. When a -page is loaded for the first time, the page will be cached using the +of time that a page should remain cached before being refreshed. + +.. note:: Per-page means per URI. Since v4.5.0, the HTTP method of the + request is also taken into account. This means that the same URI will be + cached separately if the HTTP method is different. + +When a page is loaded for the first time, the page will be cached using the currently configured cache engine. On subsequent page loads, the cache -will be retrieved and sent to the requesting user's browser. If it has -expired, it will be deleted and refreshed before being sent to the +will be retrieved and sent to the requesting user's browser. + +If it has expired, it will be deleted and refreshed before being sent to the browser. .. note:: The Benchmark tag is not cached so you can still view your page