Skip to content

Commit 5ac7cfe

Browse files
JavaClient stream response body using byte arrays (dart-lang#1007)
1 parent 0e6e58a commit 5ac7cfe

File tree

4 files changed

+291
-14
lines changed

4 files changed

+291
-14
lines changed

pkgs/java_http/jnigen.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class_path:
1212
- 'classes.jar'
1313

1414
classes:
15+
- 'java.io.BufferedInputStream'
1516
- 'java.io.InputStream'
1617
- 'java.io.OutputStream'
1718
- 'java.lang.System'

pkgs/java_http/lib/src/java_client.dart

+41-14
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'package:http/http.dart';
1212
import 'package:jni/jni.dart';
1313
import 'package:path/path.dart';
1414

15+
import 'third_party/java/io/BufferedInputStream.dart';
1516
import 'third_party/java/lang/System.dart';
1617
import 'third_party/java/net/HttpURLConnection.dart';
1718
import 'third_party/java/net/URL.dart';
@@ -96,15 +97,15 @@ class JavaClient extends BaseClient {
9697
}
9798

9899
// TODO: Rename _isolateMethod to something more descriptive.
99-
void _isolateMethod(
100+
Future<void> _isolateMethod(
100101
({
101102
SendPort sendPort,
102103
Uint8List body,
103104
Map<String, String> headers,
104105
String method,
105106
Uri url,
106107
}) request,
107-
) {
108+
) async {
108109
final httpUrlConnection = URL
109110
.ctor3(request.url.toString().toJString())
110111
.openConnection()
@@ -140,7 +141,7 @@ class JavaClient extends BaseClient {
140141
responseHeaders,
141142
);
142143

143-
_responseBody(
144+
await _responseBody(
144145
request.url,
145146
httpUrlConnection,
146147
request.sendPort,
@@ -230,35 +231,61 @@ class JavaClient extends BaseClient {
230231
return contentLength;
231232
}
232233

233-
void _responseBody(
234+
Future<void> _responseBody(
234235
Uri requestUrl,
235236
HttpURLConnection httpUrlConnection,
236237
SendPort sendPort,
237238
int? expectedBodyLength,
238-
) {
239+
) async {
239240
final responseCode = httpUrlConnection.getResponseCode();
240241

241-
final inputStream = (responseCode >= 200 && responseCode <= 299)
242-
? httpUrlConnection.getInputStream()
243-
: httpUrlConnection.getErrorStream();
242+
final responseBodyStream = (responseCode >= 200 && responseCode <= 299)
243+
? BufferedInputStream(httpUrlConnection.getInputStream())
244+
: BufferedInputStream(httpUrlConnection.getErrorStream());
244245

245-
int byte;
246246
var actualBodyLength = 0;
247-
// TODO: inputStream.read() could throw IOException.
248-
while ((byte = inputStream.read()) != -1) {
249-
sendPort.send([byte]);
250-
actualBodyLength++;
247+
final bytesBuffer = JArray(jbyte.type, 4096);
248+
249+
while (true) {
250+
// TODO: read1() could throw IOException.
251+
final bytesCount =
252+
responseBodyStream.read1(bytesBuffer, 0, bytesBuffer.length);
253+
254+
if (bytesCount == -1) {
255+
break;
256+
}
257+
258+
if (bytesCount == 0) {
259+
// No more data is available without blocking so give other Isolates an
260+
// opportunity to run.
261+
await Future<void>.delayed(Duration.zero);
262+
continue;
263+
}
264+
265+
sendPort.send(bytesBuffer.toUint8List(length: bytesCount));
266+
actualBodyLength += bytesCount;
251267
}
252268

253269
if (expectedBodyLength != null && actualBodyLength < expectedBodyLength) {
254270
sendPort.send(ClientException('Unexpected end of body', requestUrl));
255271
}
256272

257-
inputStream.close();
273+
responseBodyStream.close();
258274
}
259275
}
260276

261277
extension on Uint8List {
262278
JArray<jbyte> toJArray() =>
263279
JArray(jbyte.type, length)..setRange(0, length, this);
264280
}
281+
282+
extension on JArray<jbyte> {
283+
Uint8List toUint8List({int? length}) {
284+
length ??= this.length;
285+
final list = Uint8List(length);
286+
for (var i = 0; i < length; i++) {
287+
list[i] = this[i];
288+
}
289+
return list;
290+
}
291+
}

pkgs/java_http/lib/src/third_party/java/io/BufferedInputStream.dart

+248
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkgs/java_http/lib/src/third_party/java/io/_package.dart

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)