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
Remove package:http from Flutter #15416
Conversation
One thing we lose with this is that we used to use only a single HTTP client for all network requests done by the app. That seems unfortunate (e.g. you have to configure the UA string multiple times). Would it make sense to keep an equivalent to createHttpClient around? |
|
Also, there are some scripts that imported http that will probably fail now. You should make sure that they have http in their pubspecs. It looks like you fixed some of them, but not all: ./packages/flutter_tools/test/crash_reporting_test.dart:12:import 'package:http/http.dart'; |
I don't think that is true (at least at master). class FlutterHttpOverrides extends HttpOverrides {
HttpClient _httpClient;
HttpClient createHttpClient(SecurityContext context) {
return _httpClient ??= new HttpClient();
}
}
@xqwzts It looks like there are references to createHttpClient in those docs, as well as the udacity course. I will file follow up bugs to fix the documentation and note them in this PR. @gspencergoog Thanks, I've added the missing dependency to the |
Filed #15447 for updating the website |
Filed https://github.com/flutter/udacity-course/issues/72 for the udacity course. I can open PRs to update the code in each after this PR is resolved |
dev/bots/pubspec.yaml
Outdated
http_multi_server: 2.0.4 # TRANSITIVE DEPENDENCY | ||
http_parser: 3.1.1 # TRANSITIVE DEPENDENCY |
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.
please make sure to run flutter update-packages --force-upgrade
to update the pubspec.yaml
files.
@Hixie I've updated the dependencies and the documentation that refers to |
final Uint8List bytes = new Uint8List(response.contentLength); | ||
int offset = 0; | ||
response.listen((List<int> chunk) { | ||
for (int i = 0; i < chunk.length; i++, offset++) { |
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.
nit: += 1
rather than ++
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.
but forget that. Instead of this loop, just use bytes.addAll(chunk)
.
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.
or rather, bytes.setRange
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.
Done
cancelOnError: true, | ||
); | ||
} | ||
final Uint8List bytes = await completer.future; |
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.
cc @rmacnak-google who may have a better idea of how to do this without copying bytes multiple times.
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.
I think the case where the total length is known is optimal: copy from the OS socket into the chunk, copy from chunks into the linear buffer. The unknown length case has additional copies from growing the buffer and trimming the final result. I believe the chunks are not recycled, so it could be improved by holding onto the chunks and building the linear buffer after receiving the last chunk.
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.
Well the "optimal" case wouldn't copy at all, right, we'd just re-use the OS buffer unmodified...
completer.complete(bytes.buffer.asByteData()); | ||
}, | ||
cancelOnError: true); | ||
} |
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.
we should definitely not duplicate this code. see if you can factor it out into something in the foundation library, so that we only have to optimize it once.
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.
moved to response_converter.dart
in foundation
); | ||
return response.body; | ||
final ByteData bytes = await load(key); | ||
return const Utf8Decoder().convert(bytes.buffer.asUint8List()); |
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.
we really shouldn't do the UTF8 conversion on the main thread if the data size is big. Look for uses of compute
which show how to move this kind of thing off the main thread.
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.
Since this logic is shared by all of the Bundle classes I moved it into the base class.
LGTM modulo comments above. |
examples/hello_world/lib/main.dart
Outdated
@@ -4,4 +4,6 @@ | |||
|
|||
import 'package:flutter/widgets.dart'; | |||
|
|||
void main() => runApp(const Center(child: const Text('Hello, world!', textDirection: TextDirection.ltr))); | |||
void main() { |
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.
Fat arrow syntax for main() =>
is preferred in examples, so new users don't write any statements other than runApp
there - which wouldn't be picked up by the hot reload.
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.
Woops, shouldn't have committed this
@Hixie , @rmacnak-google PTAL at the updated response conversion code in https://github.com/jonahwilliams/flutter/blob/f7ee16fc1167db31f7cbcbf721ffe69ca24d38bf/packages/flutter/lib/src/foundation/convert_response.dart |
lgtm |
@@ -0,0 +1,45 @@ | |||
import 'dart:async'; |
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.
need license block (copy it from another file verbatim then change the year to 2018) with no other changes
import 'dart:io'; | ||
import 'dart:typed_data'; | ||
|
||
|
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.
remove a blank line here
/// Efficiently converts the response body of an [HttpClientResponse] into a [Uint8List]. | ||
/// | ||
/// The future returned by [convert] will forward all errors emitted by [response]. | ||
Future<Uint8List> convertResponse(HttpClientResponse response) { |
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.
Does this have to be an HttpClientResponse, or will it work with any Stream<List<int>>
?
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.
i guess you need contentLength, oh well.
/// Efficiently converts the response body of an [HttpClientResponse] into a [Uint8List]. | ||
/// | ||
/// The future returned by [convert] will forward all errors emitted by [response]. | ||
Future<Uint8List> convertResponse(HttpClientResponse response) { |
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.
Since this is a global method, let's call it something more specific, like "consolidateHttpClientResponseBytes" or something.
LGTM! |
* use HttpOverrides and dart:io HttpClient in flutter * add missing package:http dependency * update flutter packages and remove comment about createHttpClient from flutter_test * move byte loading logic to common class, move string parsing logic to base class * addAll doesn't work for a Uint8List * use bytes.setRange * undo addition to hello_world * add newline to end of binding.dart * and a newline for hello world * refactor to function and add tests * address comments on unknown length case * alignment * sort alaphabetically * rename convertResponse to consolidateClientHttpClientResponseBytes. Add header * fix alignment in test
Flutter will no longer automatically include package:http, nor will it support setting createHttpClient to override the default client.
NetworkAssetBundle
andImageProvider
now usedart:io
HttpClient
directly.NetworkAssetBundle
andImageProvider
use the content-length header if provided to allocate directly into aUint8List
.Moved some tests which used package:http MockClient to a Mockito based test.
Tests that need mock http requests should use
HttpOverrides.runZoned
to provide a mockHttpClient
instance. For an example, seedev/manual_tests/test/card_collection_test.dart
flutter_test now uses
HttpOverrides.global
to set a default mocked client which always returns empty 400 responses. This is completely private, clients should author their own overrides if they want specific behavior.This is a breaking change.
Fixes #13456
This saves a solid 1.4 Kb from the Gallery app on Android.