Skip to content

Commit 27ae8bb

Browse files
authored
fix: DownloadResponse cache headers (codeigniter4#9237)
* fix: `DownloadResponse` cache headers * update phpstan-baseline
1 parent bb5f925 commit 27ae8bb

File tree

5 files changed

+49
-31
lines changed

5 files changed

+49
-31
lines changed

phpstan-baseline.php

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5869,12 +5869,6 @@
58695869
'count' => 2,
58705870
'path' => __DIR__ . '/system/HTTP/DownloadResponse.php',
58715871
];
5872-
$ignoreErrors[] = [
5873-
// identifier: missingType.iterableValue
5874-
'message' => '#^Method CodeIgniter\\\\HTTP\\\\DownloadResponse\\:\\:setCache\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#',
5875-
'count' => 1,
5876-
'path' => __DIR__ . '/system/HTTP/DownloadResponse.php',
5877-
];
58785872
$ignoreErrors[] = [
58795873
// identifier: method.childReturnType
58805874
'message' => '#^Return type \\(CodeIgniter\\\\HTTP\\\\DownloadResponse\\) of method CodeIgniter\\\\HTTP\\\\DownloadResponse\\:\\:sendBody\\(\\) should be covariant with return type \\(\\$this\\(CodeIgniter\\\\HTTP\\\\Response\\)\\) of method CodeIgniter\\\\HTTP\\\\Response\\:\\:sendBody\\(\\)$#',

system/Exceptions/DownloadException.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ public static function forNotFoundDownloadSource()
4747
}
4848

4949
/**
50+
* @deprecated Since v4.5.6
51+
*
5052
* @return static
5153
*/
5254
public static function forCannotSetCache()

system/HTTP/DownloadResponse.php

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -242,16 +242,6 @@ public function noCache(): self
242242
return $this;
243243
}
244244

245-
/**
246-
* Disables cache configuration.
247-
*
248-
* @throws DownloadException
249-
*/
250-
public function setCache(array $options = [])
251-
{
252-
throw DownloadException::forCannotSetCache();
253-
}
254-
255245
/**
256246
* {@inheritDoc}
257247
*
@@ -290,10 +280,8 @@ public function buildHeaders()
290280
$this->setHeader('Content-Disposition', $this->getContentDisposition());
291281
}
292282

293-
$this->setHeader('Expires-Disposition', '0');
294283
$this->setHeader('Content-Transfer-Encoding', 'binary');
295284
$this->setHeader('Content-Length', (string) $this->getContentLength());
296-
$this->noCache();
297285
}
298286

299287
/**

tests/system/HTTP/DownloadResponseTest.php

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,25 @@ public function testNoCache(): void
148148
$this->assertSame('private, no-transform, no-store, must-revalidate', $response->getHeaderLine('Cache-control'));
149149
}
150150

151-
public function testCantSetCache(): void
151+
public function testSetCache(): void
152152
{
153153
$response = new DownloadResponse('unit-test.txt', true);
154154

155-
$this->expectException(DownloadException::class);
156-
$response->setCache();
155+
$date = date('r');
156+
157+
$options = [
158+
'etag' => '12345678',
159+
'last-modified' => $date,
160+
'max-age' => 300,
161+
'must-revalidate',
162+
];
163+
164+
$response->setCache($options);
165+
$response->buildHeaders();
166+
167+
$this->assertSame('12345678', $response->getHeaderLine('ETag'));
168+
$this->assertSame($date, $response->getHeaderLine('Last-Modified'));
169+
$this->assertSame('max-age=300, must-revalidate', $response->getHeaderLine('Cache-Control'));
157170
}
158171

159172
public function testWhenFilepathIsSetBinaryCanNotBeSet(): void
@@ -200,30 +213,53 @@ public function testCanGetContentLength(): void
200213
$this->assertSame($size, $response->getContentLength());
201214
}
202215

203-
public function testIsSetDownloadableHeadlersFromBinary(): void
216+
public function testIsSetDownloadableHeadersFromBinary(): void
204217
{
205218
$response = new DownloadResponse('unit test.txt', false);
206219

207220
$response->setBinary('test');
208221
$response->buildHeaders();
209222

223+
$this->assertSame('private, no-transform, no-store, must-revalidate', $response->getHeaderLine('Cache-Control'));
210224
$this->assertSame('application/octet-stream', $response->getHeaderLine('Content-Type'));
211225
$this->assertSame('attachment; filename="unit test.txt"; filename*=UTF-8\'\'unit%20test.txt', $response->getHeaderLine('Content-Disposition'));
212-
$this->assertSame('0', $response->getHeaderLine('Expires-Disposition'));
213226
$this->assertSame('binary', $response->getHeaderLine('Content-Transfer-Encoding'));
214227
$this->assertSame('4', $response->getHeaderLine('Content-Length'));
215228
}
216229

217-
public function testIsSetDownloadableHeadlersFromFile(): void
230+
public function testIsSetDownloadableHeadersFromFile(): void
231+
{
232+
$response = new DownloadResponse('unit-test.php', false);
233+
234+
$response->setFilePath(__FILE__);
235+
$response->buildHeaders();
236+
237+
$this->assertSame('private, no-transform, no-store, must-revalidate', $response->getHeaderLine('Cache-Control'));
238+
$this->assertSame('application/octet-stream', $response->getHeaderLine('Content-Type'));
239+
$this->assertSame('attachment; filename="unit-test.php"; filename*=UTF-8\'\'unit-test.php', $response->getHeaderLine('Content-Disposition'));
240+
$this->assertSame('binary', $response->getHeaderLine('Content-Transfer-Encoding'));
241+
$this->assertSame(filesize(__FILE__), (int) $response->getHeaderLine('Content-Length'));
242+
}
243+
244+
public function testCustomHeaders(): void
218245
{
219246
$response = new DownloadResponse('unit-test.php', false);
220247

221248
$response->setFilePath(__FILE__);
249+
250+
$response->setHeader('Last-Modified', 'Fri, 18 Oct 2024 13:17:37 GMT');
251+
$response->setHeader('Expires', 'Sun, 17 Nov 2024 14:17:37 GMT');
252+
$response->setHeader('Pragma', 'public');
253+
$response->removeHeader('Cache-Control');
254+
$response->setHeader('Cache-Control', 'public');
222255
$response->buildHeaders();
223256

257+
$this->assertSame('Fri, 18 Oct 2024 13:17:37 GMT', $response->getHeaderLine('Last-Modified'));
258+
$this->assertSame('Sun, 17 Nov 2024 14:17:37 GMT', $response->getHeaderLine('Expires'));
259+
$this->assertSame('public', $response->getHeaderLine('Pragma'));
260+
$this->assertSame('public', $response->getHeaderLine('Cache-Control'));
224261
$this->assertSame('application/octet-stream', $response->getHeaderLine('Content-Type'));
225262
$this->assertSame('attachment; filename="unit-test.php"; filename*=UTF-8\'\'unit-test.php', $response->getHeaderLine('Content-Disposition'));
226-
$this->assertSame('0', $response->getHeaderLine('Expires-Disposition'));
227263
$this->assertSame('binary', $response->getHeaderLine('Content-Transfer-Encoding'));
228264
$this->assertSame(filesize(__FILE__), (int) $response->getHeaderLine('Content-Length'));
229265
}

user_guide_src/source/changelogs/v4.5.6.rst

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,14 @@ Deprecations
2929
**********
3030
Bugs Fixed
3131
**********
32-
- **RequestTrait:** Fixed a bug where the ``fetchGlobal()`` method did not allow handling data by numeric key when stored as a list.
3332

33+
- **RequestTrait:** Fixed a bug where the ``fetchGlobal()`` method did not allow handling data by numeric key when stored as a list.
3434
- **Session Library:** The session initialization debug message now uses the correct log type "debug" instead of "info".
35-
36-
- **Validation:** Fixed the `getValidated()` method that did not return valid data when validation rules used multiple asterisks.
37-
35+
- **Validation:** Fixed the ``getValidated()`` method that did not return valid data when validation rules used multiple asterisks.
3836
- **Database:** Fixed the case insensitivity option in the ``like()`` method when dealing with accented characters.
39-
4037
- **Parser:** Fixed bug that caused equal key names to be replaced by the key name defined first.
41-
38+
- **DownloadResponse:** Fixed a bug that prevented setting custom cache headers. We can now also use the ``setCache()`` method.
39+
- **DownloadResponse:** Fixed a bug involving sending a custom "Expires-Disposition" header.
4240
- **Routing:** Fixed a TypeError in `str_replace()` when `Routing::$translateURIDashes` is set to `true` and a route is defined using a closure.
4341

4442
- **Validation:** Fixed a bug where complex language strings were not properly handled.

0 commit comments

Comments
 (0)