From e9dba5c915a97e50fb5998b8c2155d6b742220dc Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Mon, 8 Jul 2024 22:45:56 +0200 Subject: [PATCH 1/9] fix: remove unknown nodoc annotations Signed-off-by: Nikolas Rimikis --- lib/src/file_storage.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/src/file_storage.dart b/lib/src/file_storage.dart index 94aa0a7..121531f 100644 --- a/lib/src/file_storage.dart +++ b/lib/src/file_storage.dart @@ -21,11 +21,9 @@ class FileStorage implements Storage { /// A storage can be used across different jars, so this cannot be final. late String _currentDirectory; - /// {@nodoc} @visibleForTesting final bool shouldCreateDirectory; - /// {@nodoc} @visibleForTesting String get currentDirectory => _currentDirectory; From efa66e3f918f5deda86fb293c30eba601629b626 Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Fri, 19 Apr 2024 08:46:44 +0200 Subject: [PATCH 2/9] refactor!: user FutureOr on the interface to allow for synchronous implementation Signed-off-by: Nikolas Rimikis --- lib/src/cookie_jar.dart | 10 ++++++---- lib/src/jar/default.dart | 10 ++++++---- lib/src/jar/web.dart | 8 ++++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/lib/src/cookie_jar.dart b/lib/src/cookie_jar.dart index 36903f3..58169ff 100644 --- a/lib/src/cookie_jar.dart +++ b/lib/src/cookie_jar.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:universal_io/io.dart' show Cookie; import 'jar/default.dart'; @@ -20,14 +22,14 @@ abstract class CookieJar { final bool ignoreExpires = false; /// Save the [cookies] for specified [uri]. - Future saveFromResponse(Uri uri, List cookies); + FutureOr saveFromResponse(Uri uri, List cookies); /// Load the cookies for specified [uri]. - Future> loadForRequest(Uri uri); + FutureOr> loadForRequest(Uri uri); /// Delete all cookies in the [CookieJar]. - Future deleteAll(); + FutureOr deleteAll(); /// Delete cookies with the specified [uri]. - Future delete(Uri uri, [bool withDomainSharedCookie = false]); + FutureOr delete(Uri uri, [bool withDomainSharedCookie = false]); } diff --git a/lib/src/jar/default.dart b/lib/src/jar/default.dart index 4a0f936..7e7abb3 100644 --- a/lib/src/jar/default.dart +++ b/lib/src/jar/default.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:universal_io/io.dart' show Cookie; import '../cookie_jar.dart'; @@ -88,7 +90,7 @@ class DefaultCookieJar implements CookieJar { } @override - Future> loadForRequest(Uri uri) async { + FutureOr> loadForRequest(Uri uri) { final list = []; final urlPath = uri.path; // Load cookies without "domain" attribute, include port. @@ -137,7 +139,7 @@ class DefaultCookieJar implements CookieJar { } @override - Future saveFromResponse(Uri uri, List cookies) async { + FutureOr saveFromResponse(Uri uri, List cookies) { for (final cookie in cookies) { String? domain = cookie.domain; String path; @@ -174,7 +176,7 @@ class DefaultCookieJar implements CookieJar { /// /// [withDomainSharedCookie] `true` will delete the domain-shared cookies. @override - Future delete(Uri uri, [bool withDomainSharedCookie = false]) async { + FutureOr delete(Uri uri, [bool withDomainSharedCookie = false]) { final host = uri.host; hostCookies.remove(host); if (withDomainSharedCookie) { @@ -186,7 +188,7 @@ class DefaultCookieJar implements CookieJar { /// Delete all cookies stored in the memory. @override - Future deleteAll() async { + FutureOr deleteAll() { domainCookies.clear(); hostCookies.clear(); } diff --git a/lib/src/jar/web.dart b/lib/src/jar/web.dart index 50c5577..1301c31 100644 --- a/lib/src/jar/web.dart +++ b/lib/src/jar/web.dart @@ -11,14 +11,14 @@ class WebCookieJar implements CookieJar { final bool ignoreExpires; @override - Future delete(Uri uri, [bool withDomainSharedCookie = false]) async {} + void delete(Uri uri, [bool withDomainSharedCookie = false]) {} @override - Future deleteAll() async {} + void deleteAll() {} @override - Future> loadForRequest(Uri uri) async => []; + List loadForRequest(Uri uri) => []; @override - Future saveFromResponse(Uri uri, List cookies) async {} + void saveFromResponse(Uri uri, List cookies) {} } From 50cd79aad3726005459a2c6a839fa7eb8c4fcd1c Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Sat, 13 Apr 2024 17:34:46 +0200 Subject: [PATCH 3/9] refactor!: make CookieJar interface implementation independant Signed-off-by: Nikolas Rimikis --- lib/src/cookie_jar.dart | 7 ++----- lib/src/jar/default.dart | 15 +++++++++++++-- lib/src/jar/persist.dart | 9 +++++++++ lib/src/jar/web.dart | 7 ++----- test/cookie_jar_test.dart | 4 +++- test/web_test.dart | 1 - 6 files changed, 29 insertions(+), 14 deletions(-) diff --git a/lib/src/cookie_jar.dart b/lib/src/cookie_jar.dart index 58169ff..1df61e2 100644 --- a/lib/src/cookie_jar.dart +++ b/lib/src/cookie_jar.dart @@ -18,9 +18,6 @@ abstract class CookieJar { return DefaultCookieJar(ignoreExpires: ignoreExpires); } - /// Whether the [CookieJar] should ignore expired cookies during saves/loads. - final bool ignoreExpires = false; - /// Save the [cookies] for specified [uri]. FutureOr saveFromResponse(Uri uri, List cookies); @@ -30,6 +27,6 @@ abstract class CookieJar { /// Delete all cookies in the [CookieJar]. FutureOr deleteAll(); - /// Delete cookies with the specified [uri]. - FutureOr delete(Uri uri, [bool withDomainSharedCookie = false]); + /// Removes all cookies in this jar that satisfy the given [test]. + FutureOr deleteWhere(bool Function(Cookie cookie) test); } diff --git a/lib/src/jar/default.dart b/lib/src/jar/default.dart index 7e7abb3..9620309 100644 --- a/lib/src/jar/default.dart +++ b/lib/src/jar/default.dart @@ -15,7 +15,6 @@ import '../serializable_cookie.dart'; class DefaultCookieJar implements CookieJar { DefaultCookieJar({this.ignoreExpires = false}); - @override final bool ignoreExpires; /// An array to save cookies. @@ -175,7 +174,7 @@ class DefaultCookieJar implements CookieJar { /// This API will delete all cookies for the `uri.host`, it will ignored the `uri.path`. /// /// [withDomainSharedCookie] `true` will delete the domain-shared cookies. - @override + @Deprecated('Use deleteWhere instead') FutureOr delete(Uri uri, [bool withDomainSharedCookie = false]) { final host = uri.host; hostCookies.remove(host); @@ -208,4 +207,16 @@ class DefaultCookieJar implements CookieJar { final list = path.split('/')..removeLast(); return list.join('/'); } + + @override + void deleteWhere(bool Function(Cookie cookie) test) { + // Traverse all manages cookies and delete entries matching `test`. + for (final group in _cookies) { + for (final domainPair in group.values) { + for (final pathPair in domainPair.values) { + pathPair.removeWhere((key, value) => test(value.cookie)); + } + } + } + } } diff --git a/lib/src/jar/persist.dart b/lib/src/jar/persist.dart index 71bba99..db71f21 100644 --- a/lib/src/jar/persist.dart +++ b/lib/src/jar/persist.dart @@ -161,6 +161,15 @@ class PersistCookieJar extends DefaultCookieJar { } } + @override + Future deleteWhere(bool Function(Cookie cookie) test) async { + await _checkInitialized(); + super.deleteWhere(test); + + await storage.write(_indexKey, json.encode(_hostSet.toList())); + await storage.write(_domainsKey, json.encode(domainCookies)); + } + /// Delete all cookies files in the [storage] and the memory. @override Future deleteAll() async { diff --git a/lib/src/jar/web.dart b/lib/src/jar/web.dart index 1301c31..d3bcb2c 100644 --- a/lib/src/jar/web.dart +++ b/lib/src/jar/web.dart @@ -5,13 +5,10 @@ import '../cookie_jar.dart'; /// A [WebCookieJar] will do nothing to handle cookies /// since they are already handled by XHRs. class WebCookieJar implements CookieJar { - WebCookieJar({this.ignoreExpires = false}); + WebCookieJar(); @override - final bool ignoreExpires; - - @override - void delete(Uri uri, [bool withDomainSharedCookie = false]) {} + void deleteWhere(bool Function(Cookie cookie) test) {} @override void deleteAll() {} diff --git a/test/cookie_jar_test.dart b/test/cookie_jar_test.dart index 1022685..159fcf8 100644 --- a/test/cookie_jar_test.dart +++ b/test/cookie_jar_test.dart @@ -163,17 +163,19 @@ void main() async { }); test('DeleteDomainSharedCookie', () async { - final cj = CookieJar(); + final cj = DefaultCookieJar(); final cookies = [ Cookie('JSESSIONID', 'wendux')..domain = '.mozilla.org', ]; await cj.saveFromResponse(Uri.parse('https://www.mozilla.org/'), cookies); + // ignore: deprecated_member_use_from_same_package await cj.delete(Uri.parse('https://www.fakemozilla.org/'), true); final results1 = await cj.loadForRequest(Uri.parse('https://www.mozilla.org/')); expect(results1.length, 1); + // ignore: deprecated_member_use_from_same_package await cj.delete(Uri.parse('https://developer.mozilla.org/'), true); final results2 = await cj.loadForRequest(Uri.parse('https://www.mozilla.org/')); diff --git a/test/web_test.dart b/test/web_test.dart index 0795a94..dfbfcf4 100644 --- a/test/web_test.dart +++ b/test/web_test.dart @@ -6,7 +6,6 @@ void main() { test('Constructed a WebCookieJar', () async { final cj = CookieJar(); expect(cj, isA()); - await cj.delete(Uri()); await cj.deleteAll(); await cj.saveFromResponse(Uri(), []); final cookies = await cj.loadForRequest(Uri()); From 08cfb104244381998860f4e6740daac3ae586e9e Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Sat, 13 Apr 2024 17:38:32 +0200 Subject: [PATCH 4/9] feat: add ability to end the user session removing non persitent cookies as defined by RFC6265 Signed-off-by: Nikolas Rimikis --- lib/src/cookie_jar.dart | 28 ++++++++++++++++++++++++++-- lib/src/jar/default.dart | 26 +++++++++++++++++++++++++- lib/src/jar/web.dart | 6 ++++++ test/cookie_jar_test.dart | 19 +++++++++++++++++++ 4 files changed, 76 insertions(+), 3 deletions(-) diff --git a/lib/src/cookie_jar.dart b/lib/src/cookie_jar.dart index 1df61e2..0bcea3f 100644 --- a/lib/src/cookie_jar.dart +++ b/lib/src/cookie_jar.dart @@ -24,9 +24,33 @@ abstract class CookieJar { /// Load the cookies for specified [uri]. FutureOr> loadForRequest(Uri uri); - /// Delete all cookies in the [CookieJar]. + /// Ends the current session deleting all session cookies. + FutureOr endSession(); + + /// Loads all cookies in the jar. + /// + /// User agents SHOULD provide users with a mechanism for managing the cookies stored in the cookie jar. + /// https://www.rfc-editor.org/rfc/rfc6265.html#section-7.2 + /// + /// Implementing this method is optional. It must be documented if the + /// implementer does not support this operation. + FutureOr> loadAll(); + + /// Deletes all cookies in the jar. + /// + /// User agents SHOULD provide users with a mechanism for managing the cookies stored in the cookie jar. + /// https://www.rfc-editor.org/rfc/rfc6265.html#section-7.2 + /// + /// Implementing this method is optional. It must be documented if the + /// implementer does not support this operation. FutureOr deleteAll(); - /// Removes all cookies in this jar that satisfy the given [test]. + /// Removes all cookies in this store that satisfy the given [test]. + /// + /// User agents SHOULD provide users with a mechanism for managing the cookies stored in the cookie store. + /// https://www.rfc-editor.org/rfc/rfc6265.html#section-7.2 + /// + /// Implementing this method is optional. It must be documented if the + /// implementer does not support this operation. FutureOr deleteWhere(bool Function(Cookie cookie) test); } diff --git a/lib/src/jar/default.dart b/lib/src/jar/default.dart index 9620309..4c371b5 100644 --- a/lib/src/jar/default.dart +++ b/lib/src/jar/default.dart @@ -210,7 +210,7 @@ class DefaultCookieJar implements CookieJar { @override void deleteWhere(bool Function(Cookie cookie) test) { - // Traverse all manages cookies and delete entries matching `test`. + // Traverse all managed cookies and delete entries matching `test`. for (final group in _cookies) { for (final domainPair in group.values) { for (final pathPair in domainPair.values) { @@ -219,4 +219,28 @@ class DefaultCookieJar implements CookieJar { } } } + + @override + void endSession() { + deleteWhere((cookie) { + return cookie.expires == null && cookie.maxAge == null; + }); + } + + @override + FutureOr> loadAll() { + final list = []; + + for (final group in _cookies) { + for (final domainPair in group.values) { + for (final pathPair in domainPair.values) { + for (final value in pathPair.values) { + list.add(value.cookie); + } + } + } + } + + return list; + } } diff --git a/lib/src/jar/web.dart b/lib/src/jar/web.dart index d3bcb2c..a6fc637 100644 --- a/lib/src/jar/web.dart +++ b/lib/src/jar/web.dart @@ -18,4 +18,10 @@ class WebCookieJar implements CookieJar { @override void saveFromResponse(Uri uri, List cookies) {} + + @override + void endSession() {} + + @override + List loadAll() => []; } diff --git a/test/cookie_jar_test.dart b/test/cookie_jar_test.dart index 159fcf8..7a8bef6 100644 --- a/test/cookie_jar_test.dart +++ b/test/cookie_jar_test.dart @@ -275,6 +275,25 @@ void main() async { expect(otherResults, isEmpty); }); + test('Delete session cookies', () async { + final cj = CookieJar(); + await cj.saveFromResponse( + Uri(host: 'example.com', path: '/'), + cookies, + ); + await cj.saveFromResponse( + Uri(host: 'mozilla.org', path: '/'), + cookiesExpired, + ); + + var results = await cj.loadAll(); + expect(results, hasLength(4)); + + await cj.endSession(); + results = await cj.loadAll(); + expect(results, hasLength(2)); + }); + group('FileStorage', () { test('Parsed directory correctly', () async { final s1 = FileStorage.test('./test/cookies'); From c1561c3f279a40763f4a80c1b8655d1db54178c2 Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Fri, 19 Apr 2024 09:12:48 +0200 Subject: [PATCH 5/9] chore: improve documentation Signed-off-by: Nikolas Rimikis --- example/encryption.dart | 2 +- lib/src/cookie_jar.dart | 58 ++++++++++++++++++++++++++++++++++++++- lib/src/jar/default.dart | 5 ++++ lib/src/jar/persist.dart | 3 +- test/cookie_jar_test.dart | 3 ++ 5 files changed, 68 insertions(+), 3 deletions(-) diff --git a/example/encryption.dart b/example/encryption.dart index 4be8a5f..530e205 100644 --- a/example/encryption.dart +++ b/example/encryption.dart @@ -17,7 +17,7 @@ void main() async { final cj = PersistCookieJar(ignoreExpires: true, storage: storage); final uri = Uri.parse('https://xxx.xxx.com/'); - await cj.delete(uri); + await cj.deleteWhere((cookie) => cookie.domain == uri.host); List results; final cookie = Cookie('test', 'hh') ..expires = DateTime.parse('1970-02-27 13:27:00'); diff --git a/lib/src/cookie_jar.dart b/lib/src/cookie_jar.dart index 0bcea3f..5378c65 100644 --- a/lib/src/cookie_jar.dart +++ b/lib/src/cookie_jar.dart @@ -9,8 +9,64 @@ const _kIsWeb = bool.hasEnvironment('dart.library.js_util') ? bool.fromEnvironment('dart.library.js_util') : identical(0, 0.0); -/// [CookieJar] is a cookie container and manager for HTTP requests. +/// [CookieJar] is a cookie container and manager for HTTP requests implementing [RFC6265](https://www.rfc-editor.org/rfc/rfc6265.html). +/// +/// ## Implementation considerations +/// In most cases it is not needed to implement this interface. +/// Use a `PersistCookieJar` with a custom [Storage] backend. +/// +/// ### Cookie value retrieval +/// A cookie jar does not need to retrieve cookies with all attributes present. +/// Retrieved cookies only need to have a valid [Cookie.name] and [Cookie.value]. +/// It is up to the implementation to provide further information. +/// +/// ### Cookie management +/// According to [RFC6265 section 7.2](https://www.rfc-editor.org/rfc/rfc6265.html#section-7.2) +/// user agents SHOULD provide users with a mechanism for managing the cookies stored in the cookie jar. +/// It must be documented if an implementer does not provide any of the optional +/// [loadAll], [deleteAll] and [deleteWhere] methods. +/// +/// ### Public suffix validation +/// The default implementation does not validate the cookie domain against a public +/// suffix list: +/// > NOTE: A "public suffix" is a domain that is controlled by a public +/// > registry, such as "com", "co.uk", and "pvt.k12.wy.us". This step is +/// > essential for preventing attacker.com from disrupting the integrity of +/// > example.com by setting a cookie with a Domain attribute of "com". +/// > Unfortunately, the set of public suffixes (also known as "registry controlled domains") +/// > changes over time. If feasible, user agents SHOULD use an up-to-date +/// > public suffix list, such as the one maintained by the Mozilla project at . +/// +/// ### CookieJar limits and eviction policy +/// If a cookie jar has a limit to the number of cookies it can store, +/// the removal policy outlined in [RFC6265 section 5.3](https://www.rfc-editor.org/rfc/rfc6265.html#section-5.3) +/// must be followed: +/// > At any time, the user agent MAY "remove excess cookies" from the cookie store +/// > if the number of cookies sharing a domain field exceeds some implementation-defined +/// > upper bound (such as 50 cookies). +/// > +/// > At any time, the user agent MAY "remove excess cookies" from the cookie store +/// > if the cookie store exceeds some predetermined upper bound (such as 3000 cookies). +/// > +/// > When the user agent removes excess cookies from the cookie store, the user agent MUST +/// > evict cookies in the following priority order: +/// > +/// > Expired cookies. +/// > Cookies that share a domain field with more than a predetermined number of other cookies. +/// > All cookies. +/// > +/// > If two cookies have the same removal priority, the user agent MUST evict the +/// > cookie with the earliest last-access date first. +/// +/// It is recommended to set an upper bound to the time a cookie is stored +/// as described in [RFC6265 section 7.3](https://www.rfc-editor.org/rfc/rfc6265.html#section-7.3): +/// > Although servers can set the expiration date for cookies to the distant future, +/// > most user agents do not actually retain cookies for multiple decades. +/// > Rather than choosing gratuitously long expiration periods, servers SHOULD +/// > promote user privacy by selecting reasonable cookie expiration periods based on the purpose of the cookie. +/// > For example, a typical session identifier might reasonably be set to expire in two weeks. abstract class CookieJar { + /// Creates a [DefaultCookieJar] instance or a dummy [WebCookieJar] if run in a browser. factory CookieJar({bool ignoreExpires = false}) { if (_kIsWeb) { return WebCookieJar(); diff --git a/lib/src/jar/default.dart b/lib/src/jar/default.dart index 4c371b5..f609cc0 100644 --- a/lib/src/jar/default.dart +++ b/lib/src/jar/default.dart @@ -12,6 +12,11 @@ import '../serializable_cookie.dart'; /// cleared after the app exited. /// /// In order to save cookies into storages, use [PersistCookieJar] instead. +/// +/// ### Public suffix validation +/// This cookie jar implementation does not validate the cookie domain against a +/// public suffix list: +/// {@macro CookieJar.publicSuffix} class DefaultCookieJar implements CookieJar { DefaultCookieJar({this.ignoreExpires = false}); diff --git a/lib/src/jar/persist.dart b/lib/src/jar/persist.dart index db71f21..21034ac 100644 --- a/lib/src/jar/persist.dart +++ b/lib/src/jar/persist.dart @@ -10,7 +10,7 @@ import 'default.dart'; /// [PersistCookieJar] is a cookie manager which implements /// the standard cookie policy declared in RFC. /// [PersistCookieJar] persists the cookies in files, if the application exit, -/// the cookies always exist unless user explicitly called [delete]. +/// the cookies always exist unless user explicitly deleted with [deleteWhere]. class PersistCookieJar extends DefaultCookieJar { /// [persistSession] is whether persisting the cookies that without /// "expires" or "max-age" attribute. @@ -147,6 +147,7 @@ class PersistCookieJar extends DefaultCookieJar { /// This API will delete all cookies for the `uri.host`, it will ignored the `uri.path`. /// /// [withDomainSharedCookie] `true` will delete the domain-shared cookies. + @Deprecated('Use deleteWhere instead') @override Future delete(Uri uri, [bool withDomainSharedCookie = false]) async { await _checkInitialized(); diff --git a/test/cookie_jar_test.dart b/test/cookie_jar_test.dart index 7a8bef6..21d8977 100644 --- a/test/cookie_jar_test.dart +++ b/test/cookie_jar_test.dart @@ -195,6 +195,7 @@ void main() async { List results = await cj.loadForRequest(Uri.parse('https://tt.facebook.com/xxx')); expect(results.length, 1); + // ignore: deprecated_member_use_from_same_package await cj.delete(Uri.parse('https://www.facebook.com/')); results = await cj.loadForRequest(Uri.parse('https://tt.facebook.com/xxx')); @@ -207,6 +208,7 @@ void main() async { storage: FileStorage('./test/cookies'), ); final uri = Uri.parse('https://xxx.com/'); + // ignore: deprecated_member_use_from_same_package await cj.delete(uri); List results; @@ -240,6 +242,7 @@ void main() async { ); final uri = Uri.parse('https://xxx.xxx.com/'); + // ignore: deprecated_member_use_from_same_package await cj.delete(uri); List results; final cookie = Cookie('test', 'hh') From 08b66c455d7e6efd4b7a581404115599c83b8ca3 Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Fri, 19 Apr 2024 09:31:32 +0200 Subject: [PATCH 6/9] docs: add migration guide for 5.0.0 Signed-off-by: Nikolas Rimikis --- migration_guide.md | 32 ++++++++++++++++++++++++++++++++ pubspec.yaml | 4 ++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/migration_guide.md b/migration_guide.md index 299a378..5f7fad6 100644 --- a/migration_guide.md +++ b/migration_guide.md @@ -10,6 +10,38 @@ When new content need to be added to the migration guide, make sure they're foll ## Breaking versions +# NEXT + +Version 5.0 brings a few refinements to the `CookieJar` interface. +Breaking changes include: + +- Usage of `FutureOr` in interfaces. + Going forward a CookieJar can also return synchronously. If every call is + properly awaited nothing should break. + Usage in an `unawaited` method is no longer possible. The `WebCookieJar` has + been migrated to always complete synchronously. + +- Changing cookie deletion: + To allow implementers further flexibility the `delete` method has been removed + from the `CookieJar` interface. Users should migrate to the more flexible + `deleteWhere` method: + ```dart + final jar = CookieJar(); + // Check what cookies you want to have deleted. + jar.deleteWhere((cookie) { + cookie.domain == 'example.com' || cookie.name == 'cookie1'; + })); + ``` + +- Optional cookie management interface: + Cookie management interfaces like `deleteAll`, `deleteWhere` or `loadAll` have + been made optional. It is up to the implementer to support these operations. + Consult your implementers documentation. + +- Optional extra cookie parameters: + When loading cookies in any way from the store (`loadForRequest`, `deleteWhere` or `loadAll`) + implementers only have to provide the `Cookie.name` and `Cookie.value` attributes. + - [4.0.0](#400) # 4.0.0 diff --git a/pubspec.yaml b/pubspec.yaml index 687a69e..0607656 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,11 +1,11 @@ name: cookie_jar description: A cookie manager for http requests in Dart, help you to deal with the cookie policies and persistence. -version: 4.0.8 +version: 5.0.0 repository: https://github.com/flutterchina/cookie_jar issue_tracker: https://github.com/flutterchina/cookie_jar/issues environment: - sdk: '>=2.15.0 <3.0.0' + sdk: ">=2.15.0 <3.0.0" dependencies: meta: ^1.5.0 From 99356ca4740a55aa6864f95e29260533f524ce11 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Fri, 27 Feb 2026 14:59:23 +0800 Subject: [PATCH 7/9] Fix comment macro --- lib/src/cookie_jar.dart | 4 +++- lib/src/jar/default.dart | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/src/cookie_jar.dart b/lib/src/cookie_jar.dart index 5378c65..ac5190a 100644 --- a/lib/src/cookie_jar.dart +++ b/lib/src/cookie_jar.dart @@ -28,7 +28,8 @@ const _kIsWeb = bool.hasEnvironment('dart.library.js_util') /// /// ### Public suffix validation /// The default implementation does not validate the cookie domain against a public -/// suffix list: +/// suffix list. +/// {@template CookieJar.publicSuffixNote} /// > NOTE: A "public suffix" is a domain that is controlled by a public /// > registry, such as "com", "co.uk", and "pvt.k12.wy.us". This step is /// > essential for preventing attacker.com from disrupting the integrity of @@ -36,6 +37,7 @@ const _kIsWeb = bool.hasEnvironment('dart.library.js_util') /// > Unfortunately, the set of public suffixes (also known as "registry controlled domains") /// > changes over time. If feasible, user agents SHOULD use an up-to-date /// > public suffix list, such as the one maintained by the Mozilla project at . +/// {@endtemplate} /// /// ### CookieJar limits and eviction policy /// If a cookie jar has a limit to the number of cookies it can store, diff --git a/lib/src/jar/default.dart b/lib/src/jar/default.dart index f609cc0..26a4c07 100644 --- a/lib/src/jar/default.dart +++ b/lib/src/jar/default.dart @@ -15,8 +15,8 @@ import '../serializable_cookie.dart'; /// /// ### Public suffix validation /// This cookie jar implementation does not validate the cookie domain against a -/// public suffix list: -/// {@macro CookieJar.publicSuffix} +/// public suffix list. +/// {@macro CookieJar.publicSuffixNote} class DefaultCookieJar implements CookieJar { DefaultCookieJar({this.ignoreExpires = false}); From 87ad8c0f348a015e3c5e81228c3a358e26ceea12 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Fri, 27 Feb 2026 15:03:29 +0800 Subject: [PATCH 8/9] Fix docs --- CHANGELOG.md | 7 +++++++ migration_guide.md | 30 +++++++++++++++--------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2864af8..c59286d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # CHANGELOG +## NEXT + +- `CookieJar` now returns `FutureOr` instead of `Future` for all methods. +- Deprecates `delete` in favor of `deleteWhere`. +- Adds `loadAll` to get all saved Cookies. +- Adds `endSession` to delete all session Cookies. + ## 4.0.8 - Simply replace `\` to `/` rather than using `Uri` when parsing a storage base directory. diff --git a/migration_guide.md b/migration_guide.md index 5f7fad6..b4a3b2f 100644 --- a/migration_guide.md +++ b/migration_guide.md @@ -1,6 +1,6 @@ # Migration Guide -This document gathered all breaking changes and migrations requirement between versions. +This document gathered all breaking changes and migration requirements between versions.