diff --git a/pkgs/http/CHANGELOG.md b/pkgs/http/CHANGELOG.md index 67ced1f1d7..33f3a03c94 100644 --- a/pkgs/http/CHANGELOG.md +++ b/pkgs/http/CHANGELOG.md @@ -1,5 +1,7 @@ ## 1.6.1-wip +* Add `BrowserCredentialsMode` and `BrowserClient.credentialsMode` 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. @@ -46,7 +48,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` to `BaseResponse`. diff --git a/pkgs/http/lib/src/browser_client.dart b/pkgs/http/lib/src/browser_client.dart index e4e30a3886..a9762c694d 100644 --- a/pkgs/http/lib/src/browser_client.dart +++ b/pkgs/http/lib/src/browser_client.dart @@ -39,6 +39,38 @@ external JSPromise _fetch( 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,49 @@ external JSPromise _fetch( /// Responses are streamed but requests are not. A request will only be sent /// once all the data is available. class BrowserClient extends BaseClient { + /// Create a [BrowserClient]. + /// + /// By default, credentials are sent for same-origin requests only. + BrowserClient( + {RequestCredentials requestCredentials = RequestCredentials.sameOrigin}) + : _requestCredentials = requestCredentials; + + /// The internal browser `fetch` credentials mode used for requests. + RequestCredentials _requestCredentials; + + /// The browser `fetch` credentials mode used for requests. + /// + /// Defaults to [RequestCredentials.sameOrigin], which matches the + /// previous behavior when [withCredentials] was `false`. + RequestCredentials get 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 + /// [_requestCredentials] instead to also support [RequestCredentials.omit]. + /// + /// Reading this property returns `true` only when [_requestCredentials] is + /// [RequestCredentials.include]. + @Deprecated('Use requestCredentials 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 = []; @@ -85,7 +155,7 @@ class BrowserClient extends BaseClient { 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,