Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ability to control the URL cache. #1020

Merged
merged 2 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pkgs/cupertino_http/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* Disable additional analyses for generated Objective-C bindings to prevent
errors from `dart analyze`.
* Throw `ClientException` when the `'Content-Length'` header is invalid.
* Add support for configurable caching through
`URLSessionConfiguration.cache`.

## 1.0.1

Expand Down
2 changes: 2 additions & 0 deletions pkgs/cupertino_http/example/integration_test/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'error_test.dart' as error_test;
import 'http_url_response_test.dart' as http_url_response_test;
import 'mutable_data_test.dart' as mutable_data_test;
import 'mutable_url_request_test.dart' as mutable_url_request_test;
import 'url_cache_test.dart' as url_cache_test;
import 'url_request_test.dart' as url_request_test;
import 'url_response_test.dart' as url_response_test;
import 'url_session_configuration_test.dart' as url_session_configuration_test;
Expand All @@ -34,6 +35,7 @@ void main() {
http_url_response_test.main();
mutable_data_test.main();
mutable_url_request_test.main();
url_cache_test.main();
url_request_test.main();
url_response_test.main();
url_session_configuration_test.main();
Expand Down
72 changes: 72 additions & 0 deletions pkgs/cupertino_http/example/integration_test/url_cache_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:io';

import 'package:cupertino_http/cupertino_http.dart';
import 'package:integration_test/integration_test.dart';
import 'package:test/test.dart';

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('dataTaskWithCompletionHandler', () {
late HttpServer server;
var uncachedRequestCount = 0;

setUp(() async {
uncachedRequestCount = 0;
server = (await HttpServer.bind('localhost', 0))
..listen((request) async {
await request.drain<void>();
if (request.headers['if-none-match']?.first == '1234') {
request.response.statusCode = 304;
await request.response.close();
return;
}
++uncachedRequestCount;
request.response.headers.set('Content-Type', 'text/plain');
request.response.headers.set('ETag', '1234');
request.response.write('Hello World');
await request.response.close();
});
});
tearDown(() {
server.close();
});

Future<void> doRequest(URLSession session) {
final request =
URLRequest.fromUrl(Uri.parse('http://localhost:${server.port}'));
final c = Completer<void>();
session.dataTaskWithCompletionHandler(request, (d, r, e) {
c.complete();
}).resume();
return c.future;
}

test('no cache', () async {
final config = URLSessionConfiguration.defaultSessionConfiguration()
..cache = null;
final session = URLSession.sessionWithConfiguration(config);

await doRequest(session);
await doRequest(session);

expect(uncachedRequestCount, 2);
});

test('with cache', () async {
final config = URLSessionConfiguration.defaultSessionConfiguration()
..cache = URLCache.withCapacity(memoryCapacity: 100000);
final session = URLSession.sessionWithConfiguration(config);

await doRequest(session);
await doRequest(session);

expect(uncachedRequestCount, 1);
});
});
}
1 change: 1 addition & 0 deletions pkgs/cupertino_http/ffigen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ headers:
- '/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'
- '/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'
- '/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'
- '/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'
- '/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'
- '/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'
- '/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'
Expand Down
69 changes: 52 additions & 17 deletions pkgs/cupertino_http/lib/src/cupertino_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,35 @@ class Error extends _ObjectHolder<ncb.NSError> implements Exception {
']';
}

/// A cache for [URLRequest]s. Used by [URLSessionConfiguration.cache].
///
/// See [NSURLCache](https://developer.apple.com/documentation/foundation/nsurlcache)
class URLCache extends _ObjectHolder<ncb.NSURLCache> {
URLCache._(super.c);

/// The default URLCache.
///
/// See [NSURLCache.sharedURLCache](https://developer.apple.com/documentation/foundation/nsurlcache/1413377-sharedurlcache)
static URLCache? get sharedURLCache {
final sharedCache = ncb.NSURLCache.getSharedURLCache(linkedLibs);
return sharedCache == null ? null : URLCache._(sharedCache);
}

/// Create a new [URLCache] with the given memory and disk cache sizes.
///
/// [memoryCapacity] and [diskCapacity] are specified in bytes.
///
/// [directory] is the file system location where the disk cache will be
/// stored. If `null` then the default directory will be used.
///
/// See [NSURLCache initWithMemoryCapacity:diskCapacity:directoryURL:](https://developer.apple.com/documentation/foundation/nsurlcache/3240612-initwithmemorycapacity)
factory URLCache.withCapacity(
{int memoryCapacity = 0, int diskCapacity = 0, Uri? directory}) =>
URLCache._(ncb.NSURLCache.alloc(linkedLibs)
.initWithMemoryCapacity_diskCapacity_directoryURL_(memoryCapacity,
diskCapacity, directory == null ? null : uriToNSURL(directory)));
}

/// Controls the behavior of a URLSession.
///
/// See [NSURLSessionConfiguration](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration)
Expand Down Expand Up @@ -300,6 +329,15 @@ class URLSessionConfiguration
set allowsExpensiveNetworkAccess(bool value) =>
_nsObject.allowsExpensiveNetworkAccess = value;

/// The [URLCache] used to cache the results of [URLSessionTask]s.
///
/// A value of `nil` indicates that no cache will be used.
///
/// See [NSURLSessionConfiguration.URLCache](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1410148-urlcache)
URLCache? get cache =>
_nsObject.URLCache == null ? null : URLCache._(_nsObject.URLCache!);
set cache(URLCache? cache) => _nsObject.URLCache = cache?._nsObject;

/// Whether background tasks can be delayed by the system.
///
/// See [NSURLSessionConfiguration.discretionary](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1411552-discretionary)
Expand All @@ -314,10 +352,10 @@ class URLSessionConfiguration
set httpCookieAcceptPolicy(HTTPCookieAcceptPolicy value) =>
_nsObject.HTTPCookieAcceptPolicy = value.index;

// The maximum number of connections that a URLSession can have open to the
// same host.
/// The maximum number of connections that a URLSession can have open to the
/// same host.
//
// See [NSURLSessionConfiguration.HTTPMaximumConnectionsPerHost](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1407597-httpmaximumconnectionsperhost).
/// See [NSURLSessionConfiguration.HTTPMaximumConnectionsPerHost](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1407597-httpmaximumconnectionsperhost).
int get httpMaximumConnectionsPerHost =>
_nsObject.HTTPMaximumConnectionsPerHost;
set httpMaximumConnectionsPerHost(int value) =>
Expand Down Expand Up @@ -354,9 +392,9 @@ class URLSessionConfiguration
set networkServiceType(URLRequestNetworkService value) =>
_nsObject.networkServiceType = value.index;

// Controls how to deal with response caching.
//
// See [NSURLSessionConfiguration.requestCachePolicy](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1411655-requestcachepolicy)
/// Controls how to deal with response caching.
///
/// See [NSURLSessionConfiguration.requestCachePolicy](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1411655-requestcachepolicy)
URLRequestCachePolicy get requestCachePolicy =>
URLRequestCachePolicy.values[_nsObject.requestCachePolicy];
set requestCachePolicy(URLRequestCachePolicy value) =>
Expand Down Expand Up @@ -422,9 +460,9 @@ class URLSessionConfiguration
class Data extends _ObjectHolder<ncb.NSData> {
Data._(super.c);

// A new [Data] from an existing one.
//
// See [NSData dataWithData:](https://developer.apple.com/documentation/foundation/nsdata/1547230-datawithdata)
/// A new [Data] from an existing one.
///
/// See [NSData dataWithData:](https://developer.apple.com/documentation/foundation/nsdata/1547230-datawithdata)
factory Data.fromData(Data d) =>
Data._(ncb.NSData.dataWithData_(linkedLibs, d._nsObject));

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

/// Returns all of the HTTP headers for the request.
///
Expand All @@ -934,9 +969,9 @@ class URLRequest extends _ObjectHolder<ncb.NSURLRequest> {
}
}

// Controls how to deal with caching for the request.
//
// See [NSURLSession.cachePolicy](https://developer.apple.com/documentation/foundation/nsurlrequest/1407944-cachepolicy)
/// Controls how to deal with caching for the request.
///
/// See [NSURLSession.cachePolicy](https://developer.apple.com/documentation/foundation/nsurlrequest/1407944-cachepolicy)
URLRequestCachePolicy get cachePolicy =>
URLRequestCachePolicy.values[_nsObject.cachePolicy];

Expand Down
Loading
Loading