Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 http_server; | 5 library http_server; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:io'; | 8 import 'dart:io'; |
| 9 | 9 |
| 10 import 'dart:convert' show | 10 import 'dart:convert' show |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 49 | 49 |
| 50 /// Interface of the HTTP server: | 50 /// Interface of the HTTP server: |
| 51 /// | 51 /// |
| 52 /// /echo: This will stream the data received in the request stream back | 52 /// /echo: This will stream the data received in the request stream back |
| 53 /// to the client. | 53 /// to the client. |
| 54 /// /root_dart/X: This will serve the corresponding file from the dart | 54 /// /root_dart/X: This will serve the corresponding file from the dart |
| 55 /// directory (i.e. '$DartDirectory/X'). | 55 /// directory (i.e. '$DartDirectory/X'). |
| 56 /// /root_build/X: This will serve the corresponding file from the build | 56 /// /root_build/X: This will serve the corresponding file from the build |
| 57 /// directory (i.e. '$BuildDirectory/X'). | 57 /// directory (i.e. '$BuildDirectory/X'). |
| 58 /// /FOO/packages/BAR: This will serve the corresponding file from the packages | 58 /// /FOO/packages/BAR: This will serve the corresponding file from the packages |
| 59 /// directory (i.e. '$BuildDirectory/packages/BAR') | 59 /// directory (i.e. '$BuildDirectory/packages/BAR') or the |
| 60 /// passed in package root | |
|
Bill Hesse
2014/09/08 15:31:20
passed-in package root. Multi-word adjective phra
| |
| 60 /// /ws: This will upgrade the connection to a WebSocket connection and echo | 61 /// /ws: This will upgrade the connection to a WebSocket connection and echo |
| 61 /// all data back to the client. | 62 /// all data back to the client. |
| 62 /// | 63 /// |
| 63 /// In case a path does not refer to a file but rather to a directory, a | 64 /// In case a path does not refer to a file but rather to a directory, a |
| 64 /// directory listing will be displayed. | 65 /// directory listing will be displayed. |
| 65 | 66 |
| 66 const PREFIX_BUILDDIR = 'root_build'; | 67 const PREFIX_BUILDDIR = 'root_build'; |
| 67 const PREFIX_DARTDIR = 'root_dart'; | 68 const PREFIX_DARTDIR = 'root_dart'; |
| 68 | 69 |
| 69 // TODO(kustermann,ricow): We could change this to the following scheme: | 70 // TODO(kustermann,ricow): We could change this to the following scheme: |
| 70 // http://host:port/root_packages/X -> $BuildDir/packages/X | 71 // http://host:port/root_packages/X -> $BuildDir/packages/X |
| 71 // Issue: 8368 | 72 // Issue: 8368 |
| 72 | 73 |
| 73 main(List<String> arguments) { | 74 main(List<String> arguments) { |
| 74 // This script is in [dart]/tools/testing/dart. | 75 // This script is in [dart]/tools/testing/dart. |
| 75 TestUtils.setDartDirUri(Platform.script.resolve('../../..')); | 76 TestUtils.setDartDirUri(Platform.script.resolve('../../..')); |
| 76 /** Convenience method for local testing. */ | 77 /** Convenience method for local testing. */ |
| 77 var parser = new ArgParser(); | 78 var parser = new ArgParser(); |
| 78 parser.addOption('port', abbr: 'p', | 79 parser.addOption('port', abbr: 'p', |
| 79 help: 'The main server port we wish to respond to requests.', | 80 help: 'The main server port we wish to respond to requests.', |
| 80 defaultsTo: '0'); | 81 defaultsTo: '0'); |
| 81 parser.addOption('crossOriginPort', abbr: 'c', | 82 parser.addOption('crossOriginPort', abbr: 'c', |
| 82 help: 'A different port that accepts request from the main server port.', | 83 help: 'A different port that accepts request from the main server port.', |
| 83 defaultsTo: '0'); | 84 defaultsTo: '0'); |
| 84 parser.addFlag('help', abbr: 'h', negatable: false, | 85 parser.addFlag('help', abbr: 'h', negatable: false, |
| 85 help: 'Print this usage information.'); | 86 help: 'Print this usage information.'); |
| 86 parser.addOption('build-directory', help: 'The build directory to use.'); | 87 parser.addOption('build-directory', help: 'The build directory to use.'); |
| 88 parser.addOption('package-root', help: 'The package root to use.'); | |
| 87 parser.addOption('network', help: 'The network interface to use.', | 89 parser.addOption('network', help: 'The network interface to use.', |
| 88 defaultsTo: '0.0.0.0'); | 90 defaultsTo: '0.0.0.0'); |
| 89 parser.addFlag('csp', help: 'Use Content Security Policy restrictions.', | 91 parser.addFlag('csp', help: 'Use Content Security Policy restrictions.', |
| 90 defaultsTo: false); | 92 defaultsTo: false); |
| 91 parser.addOption('runtime', help: 'The runtime we are using (for csp flags).', | 93 parser.addOption('runtime', help: 'The runtime we are using (for csp flags).', |
| 92 defaultsTo: 'none'); | 94 defaultsTo: 'none'); |
| 93 | 95 |
| 94 var args = parser.parse(arguments); | 96 var args = parser.parse(arguments); |
| 95 if (args['help']) { | 97 if (args['help']) { |
| 96 print(parser.getUsage()); | 98 print(parser.getUsage()); |
| 97 } else { | 99 } else { |
| 98 var servers = new TestingServers(new Path(args['build-directory']), | 100 var servers = new TestingServers(new Path(args['build-directory']), |
| 99 args['csp'], | 101 args['csp'], |
| 100 args['runtime']); | 102 args['runtime'], |
| 103 null, | |
| 104 args['package-root']); | |
| 101 var port = int.parse(args['port']); | 105 var port = int.parse(args['port']); |
| 102 var crossOriginPort = int.parse(args['crossOriginPort']); | 106 var crossOriginPort = int.parse(args['crossOriginPort']); |
| 103 servers.startServers(args['network'], | 107 servers.startServers(args['network'], |
| 104 port: port, | 108 port: port, |
| 105 crossOriginPort: crossOriginPort).then((_) { | 109 crossOriginPort: crossOriginPort).then((_) { |
| 106 DebugLogger.info('Server listening on port ${servers.port}'); | 110 DebugLogger.info('Server listening on port ${servers.port}'); |
| 107 DebugLogger.info('Server listening on port ${servers.crossOriginPort}'); | 111 DebugLogger.info('Server listening on port ${servers.crossOriginPort}'); |
| 108 }); | 112 }); |
| 109 } | 113 } |
| 110 } | 114 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 129 "/NoSuchPart.dart", | 133 "/NoSuchPart.dart", |
| 130 "/Nonexistent_library.dart", | 134 "/Nonexistent_library.dart", |
| 131 "/missing_file", | 135 "/missing_file", |
| 132 "/xxx-missing.jpeg", | 136 "/xxx-missing.jpeg", |
| 133 "/does-not-exist.css" | 137 "/does-not-exist.css" |
| 134 ]; | 138 ]; |
| 135 | 139 |
| 136 List _serverList = []; | 140 List _serverList = []; |
| 137 Path _buildDirectory = null; | 141 Path _buildDirectory = null; |
| 138 Path _dartDirectory = null; | 142 Path _dartDirectory = null; |
| 143 Path _packageRoot; | |
| 139 final bool useContentSecurityPolicy; | 144 final bool useContentSecurityPolicy; |
| 140 final String runtime; | 145 final String runtime; |
| 141 DispatchingServer _server; | 146 DispatchingServer _server; |
| 142 | 147 |
| 143 TestingServers(Path buildDirectory, | 148 TestingServers(Path buildDirectory, |
| 144 this.useContentSecurityPolicy, | 149 this.useContentSecurityPolicy, |
| 145 [String this.runtime = 'none', String dartDirectory]) { | 150 [String this.runtime = 'none', String dartDirectory, |
| 151 String packageRoot]) { | |
| 146 _buildDirectory = TestUtils.absolutePath(buildDirectory); | 152 _buildDirectory = TestUtils.absolutePath(buildDirectory); |
| 147 _dartDirectory = dartDirectory == null ? TestUtils.dartDir | 153 _dartDirectory = dartDirectory == null ? TestUtils.dartDir |
| 148 : new Path(dartDirectory); | 154 : new Path(dartDirectory); |
| 155 _packageRoot = packageRoot == null ? | |
| 156 _buildDirectory.append('packages') : | |
| 157 new Path(packageRoot); | |
| 149 } | 158 } |
| 150 | 159 |
| 151 int get port => _serverList[0].port; | 160 int get port => _serverList[0].port; |
| 152 int get crossOriginPort => _serverList[1].port; | 161 int get crossOriginPort => _serverList[1].port; |
| 153 DispatchingServer get server => _server; | 162 DispatchingServer get server => _server; |
| 154 | 163 |
| 155 /** | 164 /** |
| 156 * [startServers] will start two Http servers. | 165 * [startServers] will start two Http servers. |
| 157 * The first server listens on [port] and sets | 166 * The first server listens on [port] and sets |
| 158 * "Access-Control-Allow-Origin: *" | 167 * "Access-Control-Allow-Origin: *" |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 169 }); | 178 }); |
| 170 } | 179 } |
| 171 | 180 |
| 172 String httpServerCommandline() { | 181 String httpServerCommandline() { |
| 173 var dart = TestUtils.dartTestExecutable.toNativePath(); | 182 var dart = TestUtils.dartTestExecutable.toNativePath(); |
| 174 var dartDir = TestUtils.dartDir; | 183 var dartDir = TestUtils.dartDir; |
| 175 var script = dartDir.join(new Path("tools/testing/dart/http_server.dart")); | 184 var script = dartDir.join(new Path("tools/testing/dart/http_server.dart")); |
| 176 var buildDirectory = _buildDirectory.toNativePath(); | 185 var buildDirectory = _buildDirectory.toNativePath(); |
| 177 var csp = useContentSecurityPolicy ? '--csp ' : ''; | 186 var csp = useContentSecurityPolicy ? '--csp ' : ''; |
| 178 return '$dart $script -p $port -c $crossOriginPort $csp' | 187 return '$dart $script -p $port -c $crossOriginPort $csp' |
| 179 '--build-directory=$buildDirectory --runtime=$runtime'; | 188 '--build-directory=$buildDirectory --runtime=$runtime ' |
| 189 '--package-root=$_packageRoot'; | |
| 180 } | 190 } |
| 181 | 191 |
| 182 void stopServers() { | 192 void stopServers() { |
| 183 for (var server in _serverList) { | 193 for (var server in _serverList) { |
| 184 server.close(); | 194 server.close(); |
| 185 } | 195 } |
| 186 } | 196 } |
| 187 | 197 |
| 188 void _onError(e) { | 198 void _onError(e) { |
| 189 DebugLogger.error('HttpServer: an error occured', e); | 199 DebugLogger.error('HttpServer: an error occured', e); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 206 } | 216 } |
| 207 | 217 |
| 208 void _handleFileOrDirectoryRequest(HttpRequest request, | 218 void _handleFileOrDirectoryRequest(HttpRequest request, |
| 209 int allowedPort) { | 219 int allowedPort) { |
| 210 // Enable browsers to cache file/directory responses. | 220 // Enable browsers to cache file/directory responses. |
| 211 var response = request.response; | 221 var response = request.response; |
| 212 response.headers.set("Cache-Control", | 222 response.headers.set("Cache-Control", |
| 213 "max-age=$_CACHE_EXPIRATION_IN_SECONDS"); | 223 "max-age=$_CACHE_EXPIRATION_IN_SECONDS"); |
| 214 var path = _getFilePathFromRequestPath(request.uri.path); | 224 var path = _getFilePathFromRequestPath(request.uri.path); |
| 215 if (path != null) { | 225 if (path != null) { |
| 226 | |
|
Bill Hesse
2014/09/08 15:31:20
Stray newline?
| |
| 216 var file = new File(path.toNativePath()); | 227 var file = new File(path.toNativePath()); |
| 217 file.exists().then((exists) { | 228 file.exists().then((exists) { |
| 218 if (exists) { | 229 if (exists) { |
| 219 _sendFileContent(request, response, allowedPort, path, file); | 230 _sendFileContent(request, response, allowedPort, path, file); |
| 220 } else { | 231 } else { |
| 221 var directory = new Directory(path.toNativePath()); | 232 var directory = new Directory(path.toNativePath()); |
| 222 directory.exists().then((exists) { | 233 directory.exists().then((exists) { |
| 223 if (exists) { | 234 if (exists) { |
| 224 _listDirectory(directory).then((entries) { | 235 _listDirectory(directory).then((entries) { |
| 225 _sendDirectoryListing(entries, request, response); | 236 _sendDirectoryListing(entries, request, response); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 var relativePath; | 287 var relativePath; |
| 277 if (pathSegments[0] == PREFIX_BUILDDIR) { | 288 if (pathSegments[0] == PREFIX_BUILDDIR) { |
| 278 basePath = _buildDirectory; | 289 basePath = _buildDirectory; |
| 279 relativePath = new Path( | 290 relativePath = new Path( |
| 280 pathSegments.skip(1).join('/')); | 291 pathSegments.skip(1).join('/')); |
| 281 } else if (pathSegments[0] == PREFIX_DARTDIR) { | 292 } else if (pathSegments[0] == PREFIX_DARTDIR) { |
| 282 basePath = _dartDirectory; | 293 basePath = _dartDirectory; |
| 283 relativePath = new Path( | 294 relativePath = new Path( |
| 284 pathSegments.skip(1).join('/')); | 295 pathSegments.skip(1).join('/')); |
| 285 } | 296 } |
| 286 var packagesDirName = 'packages'; | 297 var packagesDirName = 'packages'; |
|
Bill Hesse
2014/09/08 15:31:20
Maybe this variable is no longer worth having - on
| |
| 287 var packagesIndex = pathSegments.indexOf(packagesDirName); | 298 var packagesIndex = pathSegments.indexOf(packagesDirName); |
| 288 if (packagesIndex != -1) { | 299 if (packagesIndex != -1) { |
| 289 var start = packagesIndex + 1; | 300 var start = packagesIndex + 1; |
| 290 basePath = _buildDirectory.append(packagesDirName); | 301 basePath = _packageRoot; |
| 291 relativePath = new Path(pathSegments.skip(start).join('/')); | 302 relativePath = new Path(pathSegments.skip(start).join('/')); |
| 292 } | 303 } |
| 293 if (basePath != null && relativePath != null) { | 304 if (basePath != null && relativePath != null) { |
| 294 return basePath.join(relativePath); | 305 return basePath.join(relativePath); |
| 295 } | 306 } |
| 296 } | 307 } |
| 297 return null; | 308 return null; |
| 298 } | 309 } |
| 299 | 310 |
| 300 Future<List<_Entry>> _listDirectory(Directory directory) { | 311 Future<List<_Entry>> _listDirectory(Directory directory) { |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 450 class _Entry implements Comparable { | 461 class _Entry implements Comparable { |
| 451 final String name; | 462 final String name; |
| 452 final String displayName; | 463 final String displayName; |
| 453 | 464 |
| 454 _Entry(this.name, this.displayName); | 465 _Entry(this.name, this.displayName); |
| 455 | 466 |
| 456 int compareTo(_Entry other) { | 467 int compareTo(_Entry other) { |
| 457 return name.compareTo(other.name); | 468 return name.compareTo(other.name); |
| 458 } | 469 } |
| 459 } | 470 } |
| OLD | NEW |