From 63a6fda46778f4adc14dfb2e8e4cec53f15745e1 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 21 Nov 2023 12:17:41 -0800 Subject: [PATCH] wip - pkg:web migration --- pkgs/http/CHANGELOG.md | 4 +- pkgs/http/lib/src/browser_client.dart | 63 +++++++++++++++++++++------ pkgs/http/pubspec.yaml | 3 +- pkgs/http/test/html/utils.dart | 2 +- 4 files changed, 55 insertions(+), 17 deletions(-) diff --git a/pkgs/http/CHANGELOG.md b/pkgs/http/CHANGELOG.md index 6d39b104df..84316ff8a2 100644 --- a/pkgs/http/CHANGELOG.md +++ b/pkgs/http/CHANGELOG.md @@ -1,8 +1,10 @@ -## 1.1.1 +## 1.1.1-wip * `BrowserClient` throws `ClientException` when the `'Content-Length'` header is invalid. * `IOClient` trims trailing whitespace on header values. +* Require Dart 3.2 +* Browser: support Wasm by using package:web. ## 1.1.0 diff --git a/pkgs/http/lib/src/browser_client.dart b/pkgs/http/lib/src/browser_client.dart index 9345be0ce1..c685b0dc70 100644 --- a/pkgs/http/lib/src/browser_client.dart +++ b/pkgs/http/lib/src/browser_client.dart @@ -3,9 +3,11 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'dart:html'; +import 'dart:js_interop'; import 'dart:typed_data'; +import 'package:web/helpers.dart'; + import 'base_client.dart'; import 'base_request.dart'; import 'byte_stream.dart'; @@ -37,7 +39,7 @@ class BrowserClient extends BaseClient { /// The currently active XHRs. /// /// These are aborted if the client is closed. - final _xhrs = {}; + final _xhrs = {}; /// Whether to send credentials such as cookies or authorization headers for /// cross-site requests. @@ -55,18 +57,21 @@ class BrowserClient extends BaseClient { 'HTTP request failed. Client is already closed.', request.url); } var bytes = await request.finalize().toBytes(); - var xhr = HttpRequest(); + + var xhr = await HttpRequest.request( + '${request.url}', + method: request.method, + responseType: 'arraybuffer', + requestHeaders: request.headers, + sendData: bytes.toJS, + ); _xhrs.add(xhr); - xhr - ..open(request.method, '${request.url}', async: true) - ..responseType = 'arraybuffer' - ..withCredentials = withCredentials; - request.headers.forEach(xhr.setRequestHeader); var completer = Completer(); unawaited(xhr.onLoad.first.then((_) { - if (xhr.responseHeaders['content-length'] case final contentLengthHeader? + if (xhr.getResponseHeader('content-length') + case final contentLengthHeader? when !_digitRegex.hasMatch(contentLengthHeader)) { completer.completeError(ClientException( 'Invalid content-length header [$contentLengthHeader].', @@ -75,12 +80,17 @@ class BrowserClient extends BaseClient { return; } var body = (xhr.response as ByteBuffer).asUint8List(); - completer.complete(StreamedResponse( - ByteStream.fromBytes(body), xhr.status!, + + completer.complete( + StreamedResponse( + ByteStream.fromBytes(body), + xhr.status, contentLength: body.length, request: request, headers: xhr.responseHeaders, - reasonPhrase: xhr.statusText)); + reasonPhrase: xhr.statusText, + ), + ); })); unawaited(xhr.onError.first.then((_) { @@ -91,8 +101,6 @@ class BrowserClient extends BaseClient { StackTrace.current); })); - xhr.send(bytes); - try { return await completer.future; } finally { @@ -112,3 +120,30 @@ class BrowserClient extends BaseClient { _xhrs.clear(); } } + +extension on XMLHttpRequest { + Map get responseHeaders { + // from Closure's goog.net.Xhrio.getResponseHeaders. + var headers = {}; + var headersString = getAllResponseHeaders(); + var headersList = headersString.split('\r\n'); + for (var header in headersList) { + if (header.isEmpty) { + continue; + } + + var splitIdx = header.indexOf(': '); + if (splitIdx == -1) { + continue; + } + var key = header.substring(0, splitIdx).toLowerCase(); + var value = header.substring(splitIdx + 2); + if (headers.containsKey(key)) { + headers[key] = '${headers[key]}, $value'; + } else { + headers[key] = value; + } + } + return headers; + } +} diff --git a/pkgs/http/pubspec.yaml b/pkgs/http/pubspec.yaml index 37d397ea7d..b65b129764 100644 --- a/pkgs/http/pubspec.yaml +++ b/pkgs/http/pubspec.yaml @@ -4,12 +4,13 @@ description: A composable, multi-platform, Future-based API for HTTP requests. repository: https://github.com/dart-lang/http/tree/master/pkgs/http environment: - sdk: ^3.0.0 + sdk: ^3.2.0 dependencies: async: ^2.5.0 http_parser: ^4.0.0 meta: ^1.3.0 + web: ^0.4.0 dev_dependencies: dart_flutter_team_lints: ^2.0.0 diff --git a/pkgs/http/test/html/utils.dart b/pkgs/http/test/html/utils.dart index abe5808a99..501c621256 100644 --- a/pkgs/http/test/html/utils.dart +++ b/pkgs/http/test/html/utils.dart @@ -2,7 +2,7 @@ // 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:html'; +import 'package:web/helpers.dart'; export '../utils.dart';