Skip to content

Commit 40b8aec

Browse files
committed
Setup callback for send data progress
1 parent 8a4a4a6 commit 40b8aec

File tree

9 files changed

+227
-46
lines changed

9 files changed

+227
-46
lines changed

pkgs/http/lib/http.dart

Lines changed: 70 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'dart:typed_data';
1010

1111
import 'src/client.dart';
1212
import 'src/exception.dart';
13+
import 'src/progress.dart';
1314
import 'src/request.dart';
1415
import 'src/response.dart';
1516
import 'src/streamed_request.dart';
@@ -22,6 +23,7 @@ export 'src/client.dart' hide zoneClient;
2223
export 'src/exception.dart';
2324
export 'src/multipart_file.dart';
2425
export 'src/multipart_request.dart';
26+
export 'src/progress.dart';
2527
export 'src/request.dart';
2628
export 'src/response.dart';
2729
export 'src/streamed_request.dart';
@@ -63,12 +65,25 @@ Future<Response> get(Uri url, {Map<String, String>? headers}) =>
6365
///
6466
/// [encoding] defaults to [utf8].
6567
///
68+
/// If [onSendProgress] is provided it will be called to indicate
69+
/// the upload progress
70+
///
6671
/// For more fine-grained control over the request, use [Request] or
6772
/// [StreamedRequest] instead.
68-
Future<Response> post(Uri url,
69-
{Map<String, String>? headers, Object? body, Encoding? encoding}) =>
70-
_withClient((client) =>
71-
client.post(url, headers: headers, body: body, encoding: encoding));
73+
Future<Response> post(
74+
Uri url, {
75+
Map<String, String>? headers,
76+
Object? body,
77+
Encoding? encoding,
78+
Progress? onSendProgress,
79+
}) =>
80+
_withClient((client) => client.post(
81+
url,
82+
headers: headers,
83+
body: body,
84+
encoding: encoding,
85+
onSendProgress: onSendProgress,
86+
));
7287

7388
/// Sends an HTTP PUT request with the given headers and body to the given URL.
7489
///
@@ -86,12 +101,25 @@ Future<Response> post(Uri url,
86101
///
87102
/// [encoding] defaults to [utf8].
88103
///
104+
/// If [onSendProgress] is provided it will be called to indicate
105+
/// the upload progress
106+
///
89107
/// For more fine-grained control over the request, use [Request] or
90108
/// [StreamedRequest] instead.
91-
Future<Response> put(Uri url,
92-
{Map<String, String>? headers, Object? body, Encoding? encoding}) =>
93-
_withClient((client) =>
94-
client.put(url, headers: headers, body: body, encoding: encoding));
109+
Future<Response> put(
110+
Uri url, {
111+
Map<String, String>? headers,
112+
Object? body,
113+
Encoding? encoding,
114+
Progress? onSendProgress,
115+
}) =>
116+
_withClient((client) => client.put(
117+
url,
118+
headers: headers,
119+
body: body,
120+
encoding: encoding,
121+
onSendProgress: onSendProgress,
122+
));
95123

96124
/// Sends an HTTP PATCH request with the given headers and body to the given
97125
/// URL.
@@ -110,24 +138,50 @@ Future<Response> put(Uri url,
110138
///
111139
/// [encoding] defaults to [utf8].
112140
///
141+
/// If [onSendProgress] is provided it will be called to indicate
142+
/// the upload progress
143+
///
113144
/// For more fine-grained control over the request, use [Request] or
114145
/// [StreamedRequest] instead.
115-
Future<Response> patch(Uri url,
116-
{Map<String, String>? headers, Object? body, Encoding? encoding}) =>
117-
_withClient((client) =>
118-
client.patch(url, headers: headers, body: body, encoding: encoding));
146+
Future<Response> patch(
147+
Uri url, {
148+
Map<String, String>? headers,
149+
Object? body,
150+
Encoding? encoding,
151+
Progress? onSendProgress,
152+
}) =>
153+
_withClient((client) => client.patch(
154+
url,
155+
headers: headers,
156+
body: body,
157+
encoding: encoding,
158+
onSendProgress: onSendProgress,
159+
));
119160

120161
/// Sends an HTTP DELETE request with the given headers to the given URL.
121162
///
122163
/// This automatically initializes a new [Client] and closes that client once
123164
/// the request is complete. If you're planning on making multiple requests to
124165
/// the same server, you should use a single [Client] for all of those requests.
125166
///
167+
/// If [onSendProgress] is provided it will be called to indicate
168+
/// the upload progress
169+
///
126170
/// For more fine-grained control over the request, use [Request] instead.
127-
Future<Response> delete(Uri url,
128-
{Map<String, String>? headers, Object? body, Encoding? encoding}) =>
129-
_withClient((client) =>
130-
client.delete(url, headers: headers, body: body, encoding: encoding));
171+
Future<Response> delete(
172+
Uri url, {
173+
Map<String, String>? headers,
174+
Object? body,
175+
Encoding? encoding,
176+
Progress? onSendProgress,
177+
}) =>
178+
_withClient((client) => client.delete(
179+
url,
180+
headers: headers,
181+
body: body,
182+
encoding: encoding,
183+
onSendProgress: onSendProgress,
184+
));
131185

132186
/// Sends an HTTP GET request with the given headers to the given URL and
133187
/// returns a Future that completes to the body of the response as a [String].

pkgs/http/lib/retry.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,20 @@ final class RetryClient extends BaseClient {
105105
);
106106

107107
@override
108-
Future<StreamedResponse> send(BaseRequest request) async {
108+
Future<StreamedResponse> send(
109+
BaseRequest request, {
110+
Progress? onSendProgress,
111+
}) async {
109112
final splitter = StreamSplitter(request.finalize());
110113

111114
var i = 0;
112115
for (;;) {
113116
StreamedResponse? response;
114117
try {
115-
response = await _inner.send(_copyRequest(request, splitter.split()));
118+
response = await _inner.send(
119+
_copyRequest(request, splitter.split()),
120+
onSendProgress: onSendProgress,
121+
);
116122
} catch (error, stackTrace) {
117123
if (i == _retries || !await _whenError(error, stackTrace)) rethrow;
118124
}

pkgs/http/lib/src/base_client.dart

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'base_request.dart';
99
import 'byte_stream.dart';
1010
import 'client.dart';
1111
import 'exception.dart';
12+
import 'progress.dart';
1213
import 'request.dart';
1314
import 'response.dart';
1415
import 'streamed_response.dart';
@@ -27,24 +28,72 @@ abstract mixin class BaseClient implements Client {
2728
_sendUnstreamed('GET', url, headers);
2829

2930
@override
30-
Future<Response> post(Uri url,
31-
{Map<String, String>? headers, Object? body, Encoding? encoding}) =>
32-
_sendUnstreamed('POST', url, headers, body, encoding);
31+
Future<Response> post(
32+
Uri url, {
33+
Map<String, String>? headers,
34+
Object? body,
35+
Encoding? encoding,
36+
Progress? onSendProgress,
37+
}) =>
38+
_sendUnstreamed(
39+
'POST',
40+
url,
41+
headers,
42+
body,
43+
encoding,
44+
onSendProgress,
45+
);
3346

3447
@override
35-
Future<Response> put(Uri url,
36-
{Map<String, String>? headers, Object? body, Encoding? encoding}) =>
37-
_sendUnstreamed('PUT', url, headers, body, encoding);
48+
Future<Response> put(
49+
Uri url, {
50+
Map<String, String>? headers,
51+
Object? body,
52+
Encoding? encoding,
53+
Progress? onSendProgress,
54+
}) =>
55+
_sendUnstreamed(
56+
'PUT',
57+
url,
58+
headers,
59+
body,
60+
encoding,
61+
onSendProgress,
62+
);
3863

3964
@override
40-
Future<Response> patch(Uri url,
41-
{Map<String, String>? headers, Object? body, Encoding? encoding}) =>
42-
_sendUnstreamed('PATCH', url, headers, body, encoding);
65+
Future<Response> patch(
66+
Uri url, {
67+
Map<String, String>? headers,
68+
Object? body,
69+
Encoding? encoding,
70+
Progress? onSendProgress,
71+
}) =>
72+
_sendUnstreamed(
73+
'PATCH',
74+
url,
75+
headers,
76+
body,
77+
encoding,
78+
onSendProgress,
79+
);
4380

4481
@override
45-
Future<Response> delete(Uri url,
46-
{Map<String, String>? headers, Object? body, Encoding? encoding}) =>
47-
_sendUnstreamed('DELETE', url, headers, body, encoding);
82+
Future<Response> delete(
83+
Uri url, {
84+
Map<String, String>? headers,
85+
Object? body,
86+
Encoding? encoding,
87+
Progress? onSendProgress,
88+
}) =>
89+
_sendUnstreamed(
90+
'DELETE',
91+
url,
92+
headers,
93+
body,
94+
encoding,
95+
onSendProgress,
96+
);
4897

4998
@override
5099
Future<String> read(Uri url, {Map<String, String>? headers}) async {
@@ -68,12 +117,15 @@ abstract mixin class BaseClient implements Client {
68117
/// later point, or it could already be closed when it's returned. Any
69118
/// internal HTTP errors should be wrapped as [ClientException]s.
70119
@override
71-
Future<StreamedResponse> send(BaseRequest request);
120+
Future<StreamedResponse> send(
121+
BaseRequest request, {
122+
Progress? onSendProgress,
123+
});
72124

73125
/// Sends a non-streaming [Request] and returns a non-streaming [Response].
74126
Future<Response> _sendUnstreamed(
75127
String method, Uri url, Map<String, String>? headers,
76-
[Object? body, Encoding? encoding]) async {
128+
[Object? body, Encoding? encoding, Progress? onSendProgress]) async {
77129
var request = Request(method, url);
78130

79131
if (headers != null) request.headers.addAll(headers);
@@ -90,7 +142,10 @@ abstract mixin class BaseClient implements Client {
90142
}
91143
}
92144

93-
return Response.fromStream(await send(request));
145+
return Response.fromStream(await send(
146+
request,
147+
onSendProgress: onSendProgress,
148+
));
94149
}
95150

96151
/// Throws an error if [response] is not successful.

pkgs/http/lib/src/base_request.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import 'base_client.dart';
1111
import 'base_response.dart';
1212
import 'byte_stream.dart';
1313
import 'client.dart';
14+
import 'progress.dart';
1415
import 'streamed_response.dart';
1516
import 'utils.dart';
1617

@@ -27,6 +28,9 @@ abstract class BaseRequest {
2728
/// Non-standard method names are also supported.
2829
final String method;
2930

31+
/// The callback to call for data send progress.
32+
Progress? onSendProgress;
33+
3034
/// The URL to which the request will be sent.
3135
final Uri url;
3236

@@ -130,7 +134,10 @@ abstract class BaseRequest {
130134
var client = Client();
131135

132136
try {
133-
var response = await client.send(this);
137+
var response = await client.send(
138+
this,
139+
onSendProgress: onSendProgress,
140+
);
134141
var stream = onDone(response.stream, client.close);
135142
return StreamedResponse(ByteStream(stream), response.statusCode,
136143
contentLength: response.contentLength,

pkgs/http/lib/src/browser_client.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'base_client.dart';
1010
import 'base_request.dart';
1111
import 'byte_stream.dart';
1212
import 'exception.dart';
13+
import 'progress.dart';
1314
import 'streamed_response.dart';
1415

1516
/// Create a [BrowserClient].
@@ -47,7 +48,10 @@ class BrowserClient extends BaseClient {
4748

4849
/// Sends an HTTP request and asynchronously returns the response.
4950
@override
50-
Future<StreamedResponse> send(BaseRequest request) async {
51+
Future<StreamedResponse> send(
52+
BaseRequest request,
53+
Progress? onSendProgress,
54+
) async {
5155
if (_isClosed) {
5256
throw ClientException(
5357
'HTTP request failed. Client is already closed.', request.url);

0 commit comments

Comments
 (0)