-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
[cookie_manager] Fix FileSystemException
when saving redirect cookies without a proper host
#1948
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
350a08b
Fixes `FileSystemException: Cannot open file ... (OS Error: Is a dire…
s0nerik 4ec39c3
Fixes `FileSystemException: Cannot open file ... (OS Error: Is a dire…
s0nerik 2220c26
Fixes `FileSystemException: Cannot open file ... (OS Error: Is a dire…
s0nerik 10755a9
Added a test to verify that CookieJar.saveFromResponse() is called wi…
s0nerik 326e1c2
Updated CHANGELOG.md
s0nerik b81020a
Added another test for `CookieJar.saveFromResponse()`
s0nerik c26840c
Update CHANGELOG.md
s0nerik af40b43
📝 Add spec comment
AlexV525 2c4db02
✅ Group tests
AlexV525 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
153 changes: 153 additions & 0 deletions
153
plugins/cookie_manager/test/cookies_persistance_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
import 'dart:collection'; | ||
import 'dart:convert'; | ||
import 'dart:io'; | ||
import 'dart:typed_data'; | ||
|
||
import 'package:cookie_jar/cookie_jar.dart'; | ||
import 'package:dio/dio.dart'; | ||
import 'package:dio/io.dart'; | ||
import 'package:dio_cookie_manager/dio_cookie_manager.dart'; | ||
import 'package:test/fake.dart'; | ||
import 'package:test/test.dart'; | ||
|
||
typedef _FetchCallback = Future<ResponseBody> Function( | ||
RequestOptions options, | ||
Stream<Uint8List>? requestStream, | ||
Future<void>? cancelFuture, | ||
); | ||
|
||
class _TestAdapter implements HttpClientAdapter { | ||
_TestAdapter({required _FetchCallback fetch}) : _fetch = fetch; | ||
|
||
final _FetchCallback _fetch; | ||
final HttpClientAdapter _adapter = IOHttpClientAdapter(); | ||
|
||
@override | ||
Future<ResponseBody> fetch( | ||
RequestOptions options, | ||
Stream<Uint8List>? requestStream, | ||
Future<void>? cancelFuture, | ||
) => | ||
_fetch(options, requestStream, cancelFuture); | ||
|
||
@override | ||
void close({bool force = false}) { | ||
_adapter.close(force: force); | ||
} | ||
} | ||
|
||
class _SaveCall { | ||
_SaveCall(this.uri, this.cookies); | ||
|
||
final String uri; | ||
final String cookies; | ||
|
||
@override | ||
bool operator ==(Object other) => | ||
identical(this, other) || | ||
other is _SaveCall && | ||
runtimeType == other.runtimeType && | ||
uri == other.uri && | ||
cookies == other.cookies; | ||
|
||
@override | ||
int get hashCode => uri.hashCode ^ cookies.hashCode; | ||
|
||
@override | ||
String toString() { | ||
return '_SaveCall{uri: $uri, cookies: $cookies}'; | ||
} | ||
} | ||
|
||
class _FakeCookieJar extends Fake implements CookieJar { | ||
final _saveCalls = <_SaveCall>[]; | ||
|
||
List<_SaveCall> get saveCalls => UnmodifiableListView(_saveCalls); | ||
|
||
@override | ||
Future<List<Cookie>> loadForRequest(Uri uri) async { | ||
return const []; | ||
} | ||
|
||
@override | ||
Future<void> saveFromResponse(Uri uri, List<Cookie> cookies) async { | ||
_saveCalls.add(_SaveCall( | ||
uri.toString(), | ||
cookies.join('; '), | ||
)); | ||
} | ||
} | ||
|
||
void main() { | ||
group('CookieJar.saveFromResponse()', () { | ||
test( | ||
'is called with a full Uri for requests that had relative redirects', | ||
() async { | ||
final cookieJar = _FakeCookieJar(); | ||
final dio = Dio() | ||
..httpClientAdapter = _TestAdapter( | ||
fetch: (options, requestStream, cancelFuture) async => ResponseBody( | ||
Stream.value(Uint8List.fromList(utf8.encode(''))), | ||
HttpStatus.ok, | ||
redirects: [ | ||
RedirectRecord( | ||
HttpStatus.found, | ||
'GET', | ||
Uri(path: 'redirect'), | ||
), | ||
], | ||
headers: { | ||
HttpHeaders.setCookieHeader: ['Cookie1=value1; Path=/'], | ||
}, | ||
), | ||
) | ||
..interceptors.add(CookieManager(cookieJar)) | ||
..options.validateStatus = | ||
(status) => status != null && status >= 200 && status < 400; | ||
|
||
await dio.get('https://test.com'); | ||
expect(cookieJar.saveCalls, [ | ||
_SaveCall( | ||
'https://test.com/redirect', | ||
'Cookie1=value1; Path=/', | ||
), | ||
]); | ||
}, | ||
); | ||
|
||
test( | ||
'saves cookies only for final destination upon non-relative redirects', | ||
() async { | ||
final cookieJar = _FakeCookieJar(); | ||
final dio = Dio() | ||
..httpClientAdapter = _TestAdapter( | ||
fetch: (options, requestStream, cancelFuture) async => ResponseBody( | ||
Stream.value(Uint8List.fromList(utf8.encode(''))), | ||
HttpStatus.ok, | ||
redirects: [ | ||
RedirectRecord( | ||
HttpStatus.found, | ||
'GET', | ||
Uri.parse('https://example.com/redirect'), | ||
), | ||
], | ||
headers: { | ||
HttpHeaders.setCookieHeader: ['Cookie1=value1; Path=/'], | ||
}, | ||
), | ||
) | ||
..interceptors.add(CookieManager(cookieJar)) | ||
..options.validateStatus = | ||
(status) => status != null && status >= 200 && status < 400; | ||
|
||
await dio.get('https://test.com'); | ||
expect(cookieJar.saveCalls, [ | ||
_SaveCall( | ||
'https://example.com/redirect', | ||
'Cookie1=value1; Path=/', | ||
), | ||
]); | ||
}, | ||
); | ||
}); | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have any standards that indicate we should resolve the real dest based on the original one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://www.rfc-editor.org/rfc/rfc7231#section-7.1.2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great. Could you add it as a comment, so we can track it back somedays if we forgot it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@s0nerik