Skip to content

Commit 11a8f43

Browse files
committed
New configuration respectMaxAgeZero
If a server sends "Cache-Control: max-age=0" this might be a misconfiguration on the server; in this case we should ignore it (the behaviour up to now). It might also mean, that the content potentially already expired; for this case this commit provides a new configuration parameter to respect this response.
1 parent 54904e4 commit 11a8f43

File tree

7 files changed

+38
-11
lines changed

7 files changed

+38
-11
lines changed

flutter_cache_manager/README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ you call this method with other height/width parameters.
6060
When your files are stored on Firebase Storage you can use [flutter_cache_manager_firebase](https://pub.dev/packages/flutter_cache_manager_firebase).
6161

6262
## Customize
63-
The cache manager is customizable by creating a new CacheManager. It is very important to not create more than 1
63+
The cache manager is customizable by creating a new CacheManager. It is very important to not create more than one
6464
CacheManager instance with the same key as these bite each other. In the example down here the manager is created as a
6565
Singleton, but you could also use for example Provider to Provide a CacheManager on the top level of your app.
6666
Below is an example with other settings for the maximum age of files, maximum number of objects
@@ -85,6 +85,7 @@ class CustomCacheManager {
8585
- [How are the cache files stored?](#how-are-the-cache-files-stored)
8686
- [When are the cached files updated?](#when-are-the-cached-files-updated)
8787
- [When are cached files removed?](#when-are-cached-files-removed)
88+
- [Why are cached files kept even though the server sends max-age=0?](#why-are-cached-files-kept-even-though-the-server-sends-max-age0)
8889

8990

9091
### How are the cache files stored?
@@ -113,6 +114,18 @@ The cache knows when files have been used latest. When cleaning the cache (which
113114
deletes files when there are too many, ordered by last use, and when files just haven't been used for longer than
114115
the stale period.
115116

117+
### Why are cached files kept even though the server sends max-age=0?
118+
119+
The case when a web server responds with `Cache-Control: max-age=0` is kind of an edge case.
120+
It could either mean, that the content expires really fast (then `Cache-Control: no-cache` might
121+
be a better response) or it could be that the server has some misconfiguration in place.
122+
123+
There where some confusions among users of this library because of the second case (see also
124+
[this issue](https://github.com/Baseflow/flutter_cache_manager/issues/283) so as a default
125+
behaviour this library ignores `max-age=0`.
126+
127+
If you want to treat `max-age=0` the same as `no-cache`, then set the `Config` parameter
128+
`respectMaxAgeZero` to `true`.
116129

117130
## Breaking changes in v2
118131
- There is no longer a need to extend on BaseCacheManager, you can directly call the constructor. The BaseCacheManager

flutter_cache_manager/lib/src/config/_config_io.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ class Config implements def.Config {
1111
CacheInfoRepository? repo,
1212
FileSystem? fileSystem,
1313
FileService? fileService,
14+
bool? respectMaxAgeZero,
1415
}) : stalePeriod = stalePeriod ?? const Duration(days: 30),
1516
maxNrOfCacheObjects = maxNrOfCacheObjects ?? 200,
1617
repo = repo ?? _createRepo(cacheKey),
1718
fileSystem = fileSystem ?? IOFileSystem(cacheKey),
18-
fileService = fileService ?? HttpFileService();
19+
fileService = fileService ??
20+
HttpFileService(respectMaxAgeZero: respectMaxAgeZero ?? false);
1921

2022
@override
2123
final CacheInfoRepository repo;

flutter_cache_manager/lib/src/config/_config_unsupported.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ class Config implements def.Config {
1818
FileSystem? fileSystem,
1919
//ignore: avoid_unused_constructor_parameters
2020
FileService? fileService,
21+
//ignore: avoid_unused_constructor_parameters
22+
bool? respectMaxAgeZero,
2123
}) {
2224
throw UnsupportedError('Platform is not supported');
2325
}

flutter_cache_manager/lib/src/config/_config_web.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ class Config implements def.Config {
1212
CacheInfoRepository? repo,
1313
FileSystem? fileSystem,
1414
FileService? fileService,
15+
bool? respectMaxAgeZero,
1516
}) : stalePeriod = stalePeriod ?? const Duration(days: 30),
1617
maxNrOfCacheObjects = maxNrOfCacheObjects ?? 200,
1718
repo = repo ?? NonStoringObjectProvider(),
1819
fileSystem = fileSystem ?? MemoryCacheSystem(),
19-
fileService = fileService ?? HttpFileService();
20+
fileService = fileService ??
21+
HttpFileService(respectMaxAgeZero: respectMaxAgeZero ?? false);
2022

2123
@override
2224
final CacheInfoRepository repo;

flutter_cache_manager/lib/src/config/config.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,18 @@ abstract class Config {
2020
/// [JsonCacheInfoRepository].
2121
/// The [fileSystem] defines where the cached files are stored and the
2222
/// [fileService] defines where files are fetched, for example online.
23+
/// If an http response contains a cache-control header with max-age=0 this
24+
/// might mean that the content expires really fast or it could be a
25+
/// misconfiguration of the server. With [respectMaxAgeZero] one can
26+
/// control the lib's behaviour in this case.
2327
factory Config(
2428
String cacheKey, {
2529
Duration stalePeriod,
2630
int maxNrOfCacheObjects,
2731
CacheInfoRepository repo,
2832
FileSystem fileSystem,
2933
FileService fileService,
34+
bool respectMaxAgeZero,
3035
}) = impl.Config;
3136

3237
String get cacheKey;

flutter_cache_manager/lib/src/web/file_service.dart

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ abstract class FileService {
2323
/// [WebHelper]. One can easily adapt it to use dio or any other http client.
2424
class HttpFileService extends FileService {
2525
final http.Client _httpClient;
26+
final bool _respectMaxAgeZero;
2627

27-
HttpFileService({http.Client? httpClient})
28-
: _httpClient = httpClient ?? http.Client();
28+
HttpFileService({http.Client? httpClient, bool? respectMaxAgeZero})
29+
: _httpClient = httpClient ?? http.Client(),
30+
_respectMaxAgeZero = respectMaxAgeZero ?? false;
2931

3032
@override
3133
Future<FileServiceResponse> get(String url,
@@ -36,7 +38,7 @@ class HttpFileService extends FileService {
3638
}
3739
final httpResponse = await _httpClient.send(req);
3840

39-
return HttpGetResponse(httpResponse);
41+
return HttpGetResponse(httpResponse, _respectMaxAgeZero);
4042
}
4143
}
4244

@@ -64,12 +66,14 @@ abstract class FileServiceResponse {
6466

6567
/// Basic implementation of a [FileServiceResponse] for http requests.
6668
class HttpGetResponse implements FileServiceResponse {
67-
HttpGetResponse(this._response);
69+
HttpGetResponse(this._response, this._respectMaxAgeZero);
6870

6971
final DateTime _receivedTime = clock.now();
7072

7173
final http.StreamedResponse _response;
7274

75+
final bool _respectMaxAgeZero;
76+
7377
@override
7478
int get statusCode => _response.statusCode;
7579

@@ -98,7 +102,7 @@ class HttpGetResponse implements FileServiceResponse {
98102
if (sanitizedSetting.startsWith('max-age=')) {
99103
final validSeconds =
100104
int.tryParse(sanitizedSetting.split('=')[1]) ?? 0;
101-
if (validSeconds > 0) {
105+
if (validSeconds > 0 || _respectMaxAgeZero) {
102106
ageDuration = Duration(seconds: validSeconds);
103107
}
104108
}

flutter_cache_manager/lib/src/web/web_helper.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ const statusCodesNewFile = [HttpStatus.ok, HttpStatus.accepted];
1818
const statusCodesFileNotChanged = [HttpStatus.notModified];
1919

2020
class WebHelper {
21-
WebHelper(this._store, FileService? fileFetcher)
22-
: _memCache = {},
23-
fileFetcher = fileFetcher ?? HttpFileService();
21+
WebHelper(this._store, this.fileFetcher)
22+
: _memCache = {};
2423

2524
final CacheStore _store;
2625
@visibleForTesting

0 commit comments

Comments
 (0)