-
Notifications
You must be signed in to change notification settings - Fork 382
Update Client interface #56
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
Changes from 5 commits
d274582
bb81377
9764158
cf91544
949bb56
6cf06ea
6df8771
07dd399
69df648
35a765c
8d2e503
362ad9c
4285911
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,14 +6,12 @@ import 'dart:async'; | |
import 'dart:convert'; | ||
import 'dart:typed_data'; | ||
|
||
import 'package:collection/collection.dart'; | ||
import 'package:async/async.dart'; | ||
|
||
import 'base_request.dart'; | ||
import 'client.dart'; | ||
import 'exception.dart'; | ||
import 'request.dart'; | ||
import 'response.dart'; | ||
import 'streamed_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 | ||
|
@@ -23,15 +21,15 @@ abstract class BaseClient implements Client { | |
/// 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}) => | ||
_sendUnstreamed("HEAD", url, headers); | ||
FutureOr<Response> head(url, {Map<String, String> headers}) => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same question here: why |
||
send(new Request.head(_uri(url), headers: headers)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The request constructors should take dynamic There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about the named constructors take dynamic but the default takes a Uri? If all of them take dynamic then there's a check on each call to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd rather have a cleaner public API and add a private constructor for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. K works for me 👍 |
||
|
||
/// 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}) => | ||
_sendUnstreamed("GET", url, headers); | ||
FutureOr<Response> get(url, {Map<String, String> headers}) => | ||
send(new Request.get(_uri(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]. | ||
|
@@ -51,9 +49,10 @@ abstract class BaseClient implements Client { | |
/// [encoding] defaults to UTF-8. | ||
/// | ||
/// For more fine-grained control over the request, use [send] instead. | ||
Future<Response> post(url, {Map<String, String> headers, body, | ||
FutureOr<Response> post(url, body, {Map<String, String> headers, | ||
Encoding encoding}) => | ||
_sendUnstreamed("POST", url, headers, body, encoding); | ||
send(new Request.post(_uri(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]. | ||
|
@@ -73,9 +72,10 @@ abstract class BaseClient implements Client { | |
/// [encoding] defaults to UTF-8. | ||
/// | ||
/// For more fine-grained control over the request, use [send] instead. | ||
Future<Response> put(url, {Map<String, String> headers, body, | ||
FutureOr<Response> put(url, body, {Map<String, String> headers, | ||
Encoding encoding}) => | ||
_sendUnstreamed("PUT", url, headers, body, encoding); | ||
send(new Request.put(_uri(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]. | ||
|
@@ -95,16 +95,17 @@ abstract class BaseClient implements Client { | |
/// [encoding] defaults to UTF-8. | ||
/// | ||
/// For more fine-grained control over the request, use [send] instead. | ||
Future<Response> patch(url, {Map<String, String> headers, body, | ||
FutureOr<Response> patch(url, body, {Map<String, String> headers, | ||
Encoding encoding}) => | ||
_sendUnstreamed("PATCH", url, headers, body, encoding); | ||
send(new Request.patch(_uri(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}) => | ||
_sendUnstreamed("DELETE", url, headers); | ||
FutureOr<Response> delete(url, {Map<String, String> headers}) => | ||
send(new Request.delete(_uri(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 | ||
|
@@ -115,11 +116,11 @@ abstract class BaseClient implements Client { | |
/// | ||
/// For more fine-grained control over the request and response, use [send] or | ||
/// [get] instead. | ||
Future<String> read(url, {Map<String, String> headers}) { | ||
return get(url, headers: headers).then((response) { | ||
_checkResponseSuccess(url, response); | ||
return response.body; | ||
}); | ||
FutureOr<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 | ||
|
@@ -131,11 +132,11 @@ abstract class BaseClient implements Client { | |
/// | ||
/// For more fine-grained control over the request and response, use [send] or | ||
/// [get] instead. | ||
Future<Uint8List> readBytes(url, {Map<String, String> headers}) { | ||
return get(url, headers: headers).then((response) { | ||
_checkResponseSuccess(url, response); | ||
return response.bodyBytes; | ||
}); | ||
FutureOr<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. | ||
|
@@ -145,31 +146,7 @@ abstract class BaseClient implements Client { | |
/// 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<StreamedResponse> send(BaseRequest request); | ||
|
||
/// Sends a non-streaming [Request] and returns a non-streaming [Response]. | ||
Future<Response> _sendUnstreamed(String method, url, | ||
Map<String, String> headers, [body, Encoding encoding]) async { | ||
|
||
if (url is String) url = Uri.parse(url); | ||
var request = new Request(method, url); | ||
|
||
if (headers != null) request.headers.addAll(headers); | ||
if (encoding != null) request.encoding = encoding; | ||
if (body != null) { | ||
if (body is String) { | ||
request.body = body; | ||
} else if (body is List) { | ||
request.bodyBytes = DelegatingList.typed(body); | ||
} else if (body is Map) { | ||
request.bodyFields = DelegatingMap.typed(body); | ||
} else { | ||
throw new ArgumentError('Invalid request body "$body".'); | ||
} | ||
} | ||
|
||
return Response.fromStream(await send(request)); | ||
} | ||
FutureOr<Response> send(Request request); | ||
|
||
/// Throws an error if [response] is not successful. | ||
void _checkResponseSuccess(url, Response response) { | ||
|
@@ -187,3 +164,13 @@ abstract class BaseClient implements Client { | |
/// can cause the Dart process to hang. | ||
void close() {} | ||
} | ||
|
||
Uri _uri(url) { | ||
if (url is Uri) { | ||
return url; | ||
} else if (url is String) { | ||
return Uri.parse(url); | ||
} else { | ||
throw new ArgumentError.value(url, 'url', 'Not a Uri or String'); | ||
} | ||
} |
This file was deleted.
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.
Uh...these are always async, right?
Why the move to
FutureOr
?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.
@kevmoo the intent is to move to middleware like shelf.
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.
Okay...but do we imagine a future where these calls may be sync?
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.
Are we just talking http.dart or throughout? With the http helpers no.
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.
Exactly. So this method should always return
Future
.FutureOr
implies that it may synchronously returnResponse
.