Skip to content

Commit 2e698e8

Browse files
faisuctaylorotwell
andauthored
[12.x] Fix Accept header cache invalidation when header is modified (#57874)
* Fix Accept header cache invalidation when header is modified * Update Request.php * formatting --------- Co-authored-by: Taylor Otwell <[email protected]>
1 parent 617e4fc commit 2e698e8

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

src/Illuminate/Http/Request.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ class Request extends SymfonyRequest implements Arrayable, ArrayAccess
6363
*/
6464
protected $routeResolver;
6565

66+
/**
67+
* The cached "Accept" header value.
68+
*
69+
* @var string|null
70+
*/
71+
protected $cachedAcceptHeader;
72+
6673
/**
6774
* Create a new Illuminate HTTP request from server variables.
6875
*
@@ -356,6 +363,23 @@ public function userAgent()
356363
return $this->headers->get('User-Agent');
357364
}
358365

366+
/**
367+
* {@inheritdoc}
368+
*/
369+
#[\Override]
370+
public function getAcceptableContentTypes(): array
371+
{
372+
$currentAcceptHeader = $this->headers->get('Accept');
373+
374+
if ($this->cachedAcceptHeader !== $currentAcceptHeader) {
375+
// Flush acceptable content types so Symfony re-calculates them...
376+
$this->acceptableContentTypes = null;
377+
$this->cachedAcceptHeader = $currentAcceptHeader;
378+
}
379+
380+
return parent::getAcceptableContentTypes();
381+
}
382+
359383
/**
360384
* Merge new input into the current request's input array.
361385
*

tests/Http/HttpRequestTest.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,79 @@ public function testFormatReturnsAcceptsCharset()
14251425
$this->assertTrue($request->accepts('application/baz+json'));
14261426
}
14271427

1428+
public function testWantsJsonRespectsHeaderChanges()
1429+
{
1430+
$request = Request::create('/', 'GET', [], [], [], ['HTTP_ACCEPT' => '*/*']);
1431+
1432+
$this->assertFalse($request->wantsJson());
1433+
1434+
$this->assertTrue($request->acceptsAnyContentType());
1435+
1436+
$request->headers->set('Accept', 'application/json');
1437+
1438+
$this->assertTrue($request->wantsJson(), 'wantsJson() should return true after Accept header is changed to application/json');
1439+
}
1440+
1441+
public function testAcceptsJsonRespectsHeaderChanges()
1442+
{
1443+
$request = Request::create('/', 'GET', [], [], [], ['HTTP_ACCEPT' => '*/*']);
1444+
1445+
$this->assertTrue($request->acceptsAnyContentType());
1446+
1447+
$request->headers->set('Accept', 'application/json');
1448+
1449+
$this->assertTrue($request->acceptsJson(), 'acceptsJson() should return true after Accept header is changed to application/json');
1450+
}
1451+
1452+
public function testPrefersRespectsHeaderChanges()
1453+
{
1454+
$request = Request::create('/', 'GET', [], [], [], ['HTTP_ACCEPT' => '*/*']);
1455+
1456+
$this->assertTrue($request->acceptsAnyContentType());
1457+
1458+
$request->headers->set('Accept', 'application/json');
1459+
1460+
$this->assertSame('json', $request->prefers(['html', 'json']), 'prefers() should return json after Accept header is changed to application/json');
1461+
}
1462+
1463+
public function testWantsJsonWorksWhenHeaderSetBeforeFirstCall()
1464+
{
1465+
$request = Request::create('/', 'GET', [], [], [], []);
1466+
1467+
$request->headers->set('Accept', 'application/json');
1468+
1469+
$this->assertTrue($request->wantsJson(), 'wantsJson() should return true when Accept header is set to application/json');
1470+
}
1471+
1472+
public function testCacheClearedWhenTransitioningFromUnsetToSetHeader()
1473+
{
1474+
$request = Request::create('/', 'GET', [], [], [], []);
1475+
1476+
$request->getAcceptableContentTypes();
1477+
1478+
$request->headers->set('Accept', 'application/json');
1479+
1480+
$this->assertTrue($request->wantsJson(), 'wantsJson() should return true after Accept header is set from null to application/json');
1481+
1482+
$this->assertTrue($request->acceptsJson(), 'acceptsJson() should return true after Accept header is set from null to application/json');
1483+
}
1484+
1485+
public function testAcceptsJsonWorksWhenHeaderChangedMultipleTimes()
1486+
{
1487+
$request = Request::create('/', 'GET', [], [], [], ['HTTP_ACCEPT' => 'text/html']);
1488+
1489+
$this->assertFalse($request->acceptsJson());
1490+
1491+
$request->headers->set('Accept', 'application/json');
1492+
$this->assertTrue($request->acceptsJson());
1493+
1494+
$request->headers->set('Accept', 'text/html');
1495+
$this->assertFalse($request->acceptsJson());
1496+
1497+
$request->headers->set('Accept', 'application/json');
1498+
$this->assertTrue($request->acceptsJson());
1499+
}
1500+
14281501
public function testBadAcceptHeader()
14291502
{
14301503
$request = Request::create('/', 'GET', [], [], [], ['HTTP_ACCEPT' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-PT; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)']);

0 commit comments

Comments
 (0)