Skip to content

Commit 1251619

Browse files
authored
Add the ability to control the URL cache. (#1020)
1 parent decefa6 commit 1251619

File tree

8 files changed

+5585
-4720
lines changed

8 files changed

+5585
-4720
lines changed

pkgs/cupertino_http/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* Disable additional analyses for generated Objective-C bindings to prevent
1010
errors from `dart analyze`.
1111
* Throw `ClientException` when the `'Content-Length'` header is invalid.
12+
* Add support for configurable caching through
13+
`URLSessionConfiguration.cache`.
1214

1315
## 1.0.1
1416

pkgs/cupertino_http/example/integration_test/main.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'error_test.dart' as error_test;
1111
import 'http_url_response_test.dart' as http_url_response_test;
1212
import 'mutable_data_test.dart' as mutable_data_test;
1313
import 'mutable_url_request_test.dart' as mutable_url_request_test;
14+
import 'url_cache_test.dart' as url_cache_test;
1415
import 'url_request_test.dart' as url_request_test;
1516
import 'url_response_test.dart' as url_response_test;
1617
import 'url_session_configuration_test.dart' as url_session_configuration_test;
@@ -34,6 +35,7 @@ void main() {
3435
http_url_response_test.main();
3536
mutable_data_test.main();
3637
mutable_url_request_test.main();
38+
url_cache_test.main();
3739
url_request_test.main();
3840
url_response_test.main();
3941
url_session_configuration_test.main();
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
import 'dart:io';
7+
8+
import 'package:cupertino_http/cupertino_http.dart';
9+
import 'package:integration_test/integration_test.dart';
10+
import 'package:test/test.dart';
11+
12+
void main() {
13+
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
14+
15+
group('dataTaskWithCompletionHandler', () {
16+
late HttpServer server;
17+
var uncachedRequestCount = 0;
18+
19+
setUp(() async {
20+
uncachedRequestCount = 0;
21+
server = (await HttpServer.bind('localhost', 0))
22+
..listen((request) async {
23+
await request.drain<void>();
24+
if (request.headers['if-none-match']?.first == '1234') {
25+
request.response.statusCode = 304;
26+
await request.response.close();
27+
return;
28+
}
29+
++uncachedRequestCount;
30+
request.response.headers.set('Content-Type', 'text/plain');
31+
request.response.headers.set('ETag', '1234');
32+
request.response.write('Hello World');
33+
await request.response.close();
34+
});
35+
});
36+
tearDown(() {
37+
server.close();
38+
});
39+
40+
Future<void> doRequest(URLSession session) {
41+
final request =
42+
URLRequest.fromUrl(Uri.parse('http://localhost:${server.port}'));
43+
final c = Completer<void>();
44+
session.dataTaskWithCompletionHandler(request, (d, r, e) {
45+
c.complete();
46+
}).resume();
47+
return c.future;
48+
}
49+
50+
test('no cache', () async {
51+
final config = URLSessionConfiguration.defaultSessionConfiguration()
52+
..cache = null;
53+
final session = URLSession.sessionWithConfiguration(config);
54+
55+
await doRequest(session);
56+
await doRequest(session);
57+
58+
expect(uncachedRequestCount, 2);
59+
});
60+
61+
test('with cache', () async {
62+
final config = URLSessionConfiguration.defaultSessionConfiguration()
63+
..cache = URLCache.withCapacity(memoryCapacity: 100000);
64+
final session = URLSession.sessionWithConfiguration(config);
65+
66+
await doRequest(session);
67+
await doRequest(session);
68+
69+
expect(uncachedRequestCount, 1);
70+
});
71+
});
72+
}

pkgs/cupertino_http/ffigen.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ headers:
1111
- '/System/Volumes/Data/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSArray.h'
1212
- '/System/Volumes/Data/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSData.h'
1313
- '/System/Volumes/Data/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSDictionary.h'
14+
- '/System/Volumes/Data/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSURLCache.h'
1415
- '/System/Volumes/Data/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSURLRequest.h'
1516
- '/System/Volumes/Data/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSURLSession.h'
1617
- '/System/Volumes/Data/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSURL.h'

pkgs/cupertino_http/lib/src/cupertino_api.dart

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,35 @@ class Error extends _ObjectHolder<ncb.NSError> implements Exception {
233233
']';
234234
}
235235

236+
/// A cache for [URLRequest]s. Used by [URLSessionConfiguration.cache].
237+
///
238+
/// See [NSURLCache](https://developer.apple.com/documentation/foundation/nsurlcache)
239+
class URLCache extends _ObjectHolder<ncb.NSURLCache> {
240+
URLCache._(super.c);
241+
242+
/// The default URLCache.
243+
///
244+
/// See [NSURLCache.sharedURLCache](https://developer.apple.com/documentation/foundation/nsurlcache/1413377-sharedurlcache)
245+
static URLCache? get sharedURLCache {
246+
final sharedCache = ncb.NSURLCache.getSharedURLCache(linkedLibs);
247+
return sharedCache == null ? null : URLCache._(sharedCache);
248+
}
249+
250+
/// Create a new [URLCache] with the given memory and disk cache sizes.
251+
///
252+
/// [memoryCapacity] and [diskCapacity] are specified in bytes.
253+
///
254+
/// [directory] is the file system location where the disk cache will be
255+
/// stored. If `null` then the default directory will be used.
256+
///
257+
/// See [NSURLCache initWithMemoryCapacity:diskCapacity:directoryURL:](https://developer.apple.com/documentation/foundation/nsurlcache/3240612-initwithmemorycapacity)
258+
factory URLCache.withCapacity(
259+
{int memoryCapacity = 0, int diskCapacity = 0, Uri? directory}) =>
260+
URLCache._(ncb.NSURLCache.alloc(linkedLibs)
261+
.initWithMemoryCapacity_diskCapacity_directoryURL_(memoryCapacity,
262+
diskCapacity, directory == null ? null : uriToNSURL(directory)));
263+
}
264+
236265
/// Controls the behavior of a URLSession.
237266
///
238267
/// See [NSURLSessionConfiguration](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration)
@@ -300,6 +329,15 @@ class URLSessionConfiguration
300329
set allowsExpensiveNetworkAccess(bool value) =>
301330
_nsObject.allowsExpensiveNetworkAccess = value;
302331

332+
/// The [URLCache] used to cache the results of [URLSessionTask]s.
333+
///
334+
/// A value of `nil` indicates that no cache will be used.
335+
///
336+
/// See [NSURLSessionConfiguration.URLCache](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1410148-urlcache)
337+
URLCache? get cache =>
338+
_nsObject.URLCache == null ? null : URLCache._(_nsObject.URLCache!);
339+
set cache(URLCache? cache) => _nsObject.URLCache = cache?._nsObject;
340+
303341
/// Whether background tasks can be delayed by the system.
304342
///
305343
/// See [NSURLSessionConfiguration.discretionary](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1411552-discretionary)
@@ -314,10 +352,10 @@ class URLSessionConfiguration
314352
set httpCookieAcceptPolicy(HTTPCookieAcceptPolicy value) =>
315353
_nsObject.HTTPCookieAcceptPolicy = value.index;
316354

317-
// The maximum number of connections that a URLSession can have open to the
318-
// same host.
355+
/// The maximum number of connections that a URLSession can have open to the
356+
/// same host.
319357
//
320-
// See [NSURLSessionConfiguration.HTTPMaximumConnectionsPerHost](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1407597-httpmaximumconnectionsperhost).
358+
/// See [NSURLSessionConfiguration.HTTPMaximumConnectionsPerHost](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1407597-httpmaximumconnectionsperhost).
321359
int get httpMaximumConnectionsPerHost =>
322360
_nsObject.HTTPMaximumConnectionsPerHost;
323361
set httpMaximumConnectionsPerHost(int value) =>
@@ -354,9 +392,9 @@ class URLSessionConfiguration
354392
set networkServiceType(URLRequestNetworkService value) =>
355393
_nsObject.networkServiceType = value.index;
356394

357-
// Controls how to deal with response caching.
358-
//
359-
// See [NSURLSessionConfiguration.requestCachePolicy](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1411655-requestcachepolicy)
395+
/// Controls how to deal with response caching.
396+
///
397+
/// See [NSURLSessionConfiguration.requestCachePolicy](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1411655-requestcachepolicy)
360398
URLRequestCachePolicy get requestCachePolicy =>
361399
URLRequestCachePolicy.values[_nsObject.requestCachePolicy];
362400
set requestCachePolicy(URLRequestCachePolicy value) =>
@@ -422,9 +460,9 @@ class URLSessionConfiguration
422460
class Data extends _ObjectHolder<ncb.NSData> {
423461
Data._(super.c);
424462

425-
// A new [Data] from an existing one.
426-
//
427-
// See [NSData dataWithData:](https://developer.apple.com/documentation/foundation/nsdata/1547230-datawithdata)
463+
/// A new [Data] from an existing one.
464+
///
465+
/// See [NSData dataWithData:](https://developer.apple.com/documentation/foundation/nsdata/1547230-datawithdata)
428466
factory Data.fromData(Data d) =>
429467
Data._(ncb.NSData.dataWithData_(linkedLibs, d._nsObject));
430468

@@ -916,11 +954,8 @@ class URLRequest extends _ObjectHolder<ncb.NSURLRequest> {
916954
/// Creates a request for a URL.
917955
///
918956
/// See [NSURLRequest.requestWithURL:](https://developer.apple.com/documentation/foundation/nsurlrequest/1528603-requestwithurl)
919-
factory URLRequest.fromUrl(Uri uri) {
920-
final url = ncb.NSURL
921-
.URLWithString_(linkedLibs, uri.toString().toNSString(linkedLibs));
922-
return URLRequest._(ncb.NSURLRequest.requestWithURL_(linkedLibs, url));
923-
}
957+
factory URLRequest.fromUrl(Uri uri) => URLRequest._(
958+
ncb.NSURLRequest.requestWithURL_(linkedLibs, uriToNSURL(uri)));
924959

925960
/// Returns all of the HTTP headers for the request.
926961
///
@@ -934,9 +969,9 @@ class URLRequest extends _ObjectHolder<ncb.NSURLRequest> {
934969
}
935970
}
936971

937-
// Controls how to deal with caching for the request.
938-
//
939-
// See [NSURLSession.cachePolicy](https://developer.apple.com/documentation/foundation/nsurlrequest/1407944-cachepolicy)
972+
/// Controls how to deal with caching for the request.
973+
///
974+
/// See [NSURLSession.cachePolicy](https://developer.apple.com/documentation/foundation/nsurlrequest/1407944-cachepolicy)
940975
URLRequestCachePolicy get cachePolicy =>
941976
URLRequestCachePolicy.values[_nsObject.cachePolicy];
942977

0 commit comments

Comments
 (0)