Get curl uploads working on Mac.
Review URL: https://codereview.chromium.org//11411273
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@15592 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/utils/pub/curl_client.dart b/utils/pub/curl_client.dart
index 71b4701..e1afc2d 100644
--- a/utils/pub/curl_client.dart
+++ b/utils/pub/curl_client.dart
@@ -105,12 +105,17 @@
/// receiving the response headers. [expectBody] indicates that the server is
/// expected to send a response body (which is not the case for HEAD
/// requests).
+ ///
+ /// Curl prints the headers to a file and then prints the body to stdout. So,
+ /// in theory, we could read the headers as soon as we see anything appear
+ /// in stdout. However, that seems to be too early to successfully read the
+ /// file (at least on Mac). Instead, this just waits until the entire process
+ /// has completed.
Future _waitForHeaders(Process process, {bool expectBody}) {
- var exitCompleter = new Completer<int>();
- var exitFuture = exitCompleter.future;
+ var completer = new Completer();
process.onExit = (exitCode) {
if (exitCode == 0) {
- exitCompleter.complete(0);
+ completer.complete(null);
return;
}
@@ -122,7 +127,7 @@
} else {
throw new HttpException(message);
}
- }), exitCompleter);
+ }), completer);
};
// If there's not going to be a response body (e.g. for HEAD requests), curl
@@ -131,40 +136,10 @@
if (!expectBody) {
return Futures.wait([
consumeInputStream(process.stdout),
- exitFuture
+ completer.future
]);
}
- // TODO(nweiz): remove this when issue 4061 is fixed.
- var stackTrace;
- try {
- throw "";
- } catch (_, localStackTrace) {
- stackTrace = localStackTrace;
- }
-
- var completer = new Completer();
- resetCallbacks() {
- process.stdout.onData = null;
- process.stdout.onError = null;
- process.stdout.onClosed = null;
- }
- process.stdout.onData = () {
- // TODO(nweiz): If an error happens after the body data starts being
- // received, it should be piped through Response.stream once issue
- // 3657 is fixed.
- exitFuture.handleException((e) => true);
- resetCallbacks();
- completer.complete(null);
- };
- process.stdout.onError = (e) {
- resetCallbacks();
- completer.completeException(e, stackTrace);
- };
- process.stdout.onClosed = () {
- resetCallbacks();
- chainToCompleter(exitFuture, completer);
- };
return completer.future;
}
diff --git a/utils/tests/pub/pub_lish_test.dart b/utils/tests/pub/pub_lish_test.dart
index 1b7c633..aa67161 100644
--- a/utils/tests/pub/pub_lish_test.dart
+++ b/utils/tests/pub/pub_lish_test.dart
@@ -204,11 +204,18 @@
handleUploadForm(server);
server.handle('POST', '/upload', (request, response) {
- response.statusCode = 400;
- response.headers.contentType = new ContentType('application', 'xml');
- response.outputStream.writeString('<Error><Message>Your request sucked.'
- '</Message></Error>');
- return closeHttpResponse(request, response);
+ // TODO(rnystrom): HTTP requires that you don't start sending a response
+ // until the request has been completely sent, but dart:io doesn't
+ // ensure that (#7044). Workaround it by manually consuming the entire
+ // input stream before we start responding. If we don't do this, curl
+ // will choke on this on Mac and Windows.
+ return consumeInputStream(request.inputStream).transform((_) {
+ response.statusCode = 400;
+ response.headers.contentType = new ContentType('application', 'xml');
+ response.outputStream.writeString('<Error><Message>Your request sucked.'
+ '</Message></Error>');
+ response.outputStream.close();
+ });
});
// TODO(nweiz): This should use the server's error message once the client