Skip to content

Commit

Permalink
feat: Cache-Control: max-age as cache trigger added.
Browse files Browse the repository at this point in the history
  • Loading branch information
llfbandit committed Apr 20, 2021
1 parent af9d769 commit 283ba28
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 12 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.2.0
- feat: Cache-Control: max-age as cache trigger added.
- core: update README.md.

## 2.1.1
- fix: refreshForceCache policy added.
Get parity with refresh/request and refreshForceCache/forceCache.
Expand Down
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@
Dio HTTP cache interceptor with multiple stores respecting HTTP directives (or not).

## HTTP directives:
- ETag
- Last-Modified
- Cache-Control
- Date
- Expires
| | |
|-------------------|--------------------------------|
| Cache triggers | ETag |
| | Last-Modified |
| | max-age (Cache-Control) |
| Cache freshness | Date (request date otherwise) |
| | Expires |
| | max-age (Cache-Control) |
| Cache commutators | no-cache (Cache-Control) |
| | no-store (Cache-Control) |
| | |

## Stores
- BackupCacheStore: Combined store with primary and secondary.
Expand Down
17 changes: 11 additions & 6 deletions lib/src/dio_cache_interceptor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ class DioCacheInterceptor extends Interceptor {
options.policy != CachePolicy.refreshForceCache) {
final cacheResp = await _getCacheResponse(request);
if (cacheResp != null) {
if (_shouldReturnCache(options, cacheResp)) {
if (_isCacheValid(options, cacheResp)) {
handler.resolve(cacheResp.toResponse(request, fromNetwork: false));
return;
}

// Update request with cache directives
_addCacheDirectives(request, cacheResp);
_addCacheValidationHeaders(request, cacheResp);
}
}

Expand All @@ -71,7 +71,7 @@ class DioCacheInterceptor extends Interceptor {
await _getCacheStore(options).delete(
options.keyBuilder(response.requestOptions),
);
} else if (_hasCacheDirectives(response, policy: policy)) {
} else if (_shouldStoreResponse(response, policy: policy)) {
// Cache response into store
final cacheResp = await _buildCacheResponse(
options.keyBuilder(response.requestOptions),
Expand Down Expand Up @@ -132,7 +132,10 @@ class DioCacheInterceptor extends Interceptor {
handler.next(err);
}

void _addCacheDirectives(RequestOptions request, CacheResponse response) {
void _addCacheValidationHeaders(
RequestOptions request,
CacheResponse response,
) {
if (response.eTag != null) {
request.headers[ifNoneMatchHeader] = response.eTag;
}
Expand All @@ -142,7 +145,7 @@ class DioCacheInterceptor extends Interceptor {
}
}

bool _hasCacheDirectives(Response response, {CachePolicy? policy}) {
bool _shouldStoreResponse(Response response, {CachePolicy? policy}) {
if (policy == CachePolicy.forceCache ||
policy == CachePolicy.refreshForceCache) {
return true;
Expand All @@ -156,13 +159,15 @@ class DioCacheInterceptor extends Interceptor {
);

if (cacheControl != null) {
final checkedMaxAge = cacheControl.maxAge;
result |= checkedMaxAge != null && checkedMaxAge > 0;
result &= !(cacheControl.noStore ?? false);
}

return result;
}

bool _shouldReturnCache(CacheOptions options, CacheResponse cacheResp) {
bool _isCacheValid(CacheOptions options, CacheResponse cacheResp) {
// Forced cache response
if (options.policy == CachePolicy.forceCache) {
return true;
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Dio HTTP cache interceptor with multiple stores respecting HTTP dir
repository: https://github.com/llfbandit/dio_cache_interceptor
issue_tracker: https://github.com/llfbandit/dio_cache_interceptor/issues

version: 2.1.1
version: 2.2.0

environment:
sdk: ">=2.12.0 <3.0.0"
Expand Down
13 changes: 13 additions & 0 deletions test/cache_interceptor_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -275,4 +275,17 @@ void main() {
final cacheKey = resp.extra[CacheResponse.cacheKey];
expect(cacheKey, isNull);
});

test('Fetch max-age', () async {
final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/max-age');
final cacheKey = resp.extra[CacheResponse.cacheKey];
final cacheResp = await store.get(cacheKey);
expect(cacheResp, isNotNull);

// We're before max-age: 1
expect(cacheResp!.isExpired(), isFalse);
// We're after max-age: 1
await Future.delayed(const Duration(seconds: 1));
expect(cacheResp.isExpired(), isTrue);
});
}
11 changes: 11 additions & 0 deletions test/mock_httpclient_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,17 @@ class MockHttpClientAdapter extends HttpClientAdapter {
},
);
}
case '/max-age':
{
return ResponseBody.fromBytes(
utf8.encode(jsonEncode({'path': uri.path})),
200,
headers: {
Headers.contentTypeHeader: [Headers.jsonContentType],
'cache-control': ['public', 'max-age=1'],
},
);
}
default:
return ResponseBody.fromString('', 404);
}
Expand Down

0 comments on commit 283ba28

Please sign in to comment.