request.dart
3.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import '../http.dart';
import '../multipart/form_data.dart';
class Request<T> {
/// Headers attach to this [Request]
final Map<String, String> headers;
/// The [Uri] from request
final Uri url;
final Decoder<T>? decoder;
/// The Http Method from this [Request]
/// ex: `GET`,`POST`,`PUT`,`DELETE`
final String method;
final int? contentLength;
/// The BodyBytesStream of body from this [Request]
final Stream<List<int>> bodyBytes;
/// When true, the client will follow redirects to resolves this [Request]
final bool followRedirects;
/// The maximum number of redirects if [followRedirects] is true.
final int maxRedirects;
final bool persistentConnection;
final FormData? files;
const Request._({
required this.method,
required this.bodyBytes,
required this.url,
required this.headers,
required this.contentLength,
required this.followRedirects,
required this.maxRedirects,
required this.files,
required this.persistentConnection,
required this.decoder,
});
factory Request({
required Uri url,
required String method,
required Map<String, String> headers,
Stream<List<int>>? bodyBytes,
bool followRedirects = true,
int maxRedirects = 4,
int? contentLength,
FormData? files,
bool persistentConnection = true,
Decoder<T>? decoder,
}) {
if (followRedirects) {
assert(maxRedirects > 0);
}
return Request._(
url: url,
method: method,
bodyBytes: bodyBytes ??= BodyBytesStream.fromBytes(const []),
headers: Map.from(headers),
followRedirects: followRedirects,
maxRedirects: maxRedirects,
contentLength: contentLength,
files: files,
persistentConnection: persistentConnection,
decoder: decoder,
);
}
Request<T> copyWith({
Uri? url,
String? method,
Map<String, String>? headers,
Stream<List<int>>? bodyBytes,
bool? followRedirects,
int? maxRedirects,
int? contentLength,
FormData? files,
bool? persistentConnection,
Decoder<T>? decoder,
bool appendHeader = true,
}) {
// If appendHeader is set to true, we will merge origin headers with that
if (appendHeader && headers != null) {
headers.addAll(this.headers);
}
return Request<T>._(
url: url ?? this.url,
method: method ?? this.method,
bodyBytes: bodyBytes ?? this.bodyBytes,
headers: headers == null ? this.headers : Map.from(headers),
followRedirects: followRedirects ?? this.followRedirects,
maxRedirects: maxRedirects ?? this.maxRedirects,
contentLength: contentLength ?? this.contentLength,
files: files ?? this.files,
persistentConnection: persistentConnection ?? this.persistentConnection,
decoder: decoder ?? this.decoder,
);
}
}
extension BodyBytesStream on Stream<List<int>> {
static Stream<List<int>> fromBytes(List<int> bytes) =>
Stream.fromIterable([bytes]);
Future<Uint8List> toBytes() {
var completer = Completer<Uint8List>();
var sink = ByteConversionSink.withCallback(
(bytes) => completer.complete(
Uint8List.fromList(bytes),
),
);
listen((val) => sink.add(val),
onError: completer.completeError,
onDone: sink.close,
cancelOnError: true);
return completer.future;
}
Future<String> bytesToString([Encoding encoding = utf8]) =>
encoding.decodeStream(this);
}