From 7ef1df4d5b011f6bfa4436279e2c3c8693aba38e Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Wed, 27 Apr 2016 13:09:37 -0700 Subject: [PATCH] Remove fetch.dart (#3584) These uses cases are now address by http.dart via http.readDataPipe. --- examples/layers/services/media_service.dart | 5 +- packages/flutter/lib/services.dart | 1 - packages/flutter/lib/src/http/http.dart | 16 ++++++ .../flutter/lib/src/http/mojo_client.dart | 31 ++++++++++- .../lib/src/services/asset_bundle.dart | 5 +- packages/flutter/lib/src/services/fetch.dart | 53 ------------------- .../flutter/lib/src/services/image_cache.dart | 19 ++++--- 7 files changed, 63 insertions(+), 67 deletions(-) delete mode 100644 packages/flutter/lib/src/services/fetch.dart diff --git a/examples/layers/services/media_service.dart b/examples/layers/services/media_service.dart index 2bb0e4a7f1e..301955c3403 100644 --- a/examples/layers/services/media_service.dart +++ b/examples/layers/services/media_service.dart @@ -4,11 +4,11 @@ import 'dart:async'; -import 'package:mojo/mojo/url_response.mojom.dart'; import 'package:sky_services/media/media.mojom.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; +import 'package:flutter/http.dart' as http; // All of these sounds are marked as public domain at soundbible. const String chimes = "http://soundbible.com/grab.php?id=2030&type=wav"; @@ -42,8 +42,7 @@ class PianoKey { Future load(MediaServiceProxy mediaService) async { try { mediaService.ptr.createPlayer(player); - UrlResponse response = await fetchUrl(soundUrl); - await player.ptr.prepare(response.body); + await player.ptr.prepare(await http.readDataPipe(soundUrl)); } catch (e) { print("Error: failed to load sound file $soundUrl"); player.close(); diff --git a/packages/flutter/lib/services.dart b/packages/flutter/lib/services.dart index 6562107e1f9..73e12050887 100644 --- a/packages/flutter/lib/services.dart +++ b/packages/flutter/lib/services.dart @@ -18,7 +18,6 @@ export 'src/services/activity.dart'; export 'src/services/app_messages.dart'; export 'src/services/asset_bundle.dart'; export 'src/services/binding.dart'; -export 'src/services/fetch.dart'; export 'src/services/image_cache.dart'; export 'src/services/image_decoder.dart'; export 'src/services/image_resource.dart'; diff --git a/packages/flutter/lib/src/http/http.dart b/packages/flutter/lib/src/http/http.dart index 3d28a3d1057..d3149e9950a 100644 --- a/packages/flutter/lib/src/http/http.dart +++ b/packages/flutter/lib/src/http/http.dart @@ -6,6 +6,8 @@ import 'dart:async'; import 'dart:convert'; import 'dart:typed_data'; +import 'package:mojo/core.dart' as mojo; + import 'mojo_client.dart'; import 'response.dart'; @@ -145,6 +147,20 @@ Future readBytes(dynamic url, { Map headers }) { return _withClient/**/((MojoClient client) => client.readBytes(url, headers: headers)); } +/// Sends an HTTP GET request with the given headers to the given URL, which can +/// be a [Uri] or a [String], and returns a Future that completes to a data pipe +/// containing the response bytes. +/// +/// The Future will emit a [ClientException] if the response doesn't have a +/// success status code. +/// +/// This automatically initializes a new [MojoClient] and closes that client once +/// the request is complete. If you're planning on making multiple requests to +/// the same server, you should use a single [MojoClient] for all of those requests. +Future readDataPipe(dynamic url, { Map headers }) { + return _withClient/**/((MojoClient client) => client.readDataPipe(url, headers: headers)); +} + Future _withClient/**/(Future fn(MojoClient client)) { return fn(new MojoClient()); } diff --git a/packages/flutter/lib/src/http/mojo_client.dart b/packages/flutter/lib/src/http/mojo_client.dart index caccef232d0..682bb9a693d 100644 --- a/packages/flutter/lib/src/http/mojo_client.dart +++ b/packages/flutter/lib/src/http/mojo_client.dart @@ -124,8 +124,31 @@ class MojoClient { }); } - Future _send(String method, dynamic url, Map headers, [dynamic body, Encoding encoding = UTF8]) async { + Future readDataPipe(dynamic url, { Map headers }) async { mojom.UrlLoaderProxy loader = new mojom.UrlLoaderProxy.unbound(); + mojom.UrlRequest request = _prepareRequest('get', url, headers); + mojom.UrlResponse response; + try { + networkService.ptr.createUrlLoader(loader); + response = (await loader.ptr.start(request)).response; + } catch (exception, stack) { + FlutterError.reportError(new FlutterErrorDetails( + exception: exception, + stack: stack, + library: 'networking HTTP library', + context: 'while sending bytes to the Mojo network library', + silent: true + )); + return null; + } finally { + loader.close(); + } + if (response.statusCode < 400) + return response.body; + throw new Exception("Request to $url failed with status ${response.statusCode}."); + } + + mojom.UrlRequest _prepareRequest(String method, dynamic url, Map headers, [dynamic body, Encoding encoding = UTF8]) { List mojoHeaders = []; headers?.forEach((String name, String value) { mojom.HttpHeader header = new mojom.HttpHeader() @@ -144,6 +167,12 @@ class MojoClient { ByteData data = new ByteData.view(encodedBody.buffer); mojo.DataPipeFiller.fillHandle(pipe.producer, data); } + return request; + } + + Future _send(String method, dynamic url, Map headers, [dynamic body, Encoding encoding = UTF8]) async { + mojom.UrlLoaderProxy loader = new mojom.UrlLoaderProxy.unbound(); + mojom.UrlRequest request = _prepareRequest(method, url, headers, body, encoding); try { networkService.ptr.createUrlLoader(loader); mojom.UrlResponse response = (await loader.ptr.start(request)).response; diff --git a/packages/flutter/lib/src/services/asset_bundle.dart b/packages/flutter/lib/src/services/asset_bundle.dart index 20041fddca1..12be90c64c3 100644 --- a/packages/flutter/lib/src/services/asset_bundle.dart +++ b/packages/flutter/lib/src/services/asset_bundle.dart @@ -10,7 +10,6 @@ import 'package:flutter/http.dart' as http; import 'package:mojo/core.dart' as core; import 'package:mojo_services/mojo/asset_bundle/asset_bundle.mojom.dart'; -import 'fetch.dart'; import 'image_cache.dart'; import 'image_decoder.dart'; import 'image_resource.dart'; @@ -34,7 +33,7 @@ class NetworkAssetBundle extends AssetBundle { @override Future load(String key) async { - return (await fetchUrl(_urlFromKey(key))).body; + return await http.readDataPipe(_urlFromKey(key)); } @override @@ -88,7 +87,7 @@ class MojoAssetBundle extends CachingAssetBundle { } static Future _fetchAndUnpackBundle(String relativeUrl, AssetBundleProxy bundle) async { - core.MojoDataPipeConsumer bundleData = (await fetchUrl(relativeUrl)).body; + core.MojoDataPipeConsumer bundleData = await http.readDataPipe(Uri.base.resolve(relativeUrl)); AssetUnpackerProxy unpacker = new AssetUnpackerProxy.unbound(); shell.connectToService("mojo:asset_bundle", unpacker); unpacker.ptr.unpackZipStream(bundleData, bundle); diff --git a/packages/flutter/lib/src/services/fetch.dart b/packages/flutter/lib/src/services/fetch.dart deleted file mode 100644 index 74e09ff1464..00000000000 --- a/packages/flutter/lib/src/services/fetch.dart +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2015 The Chromium Authors. 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:async'; - -import 'package:flutter/foundation.dart'; -import 'package:mojo/mojo/url_request.mojom.dart' as mojom; -import 'package:mojo/mojo/url_response.mojom.dart' as mojom; -import 'package:mojo_services/mojo/url_loader.mojom.dart' as mojom; - -import '../http/mojo_client.dart'; // TODO(ianh): clean this up, see https://github.com/flutter/flutter/issues/2889 - -export 'package:mojo/mojo/url_response.mojom.dart' show UrlResponse; - -Future fetch(mojom.UrlRequest request, { bool require200: false }) async { - mojom.UrlLoaderProxy loader = new mojom.UrlLoaderProxy.unbound(); - try { - MojoClient.networkService.ptr.createUrlLoader(loader); - mojom.UrlResponse response = (await loader.ptr.start(request)).response; - if (require200 && (response.error != null || response.statusCode != 200)) { - StringBuffer message = new StringBuffer(); - message.writeln('Could not ${request.method ?? "fetch"} ${request.url ?? "resource"}'); - if (response.error != null) - message.writeln('Network error: ${response.error.code} ${response.error.description ?? ""}'); - if (response.statusCode != 200) - message.writeln('Protocol error: ${response.statusCode} ${response.statusLine ?? ""}'); - if (response.url != request.url) - message.writeln('Final URL after redirects was: ${response.url}'); - throw message; // this is not a FlutterError, because it's a real error, not an assertion - } - return response; - } catch (exception, stack) { - FlutterError.reportError(new FlutterErrorDetails( - exception: exception, - stack: stack, - library: 'fetch service', - context: 'while sending bytes to the Mojo network library', - silent: true - )); - return null; - } finally { - loader.close(); - } -} - -Future fetchUrl(String relativeUrl, { bool require200: false }) { - String url = Uri.base.resolve(relativeUrl).toString(); - mojom.UrlRequest request = new mojom.UrlRequest() - ..url = url - ..autoFollowRedirects = true; - return fetch(request, require200: require200); -} diff --git a/packages/flutter/lib/src/services/image_cache.dart b/packages/flutter/lib/src/services/image_cache.dart index 560e182c447..66298fd1c12 100644 --- a/packages/flutter/lib/src/services/image_cache.dart +++ b/packages/flutter/lib/src/services/image_cache.dart @@ -6,9 +6,9 @@ import 'dart:async'; import 'dart:collection'; import 'dart:ui' show hashValues; -import 'package:mojo/mojo/url_response.mojom.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/http.dart' as http; -import 'fetch.dart'; import 'image_decoder.dart'; import 'image_resource.dart'; @@ -52,14 +52,21 @@ class _UrlFetcher implements ImageProvider { @override Future loadImage() async { - UrlResponse response = await fetchUrl(_url, require200: true); - if (response != null) { + try { return new ImageInfo( - image: await decodeImageFromDataPipe(response.body), + image: await decodeImageFromDataPipe(await http.readDataPipe(Uri.base.resolve(_url))), scale: _scale ); + } catch (exception, stack) { + FlutterError.reportError(new FlutterErrorDetails( + exception: exception, + stack: stack, + library: 'services library', + context: 'while fetching an image for the image cache', + silent: true + )); + return null; } - return null; } @override