| 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 27 matching lines...) Expand all Loading... |
| 38 return Process.start(executable, arguments).chain((process_) { | 38 return Process.start(executable, arguments).chain((process_) { |
| 39 process = process_; | 39 process = process_; |
| 40 if (requestStream.closed) { | 40 if (requestStream.closed) { |
| 41 process.stdin.close(); | 41 process.stdin.close(); |
| 42 } else { | 42 } else { |
| 43 requestStream.pipe(process.stdin); | 43 requestStream.pipe(process.stdin); |
| 44 } | 44 } |
| 45 | 45 |
| 46 return _waitForHeaders(process, expectBody: request.method != "HEAD"); | 46 return _waitForHeaders(process, expectBody: request.method != "HEAD"); |
| 47 }).chain((_) => new File(headerFile).readAsLines()) | 47 }).chain((_) => new File(headerFile).readAsLines()) |
| 48 .transform((lines) => _buildResponse(process, lines)); | 48 .transform((lines) => _buildResponse(request, process, lines)); |
| 49 }); | 49 }); |
| 50 } | 50 } |
| 51 | 51 |
| 52 /// Returns the list of arguments to `curl` necessary for performing | 52 /// Returns the list of arguments to `curl` necessary for performing |
| 53 /// [request]. [headerFile] is the path to the file where the response headers | 53 /// [request]. [headerFile] is the path to the file where the response headers |
| 54 /// should be stored. | 54 /// should be stored. |
| 55 List<String> _argumentsForRequest( | 55 List<String> _argumentsForRequest( |
| 56 http.BaseRequest request, String headerFile) { | 56 http.BaseRequest request, String headerFile) { |
| 57 // Note: This line of code gets munged by create_sdk.py to be the correct | 57 // Note: This line of code gets munged by create_sdk.py to be the correct |
| 58 // relative path to the certificate file in the SDK. | 58 // relative path to the certificate file in the SDK. |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 }; | 163 }; |
| 164 process.stdout.onClosed = () { | 164 process.stdout.onClosed = () { |
| 165 resetCallbacks(); | 165 resetCallbacks(); |
| 166 chainToCompleter(exitFuture, completer); | 166 chainToCompleter(exitFuture, completer); |
| 167 }; | 167 }; |
| 168 return completer.future; | 168 return completer.future; |
| 169 } | 169 } |
| 170 | 170 |
| 171 /// Returns a [http.StreamedResponse] from the response data printed by the | 171 /// Returns a [http.StreamedResponse] from the response data printed by the |
| 172 /// `curl` [process]. [lines] are the headers that `curl` wrote to a file. | 172 /// `curl` [process]. [lines] are the headers that `curl` wrote to a file. |
| 173 http.StreamedResponse _buildResponse(Process process, List<String> lines) { | 173 http.StreamedResponse _buildResponse( |
| 174 http.BaseRequest request, Process process, List<String> lines) { |
| 174 // When curl follows redirects, it prints the redirect headers as well as | 175 // When curl follows redirects, it prints the redirect headers as well as |
| 175 // the headers of the final request. Each block is separated by a blank | 176 // the headers of the final request. Each block is separated by a blank |
| 176 // line. We just care about the last block. There is one trailing empty | 177 // line. We just care about the last block. There is one trailing empty |
| 177 // line, though, which we don't want to consider a separator. | 178 // line, though, which we don't want to consider a separator. |
| 178 var lastBlank = lines.lastIndexOf("", lines.length - 2); | 179 var lastBlank = lines.lastIndexOf("", lines.length - 2); |
| 179 if (lastBlank != -1) lines.removeRange(0, lastBlank + 1); | 180 if (lastBlank != -1) lines.removeRange(0, lastBlank + 1); |
| 180 | 181 |
| 181 var statusParts = lines.removeAt(0).split(" "); | 182 var statusParts = lines.removeAt(0).split(" "); |
| 182 var status = int.parse(statusParts[1]); | 183 var status = int.parse(statusParts[1]); |
| 183 var isRedirect = status >= 300 && status < 400; | 184 var isRedirect = status >= 300 && status < 400; |
| 184 var reasonPhrase = | 185 var reasonPhrase = |
| 185 Strings.join(statusParts.getRange(2, statusParts.length - 2), " "); | 186 Strings.join(statusParts.getRange(2, statusParts.length - 2), " "); |
| 186 var headers = <String>{}; | 187 var headers = <String>{}; |
| 187 for (var line in lines) { | 188 for (var line in lines) { |
| 188 if (line.isEmpty) continue; | 189 if (line.isEmpty) continue; |
| 189 var split = split1(line, ":"); | 190 var split = split1(line, ":"); |
| 190 headers[split[0].toLowerCase()] = split[1].trim(); | 191 headers[split[0].toLowerCase()] = split[1].trim(); |
| 191 } | 192 } |
| 192 var responseStream = process.stdout; | 193 var responseStream = process.stdout; |
| 193 if (responseStream.closed) { | 194 if (responseStream.closed) { |
| 194 responseStream = new ListInputStream(); | 195 responseStream = new ListInputStream(); |
| 195 responseStream.markEndOfStream(); | 196 responseStream.markEndOfStream(); |
| 196 } | 197 } |
| 197 var contentLength = -1; | 198 var contentLength = -1; |
| 198 if (headers.containsKey('content-length')) { | 199 if (headers.containsKey('content-length')) { |
| 199 contentLength = int.parse(headers['content-length']); | 200 contentLength = int.parse(headers['content-length']); |
| 200 } | 201 } |
| 201 | 202 |
| 202 return new http.StreamedResponse(responseStream, status, contentLength, | 203 return new http.StreamedResponse(responseStream, status, contentLength, |
| 204 request: request, |
| 203 headers: headers, | 205 headers: headers, |
| 204 isRedirect: isRedirect, | 206 isRedirect: isRedirect, |
| 205 reasonPhrase: reasonPhrase); | 207 reasonPhrase: reasonPhrase); |
| 206 } | 208 } |
| 207 | 209 |
| 208 /// The default executable to use for running curl. On Windows, this is the | 210 /// The default executable to use for running curl. On Windows, this is the |
| 209 /// path to the bundled `curl.exe`; elsewhere, this is just "curl", and we | 211 /// path to the bundled `curl.exe`; elsewhere, this is just "curl", and we |
| 210 /// assume it to be installed and on the user's PATH. | 212 /// assume it to be installed and on the user's PATH. |
| 211 static String get _defaultExecutable { | 213 static String get _defaultExecutable { |
| 212 if (Platform.operatingSystem != 'windows') return 'curl'; | 214 if (Platform.operatingSystem != 'windows') return 'curl'; |
| 213 // Note: This line of code gets munged by create_sdk.py to be the correct | 215 // Note: This line of code gets munged by create_sdk.py to be the correct |
| 214 // relative path to curl in the SDK. | 216 // relative path to curl in the SDK. |
| 215 var pathToCurl = "../../third_party/curl/curl.exe"; | 217 var pathToCurl = "../../third_party/curl/curl.exe"; |
| 216 return relativeToPub(pathToCurl); | 218 return relativeToPub(pathToCurl); |
| 217 } | 219 } |
| 218 } | 220 } |
| OLD | NEW |