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:async'; |
7 import 'dart:io'; | 8 import 'dart:io'; |
8 | 9 |
9 import '../../pkg/http/lib/http.dart' as http; | 10 import '../../pkg/http/lib/http.dart' as http; |
10 import 'io.dart'; | 11 import 'io.dart'; |
11 import 'log.dart' as log; | 12 import 'log.dart' as log; |
12 import 'utils.dart'; | 13 import 'utils.dart'; |
13 | 14 |
14 /// A drop-in replacement for [http.Client] that uses the `curl` command-line | 15 /// A drop-in replacement for [http.Client] that uses the `curl` command-line |
15 /// utility rather than [dart:io] to make requests. This class will only exist | 16 /// utility rather than [dart:io] to make requests. This class will only exist |
16 /// temporarily until [dart:io] natively supports requests over HTTPS. | 17 /// temporarily until [dart:io] natively supports requests over HTTPS. |
(...skipping 15 matching lines...) Expand all Loading... |
32 /// Sends a request via `curl` and returns the response. | 33 /// Sends a request via `curl` and returns the response. |
33 Future<http.StreamedResponse> send(http.BaseRequest request) { | 34 Future<http.StreamedResponse> send(http.BaseRequest request) { |
34 log.fine("Sending Curl request $request"); | 35 log.fine("Sending Curl request $request"); |
35 | 36 |
36 var requestStream = request.finalize(); | 37 var requestStream = request.finalize(); |
37 return withTempDir((tempDir) { | 38 return withTempDir((tempDir) { |
38 var headerFile = join(tempDir, "curl-headers"); | 39 var headerFile = join(tempDir, "curl-headers"); |
39 var arguments = _argumentsForRequest(request, headerFile); | 40 var arguments = _argumentsForRequest(request, headerFile); |
40 log.process(executable, arguments); | 41 log.process(executable, arguments); |
41 var process; | 42 var process; |
42 return startProcess(executable, arguments).chain((process_) { | 43 return startProcess(executable, arguments).then((process_) { |
43 process = process_; | 44 process = process_; |
44 if (requestStream.closed) { | 45 if (requestStream.closed) { |
45 process.stdin.close(); | 46 process.stdin.close(); |
46 } else { | 47 } else { |
47 requestStream.pipe(process.stdin); | 48 requestStream.pipe(process.stdin); |
48 } | 49 } |
49 | 50 |
50 return _waitForHeaders(process, expectBody: request.method != "HEAD"); | 51 return _waitForHeaders(process, expectBody: request.method != "HEAD"); |
51 }).chain((_) => new File(headerFile).readAsLines()) | 52 }).then((_) => new File(headerFile).readAsLines()) |
52 .transform((lines) => _buildResponse(request, process, lines)); | 53 .then((lines) => _buildResponse(request, process, lines)); |
53 }); | 54 }); |
54 } | 55 } |
55 | 56 |
56 /// Returns the list of arguments to `curl` necessary for performing | 57 /// Returns the list of arguments to `curl` necessary for performing |
57 /// [request]. [headerFile] is the path to the file where the response headers | 58 /// [request]. [headerFile] is the path to the file where the response headers |
58 /// should be stored. | 59 /// should be stored. |
59 List<String> _argumentsForRequest( | 60 List<String> _argumentsForRequest( |
60 http.BaseRequest request, String headerFile) { | 61 http.BaseRequest request, String headerFile) { |
61 // Note: This line of code gets munged by create_sdk.py to be the correct | 62 // Note: This line of code gets munged by create_sdk.py to be the correct |
62 // relative path to the certificate file in the SDK. | 63 // relative path to the certificate file in the SDK. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 var completer = new Completer(); | 120 var completer = new Completer(); |
120 process.onExit = (exitCode) { | 121 process.onExit = (exitCode) { |
121 log.io("Curl process exited with code $exitCode."); | 122 log.io("Curl process exited with code $exitCode."); |
122 | 123 |
123 if (exitCode == 0) { | 124 if (exitCode == 0) { |
124 completer.complete(null); | 125 completer.complete(null); |
125 return; | 126 return; |
126 } | 127 } |
127 | 128 |
128 chainToCompleter(consumeInputStream(process.stderr) | 129 chainToCompleter(consumeInputStream(process.stderr) |
129 .transform((stderrBytes) { | 130 .then((stderrBytes) { |
130 var message = new String.fromCharCodes(stderrBytes); | 131 var message = new String.fromCharCodes(stderrBytes); |
131 log.fine('Got error reading headers from curl: $message'); | 132 log.fine('Got error reading headers from curl: $message'); |
132 if (exitCode == 47) { | 133 if (exitCode == 47) { |
133 throw new RedirectLimitExceededException([]); | 134 throw new RedirectLimitExceededException([]); |
134 } else { | 135 } else { |
135 throw new HttpException(message); | 136 throw new HttpException(message); |
136 } | 137 } |
137 }), completer); | 138 }), completer); |
138 }; | 139 }; |
139 | 140 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 /// path to the bundled `curl.exe`; elsewhere, this is just "curl", and we | 194 /// path to the bundled `curl.exe`; elsewhere, this is just "curl", and we |
194 /// assume it to be installed and on the user's PATH. | 195 /// assume it to be installed and on the user's PATH. |
195 static String get _defaultExecutable { | 196 static String get _defaultExecutable { |
196 if (Platform.operatingSystem != 'windows') return 'curl'; | 197 if (Platform.operatingSystem != 'windows') return 'curl'; |
197 // Note: This line of code gets munged by create_sdk.py to be the correct | 198 // Note: This line of code gets munged by create_sdk.py to be the correct |
198 // relative path to curl in the SDK. | 199 // relative path to curl in the SDK. |
199 var pathToCurl = "../../third_party/curl/curl.exe"; | 200 var pathToCurl = "../../third_party/curl/curl.exe"; |
200 return relativeToPub(pathToCurl); | 201 return relativeToPub(pathToCurl); |
201 } | 202 } |
202 } | 203 } |
OLD | NEW |