Skip to content

Commit 8180363

Browse files
Merge branch '4.4' into 5.3
* 4.4: Fix composer.json versions Fix composer.json versions Remove redundant license info [HttpFoundation] Fix isNotModified determination logic Fix Url Validator false positives [Translation] Reverse fallback locales [FrameworkBundle] Fall back to default configuration in debug:config and consistently resolve parameter values allow null for framework.translator.default_path improve failure messages of the CrawlerSelectorTextContains constraint
2 parents abeecbf + 69f0b8c commit 8180363

File tree

3 files changed

+57
-10
lines changed

3 files changed

+57
-10
lines changed

Request.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1599,7 +1599,7 @@ public function toArray()
15991599
*/
16001600
public function getETags()
16011601
{
1602-
return preg_split('/\s*,\s*/', $this->headers->get('if_none_match', ''), -1, \PREG_SPLIT_NO_EMPTY);
1602+
return preg_split('/\s*,\s*/', $this->headers->get('If-None-Match', ''), -1, \PREG_SPLIT_NO_EMPTY);
16031603
}
16041604

16051605
/**

Response.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,12 +1090,27 @@ public function isNotModified(Request $request): bool
10901090
$lastModified = $this->headers->get('Last-Modified');
10911091
$modifiedSince = $request->headers->get('If-Modified-Since');
10921092

1093-
if ($etags = $request->getETags()) {
1094-
$notModified = \in_array($this->getEtag(), $etags) || \in_array('*', $etags);
1095-
}
1093+
if ($ifNoneMatchEtags = $request->getETags()) {
1094+
$etag = $this->getEtag();
1095+
if (0 == strncmp($etag, 'W/', 2)) {
1096+
$etag = substr($etag, 2);
1097+
}
1098+
1099+
// Use weak comparison as per https://tools.ietf.org/html/rfc7232#section-3.2.
1100+
foreach ($ifNoneMatchEtags as $ifNoneMatchEtag) {
1101+
if (0 == strncmp($ifNoneMatchEtag, 'W/', 2)) {
1102+
$ifNoneMatchEtag = substr($ifNoneMatchEtag, 2);
1103+
}
10961104

1097-
if ($modifiedSince && $lastModified) {
1098-
$notModified = strtotime($modifiedSince) >= strtotime($lastModified) && (!$etags || $notModified);
1105+
if ($ifNoneMatchEtag === $etag || '*' === $ifNoneMatchEtag) {
1106+
$notModified = true;
1107+
break;
1108+
}
1109+
}
1110+
}
1111+
// Only do If-Modified-Since date comparison when If-None-Match is not present as per https://tools.ietf.org/html/rfc7232#section-3.3.
1112+
elseif ($modifiedSince && $lastModified) {
1113+
$notModified = strtotime($modifiedSince) >= strtotime($lastModified);
10991114
}
11001115

11011116
if ($notModified) {

Tests/ResponseTest.php

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ public function testIsNotModifiedEtag()
197197
$etagTwo = 'randomly_generated_etag_2';
198198

199199
$request = new Request();
200-
$request->headers->set('if_none_match', sprintf('%s, %s, %s', $etagOne, $etagTwo, 'etagThree'));
200+
$request->headers->set('If-None-Match', sprintf('%s, %s, %s', $etagOne, $etagTwo, 'etagThree'));
201201

202202
$response = new Response();
203203

@@ -209,6 +209,38 @@ public function testIsNotModifiedEtag()
209209

210210
$response->headers->set('ETag', '');
211211
$this->assertFalse($response->isNotModified($request));
212+
213+
// Test wildcard
214+
$request = new Request();
215+
$request->headers->set('If-None-Match', '*');
216+
217+
$response->headers->set('ETag', $etagOne);
218+
$this->assertTrue($response->isNotModified($request));
219+
}
220+
221+
public function testIsNotModifiedWeakEtag()
222+
{
223+
$etag = 'randomly_generated_etag';
224+
$weakEtag = 'W/randomly_generated_etag';
225+
226+
$request = new Request();
227+
$request->headers->set('If-None-Match', $etag);
228+
$response = new Response();
229+
230+
$response->headers->set('ETag', $etag);
231+
$this->assertTrue($response->isNotModified($request));
232+
233+
$response->headers->set('ETag', $weakEtag);
234+
$this->assertTrue($response->isNotModified($request));
235+
236+
$request->headers->set('If-None-Match', $weakEtag);
237+
$response = new Response();
238+
239+
$response->headers->set('ETag', $etag);
240+
$this->assertTrue($response->isNotModified($request));
241+
242+
$response->headers->set('ETag', $weakEtag);
243+
$this->assertTrue($response->isNotModified($request));
212244
}
213245

214246
public function testIsNotModifiedLastModifiedAndEtag()
@@ -219,14 +251,14 @@ public function testIsNotModifiedLastModifiedAndEtag()
219251
$etag = 'randomly_generated_etag';
220252

221253
$request = new Request();
222-
$request->headers->set('if_none_match', sprintf('%s, %s', $etag, 'etagThree'));
254+
$request->headers->set('If-None-Match', sprintf('%s, %s', $etag, 'etagThree'));
223255
$request->headers->set('If-Modified-Since', $modified);
224256

225257
$response = new Response();
226258

227259
$response->headers->set('ETag', $etag);
228260
$response->headers->set('Last-Modified', $after);
229-
$this->assertFalse($response->isNotModified($request));
261+
$this->assertTrue($response->isNotModified($request));
230262

231263
$response->headers->set('ETag', 'non-existent-etag');
232264
$response->headers->set('Last-Modified', $before);
@@ -243,7 +275,7 @@ public function testIsNotModifiedIfModifiedSinceAndEtagWithoutLastModified()
243275
$etag = 'randomly_generated_etag';
244276

245277
$request = new Request();
246-
$request->headers->set('if_none_match', sprintf('%s, %s', $etag, 'etagThree'));
278+
$request->headers->set('If-None-Match', sprintf('%s, %s', $etag, 'etagThree'));
247279
$request->headers->set('If-Modified-Since', $modified);
248280

249281
$response = new Response();

0 commit comments

Comments
 (0)