-
Notifications
You must be signed in to change notification settings - Fork 366
/
Copy pathbase_client.dart
166 lines (150 loc) · 6.88 KB
/
base_client.dart
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. 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 'dart:convert';
import 'dart:typed_data';
import 'package:async/async.dart';
import 'client.dart';
import 'exception.dart';
import 'request.dart';
import 'response.dart';
/// The abstract base class for an HTTP client. This is a mixin-style class;
/// subclasses only need to implement [send] and maybe [close], and then they
/// get various convenience methods for free.
abstract class BaseClient implements Client {
/// Sends an HTTP HEAD request with the given headers to the given URL, which
/// can be a [Uri] or a [String].
///
/// For more fine-grained control over the request, use [send] instead.
Future<Response> head(url, {Map<String, String> headers}) =>
send(new Request.head(url, headers: headers));
/// Sends an HTTP GET request with the given headers to the given URL, which
/// can be a [Uri] or a [String].
///
/// For more fine-grained control over the request, use [send] instead.
Future<Response> get(url, {Map<String, String> headers}) =>
send(new Request.get(url, headers: headers));
/// Sends an HTTP POST request with the given headers and body to the given
/// URL, which can be a [Uri] or a [String].
///
/// [body] sets the body of the request. It can be a [String], a [List<int>]
/// or a [Map<String, String>]. If it's a String, it's encoded using
/// [encoding] and used as the body of the request. The content-type of the
/// request will default to "text/plain".
///
/// If [body] is a List, it's used as a list of bytes for the body of the
/// request.
///
/// If [body] is a Map, it's encoded as form fields using [encoding]. The
/// content-type of the request will be set to
/// `"application/x-www-form-urlencoded"`; this cannot be overridden.
///
/// [encoding] defaults to UTF-8.
///
/// For more fine-grained control over the request, use [send] instead.
Future<Response> post(url, body, {Map<String, String> headers,
Encoding encoding}) =>
send(new Request.post(url, body, headers: headers,
encoding: encoding));
/// Sends an HTTP PUT request with the given headers and body to the given
/// URL, which can be a [Uri] or a [String].
///
/// [body] sets the body of the request. It can be a [String], a [List<int>]
/// or a [Map<String, String>]. If it's a String, it's encoded using
/// [encoding] and used as the body of the request. The content-type of the
/// request will default to "text/plain".
///
/// If [body] is a List, it's used as a list of bytes for the body of the
/// request.
///
/// If [body] is a Map, it's encoded as form fields using [encoding]. The
/// content-type of the request will be set to
/// `"application/x-www-form-urlencoded"`; this cannot be overridden.
///
/// [encoding] defaults to UTF-8.
///
/// For more fine-grained control over the request, use [send] instead.
Future<Response> put(url, body, {Map<String, String> headers,
Encoding encoding}) =>
send(new Request.put(url, body, headers: headers,
encoding: encoding));
/// Sends an HTTP PATCH request with the given headers and body to the given
/// URL, which can be a [Uri] or a [String].
///
/// [body] sets the body of the request. It can be a [String], a [List<int>]
/// or a [Map<String, String>]. If it's a String, it's encoded using
/// [encoding] and used as the body of the request. The content-type of the
/// request will default to "text/plain".
///
/// If [body] is a List, it's used as a list of bytes for the body of the
/// request.
///
/// If [body] is a Map, it's encoded as form fields using [encoding]. The
/// content-type of the request will be set to
/// `"application/x-www-form-urlencoded"`; this cannot be overridden.
///
/// [encoding] defaults to UTF-8.
///
/// For more fine-grained control over the request, use [send] instead.
Future<Response> patch(url, body, {Map<String, String> headers,
Encoding encoding}) =>
send(new Request.patch(url, body, headers: headers,
encoding: encoding));
/// Sends an HTTP DELETE request with the given headers to the given URL,
/// which can be a [Uri] or a [String].
///
/// For more fine-grained control over the request, use [send] instead.
Future<Response> delete(url, {Map<String, String> headers}) =>
send(new Request.delete(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 the
/// body of the response as a String.
///
/// The Future will emit a [ClientException] if the response doesn't have a
/// success status code.
///
/// For more fine-grained control over the request and response, use [send] or
/// [get] instead.
Future<String> read(url, {Map<String, String> headers}) async {
var response = await get(url, headers: headers);
_checkResponseSuccess(url, response);
return await response.readAsString();
}
/// 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 the
/// body of the response as a list of bytes.
///
/// The Future will emit an [ClientException] if the response doesn't have a
/// success status code.
///
/// For more fine-grained control over the request and response, use [send] or
/// [get] instead.
Future<Uint8List> readBytes(url, {Map<String, String> headers}) async {
var response = await get(url, headers: headers);
_checkResponseSuccess(url, response);
return await collectBytes(response.read());
}
/// Sends an HTTP request and asynchronously returns the response.
///
/// Implementers should call [BaseRequest.finalize] to get the body of the
/// request as a [ByteStream]. They shouldn't make any assumptions about the
/// state of the stream; it could have data written to it asynchronously at a
/// later point, or it could already be closed when it's returned. Any
/// internal HTTP errors should be wrapped as [ClientException]s.
Future<Response> send(Request request);
/// Throws an error if [response] is not successful.
void _checkResponseSuccess(url, Response response) {
if (response.statusCode < 400) return;
var message = "Request to $url failed with status ${response.statusCode}";
if (response.reasonPhrase != null) {
message = "$message: ${response.reasonPhrase}";
}
if (url is String) url = Uri.parse(url);
throw new ClientException("$message.", url);
}
/// Closes the client and cleans up any resources associated with it. It's
/// important to close each client when it's done being used; failing to do so
/// can cause the Dart process to hang.
void close() {}
}