OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library curl_client; | 5 library curl_client; |
6 | 6 |
7 import 'dart:io'; | 7 import 'dart:io'; |
8 | 8 |
9 import '../../pkg/http/lib/http.dart' as http; | 9 import '../../pkg/http/lib/http.dart' as http; |
10 import 'io.dart'; | 10 import 'io.dart'; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
98 }); | 98 }); |
99 arguments.add(request.url.toString()); | 99 arguments.add(request.url.toString()); |
100 | 100 |
101 return arguments; | 101 return arguments; |
102 } | 102 } |
103 | 103 |
104 /// Returns a [Future] that completes once the `curl` [process] has finished | 104 /// Returns a [Future] that completes once the `curl` [process] has finished |
105 /// receiving the response headers. [expectBody] indicates that the server is | 105 /// receiving the response headers. [expectBody] indicates that the server is |
106 /// expected to send a response body (which is not the case for HEAD | 106 /// expected to send a response body (which is not the case for HEAD |
107 /// requests). | 107 /// requests). |
108 Future _waitForHeaders(Process process, {bool expectBody}) { | 108 Future _waitForHeaders(Process process, {bool expectBody}) { |
nweiz
2012/11/30 01:19:45
If you're still going to call this "waitForHeaders
Bob Nystrom
2012/11/30 01:42:45
Added a comment explaining.
| |
109 var exitCompleter = new Completer<int>(); | 109 var completer = new Completer(); |
110 var exitFuture = exitCompleter.future; | |
111 process.onExit = (exitCode) { | 110 process.onExit = (exitCode) { |
112 if (exitCode == 0) { | 111 if (exitCode == 0) { |
113 exitCompleter.complete(0); | 112 completer.complete(null); |
114 return; | 113 return; |
115 } | 114 } |
116 | 115 |
117 chainToCompleter(consumeInputStream(process.stderr) | 116 chainToCompleter(consumeInputStream(process.stderr) |
118 .transform((stderrBytes) { | 117 .transform((stderrBytes) { |
119 var message = new String.fromCharCodes(stderrBytes); | 118 var message = new String.fromCharCodes(stderrBytes); |
120 if (exitCode == 47) { | 119 if (exitCode == 47) { |
121 throw new RedirectLimitExceededException([]); | 120 throw new RedirectLimitExceededException([]); |
122 } else { | 121 } else { |
123 throw new HttpException(message); | 122 throw new HttpException(message); |
124 } | 123 } |
125 }), exitCompleter); | 124 }), completer); |
126 }; | 125 }; |
127 | 126 |
128 // If there's not going to be a response body (e.g. for HEAD requests), curl | 127 // If there's not going to be a response body (e.g. for HEAD requests), curl |
129 // prints the headers to stdout instead of the body. We want to wait until | 128 // prints the headers to stdout instead of the body. We want to wait until |
130 // all the headers are received to read them from the header file. | 129 // all the headers are received to read them from the header file. |
131 if (!expectBody) { | 130 if (!expectBody) { |
132 return Futures.wait([ | 131 return Futures.wait([ |
133 consumeInputStream(process.stdout), | 132 consumeInputStream(process.stdout), |
134 exitFuture | 133 completer.future |
135 ]); | 134 ]); |
136 } | 135 } |
137 | 136 |
138 // TODO(nweiz): remove this when issue 4061 is fixed. | |
139 var stackTrace; | |
140 try { | |
141 throw ""; | |
142 } catch (_, localStackTrace) { | |
143 stackTrace = localStackTrace; | |
144 } | |
145 | |
146 var completer = new Completer(); | |
147 resetCallbacks() { | |
148 process.stdout.onData = null; | |
149 process.stdout.onError = null; | |
150 process.stdout.onClosed = null; | |
151 } | |
152 process.stdout.onData = () { | |
153 // TODO(nweiz): If an error happens after the body data starts being | |
154 // received, it should be piped through Response.stream once issue | |
155 // 3657 is fixed. | |
156 exitFuture.handleException((e) => true); | |
157 resetCallbacks(); | |
158 completer.complete(null); | |
159 }; | |
160 process.stdout.onError = (e) { | |
161 resetCallbacks(); | |
162 completer.completeException(e, stackTrace); | |
163 }; | |
164 process.stdout.onClosed = () { | |
165 resetCallbacks(); | |
166 chainToCompleter(exitFuture, completer); | |
167 }; | |
168 return completer.future; | 137 return completer.future; |
169 } | 138 } |
170 | 139 |
171 /// Returns a [http.StreamedResponse] from the response data printed by the | 140 /// Returns a [http.StreamedResponse] from the response data printed by the |
172 /// `curl` [process]. [lines] are the headers that `curl` wrote to a file. | 141 /// `curl` [process]. [lines] are the headers that `curl` wrote to a file. |
173 http.StreamedResponse _buildResponse( | 142 http.StreamedResponse _buildResponse( |
174 http.BaseRequest request, Process process, List<String> lines) { | 143 http.BaseRequest request, Process process, List<String> lines) { |
175 // When curl follows redirects, it prints the redirect headers as well as | 144 // When curl follows redirects, it prints the redirect headers as well as |
176 // the headers of the final request. Each block is separated by a blank | 145 // the headers of the final request. Each block is separated by a blank |
177 // line. We just care about the last block. There is one trailing empty | 146 // line. We just care about the last block. There is one trailing empty |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
211 /// path to the bundled `curl.exe`; elsewhere, this is just "curl", and we | 180 /// path to the bundled `curl.exe`; elsewhere, this is just "curl", and we |
212 /// assume it to be installed and on the user's PATH. | 181 /// assume it to be installed and on the user's PATH. |
213 static String get _defaultExecutable { | 182 static String get _defaultExecutable { |
214 if (Platform.operatingSystem != 'windows') return 'curl'; | 183 if (Platform.operatingSystem != 'windows') return 'curl'; |
215 // Note: This line of code gets munged by create_sdk.py to be the correct | 184 // Note: This line of code gets munged by create_sdk.py to be the correct |
216 // relative path to curl in the SDK. | 185 // relative path to curl in the SDK. |
217 var pathToCurl = "../../third_party/curl/curl.exe"; | 186 var pathToCurl = "../../third_party/curl/curl.exe"; |
218 return relativeToPub(pathToCurl); | 187 return relativeToPub(pathToCurl); |
219 } | 188 } |
220 } | 189 } |
OLD | NEW |