Skip to content

Commit 39cf36b

Browse files
committed
Enforce RFC HTTP date semantics
1 parent 6f493b8 commit 39cf36b

1 file changed

Lines changed: 29 additions & 10 deletions

File tree

‎src/Middleware/ResponseCacheMiddleware.php‎

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Componenta\Http\Cache\Protocol\CacheControl;
1313
use Componenta\Http\Cache\Protocol\EntityTag;
1414
use Componenta\Http\Cache\Protocol\HeaderList;
15+
use Componenta\Http\Cache\Protocol\HttpDate;
1516
use Componenta\Http\Cache\Protocol\ResponseAge;
1617
use Componenta\Http\Cache\Store\CachedResponse;
1718
use Componenta\Http\Cache\Store\ResponseCacheStoreInterface;
@@ -97,6 +98,14 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
9798
$requestTime = microtime(true);
9899
$response = $handler->handle($request);
99100
$responseTime = microtime(true);
101+
102+
if (
103+
!$response->hasHeader(Header::DATE)
104+
|| HttpDate::parse($response->getHeaderLine(Header::DATE), (int) $responseTime) === null
105+
) {
106+
$response = $response->withHeader(Header::DATE, HttpDate::format((int) $responseTime));
107+
}
108+
100109
$initialAge = ResponseAge::correctedInitialAge($response, $requestTime, $responseTime);
101110
$ttl = $this->responseTtl($response, $policy, $initialAge, $responseTime);
102111

@@ -274,12 +283,10 @@ private function responseTtl(
274283

275284
$ttl = min($ttl, $remaining);
276285
} elseif ($response->hasHeader(Header::EXPIRES)) {
277-
$expires = strtotime($response->getHeaderLine(Header::EXPIRES));
278-
$date = $response->hasHeader(Header::DATE)
279-
? strtotime($response->getHeaderLine(Header::DATE))
280-
: (int) $responseTime;
286+
$expires = HttpDate::parse($response->getHeaderLine(Header::EXPIRES), (int) $responseTime);
287+
$date = HttpDate::parse($response->getHeaderLine(Header::DATE), (int) $responseTime);
281288

282-
if ($expires === false || $date === false || $expires <= $date) {
289+
if ($expires === null || $date === null || $expires <= $date) {
283290
return null;
284291
}
285292

@@ -290,6 +297,14 @@ private function responseTtl(
290297
}
291298

292299
$ttl = min($ttl, $remaining);
300+
} else {
301+
$remaining = $policy->ttl - $currentAge;
302+
303+
if ($remaining <= 0) {
304+
return null;
305+
}
306+
307+
$ttl = $remaining;
293308
}
294309

295310
return max(1, $ttl);
@@ -408,21 +423,25 @@ private function isNotModified(
408423
return false;
409424
}
410425

411-
$condition = strtotime($request->getHeaderLine(Header::IF_MODIFIED_SINCE));
426+
$condition = HttpDate::parse($request->getHeaderLine(Header::IF_MODIFIED_SINCE));
412427

413-
if ($condition === false) {
428+
if ($condition === null) {
414429
return false;
415430
}
416431

417432
if ($response->hasHeader(Header::LAST_MODIFIED)) {
418-
$validator = strtotime($response->getHeaderLine(Header::LAST_MODIFIED));
433+
$validator = HttpDate::parse($response->getHeaderLine(Header::LAST_MODIFIED));
434+
435+
if ($validator === null) {
436+
return false;
437+
}
419438
} elseif ($response->hasHeader(Header::DATE)) {
420-
$validator = strtotime($response->getHeaderLine(Header::DATE));
439+
$validator = HttpDate::parse($response->getHeaderLine(Header::DATE)) ?? $cached->storedAt;
421440
} else {
422441
$validator = $cached->storedAt;
423442
}
424443

425-
return $validator !== false && $validator <= $condition;
444+
return $validator <= $condition;
426445
}
427446

428447
private function bypassLookup(ServerRequestInterface $request): bool

0 commit comments

Comments
 (0)