Support for configuring the browser `fetch` credentials mode in `BrowserClient`. (#1937)
* add enum for omit value
* add changelog and new version
* Add requestCredentials parameter to BrowserClient to support full fetch credentials modes
- Introduce `RequestCredentials` enum (`omit`, `same-origin`, `include`).
- Deprecate `withCredentials` getter and setter while maintaining full backwards compatibility.
- Update README.md with instructions on how to use the new parameter.
- Add unit tests verifying correct constructor initialization and fallback behaviors.
* - Reverted README.md changes; the feature is now documented exclusively in the class/constructor Dartdoc.
- Cut down the constructor documentation to remove references to historical behavior.
- Cleaned up the changelog entry by moving the note under the existing `1.6.1-wip` section and reverted the pubspec version bump.
- Removed the unnecessary browser unit/integration tests.
* Update pkgs/http/CHANGELOG.md
Co-authored-by: Brian Quinlan <bquinlan@google.com>
* refactor(http): encapsulate fetch credentials mode and clean up BrowserClient API
- Move `_requestCredentials` field declaration above the constructor to match style guide.
- Remove the public `requestCredentials` getter to keep the new feature internal.
- Update Dartdoc for the deprecated `withCredentials` getter to reference the constructor parameter instead of the private field.
- Revert unintended version bumps, changelog additions, and README notes.
- Remove browser integration tests per maintainer request.
* style: wrap long line in browser_client documentation
---------
Co-authored-by: Brian Quinlan <bquinlan@google.com>
diff --git a/pkgs/http/CHANGELOG.md b/pkgs/http/CHANGELOG.md
index 3be69e3..ea78c6f 100644
--- a/pkgs/http/CHANGELOG.md
+++ b/pkgs/http/CHANGELOG.md
@@ -1,5 +1,7 @@
## 1.6.1-wip
+* Add `BrowserCredentialsMode` to support the `omit` browser fetch credentials
+ mode. Deprecate `withCredentials`.
* Clarified the behavior of response headers in API documentation comments.
* Make it more clear that `close` must be called for correctness.
* Replace references to `dart:web` with `package:web` dartdoc.
@@ -48,7 +50,8 @@
## 1.2.0
* Add `MockClient.pngResponse`, which makes it easier to fake image responses.
-* Added the ability to fetch the URL of the response through `BaseResponseWithUrl`.
+* Added the ability to fetch the URL of the response through
+ `BaseResponseWithUrl`.
* Add the ability to get headers as a `Map<String, List<String>` to
`BaseResponse`.
diff --git a/pkgs/http/lib/src/browser_client.dart b/pkgs/http/lib/src/browser_client.dart
index e4e30a3..79c6b62 100644
--- a/pkgs/http/lib/src/browser_client.dart
+++ b/pkgs/http/lib/src/browser_client.dart
@@ -39,6 +39,38 @@
RequestInit init,
]);
+/// The browser `fetch` credentials mode represented by [RequestCredentials].
+///
+/// Controls whether the browser sends credentials such as cookies, TLS client
+/// certificates, or authorization headers with a request.
+///
+/// See also:
+/// - https://fetch.spec.whatwg.org/#requestcredentials
+enum RequestCredentials {
+ /// Never send credentials with the request and never include credentials in
+ /// the response.
+ ///
+ /// This corresponds to the browser `fetch` credentials mode `omit`.
+ omit('omit'),
+
+ /// Send credentials for same-origin requests only and only include
+ /// credentials in same-origin replies.
+ ///
+ /// This corresponds to the browser `fetch` credentials mode `same-origin`.
+ sameOrigin('same-origin'),
+
+ /// Always send credentials, even for cross-origin requests, and include them
+ /// in all responses.
+ ///
+ /// This corresponds to the browser `fetch` credentials mode `include`.
+ include('include');
+
+ const RequestCredentials(this._value);
+
+ /// The value passed to the browser `fetch` `RequestInit.credentials` field.
+ final String _value;
+}
+
/// A `package:web`-based HTTP client that runs in the browser and is backed by
/// [`window.fetch`](https://fetch.spec.whatwg.org/).
///
@@ -52,11 +84,44 @@
/// Responses are streamed but requests are not. A request will only be sent
/// once all the data is available.
class BrowserClient extends BaseClient {
+ /// The internal browser `fetch` credentials mode used for requests.
+ RequestCredentials _requestCredentials;
+
+ /// Create a [BrowserClient].
+ ///
+ /// By default, credentials are sent for same-origin requests only.
+ BrowserClient(
+ {RequestCredentials requestCredentials = RequestCredentials.sameOrigin})
+ : _requestCredentials = requestCredentials;
+
/// Whether to send credentials such as cookies or authorization headers for
/// cross-site requests.
///
/// Defaults to `false`.
- bool withCredentials = false;
+ ///
+ /// This property is deprecated because it can only represent two of the three
+ /// browser `fetch` credentials modes (`same-origin` and `include`).
+ /// Use the constructor parameter instead to also support
+ /// [RequestCredentials.omit].
+ ///
+ /// Reading this property returns `true` only when [_requestCredentials] is
+ /// [RequestCredentials.include].
+ @Deprecated('Use the requestCredentials constructor parameter instead.')
+ bool get withCredentials => _requestCredentials == RequestCredentials.include;
+
+ /// Whether to send credentials such as cookies or authorization headers for
+ /// cross-site requests.
+ ///
+ /// Setting this to `true` sets [_requestCredentials] to
+ /// [RequestCredentials.include].
+ ///
+ /// Setting this to `false` sets [_requestCredentials] to
+ /// [RequestCredentials.sameOrigin].
+ @Deprecated('Use the requestCredentials constructor parameter instead.')
+ set withCredentials(bool value) {
+ _requestCredentials =
+ value ? RequestCredentials.include : RequestCredentials.sameOrigin;
+ }
bool _isClosed = false;
final _openRequestAbortControllers = <AbortController>[];
@@ -85,7 +150,7 @@
RequestInit(
method: request.method,
body: bodyBytes.isNotEmpty ? bodyBytes.toJS : null,
- credentials: withCredentials ? 'include' : 'same-origin',
+ credentials: _requestCredentials._value,
headers: {
if (request.contentLength case final contentLength?)
'content-length': contentLength,