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
This commit is contained in:
rnystrom@google.com 2012-11-30 18:21:41 +00:00
parent 0ddc6d93b1
commit 0c0d8d9dc7
2 changed files with 22 additions and 40 deletions

View file

@ -105,12 +105,17 @@ class CurlClient extends http.BaseClient {
/// 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 @@ class CurlClient extends http.BaseClient {
} 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 @@ class CurlClient extends http.BaseClient {
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;
}

View file

@ -204,11 +204,18 @@ main() {
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