| 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 import 'dart:isolate'; | 9 import 'dart:isolate'; |
| 10 import 'dart:uri'; | 10 import 'dart:uri'; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 parser.addOption('crossOriginPort', abbr: 'c', | 48 parser.addOption('crossOriginPort', abbr: 'c', |
| 49 help: 'A different port that accepts request from the main server port.', | 49 help: 'A different port that accepts request from the main server port.', |
| 50 defaultsTo: '0'); | 50 defaultsTo: '0'); |
| 51 parser.addFlag('help', abbr: 'h', negatable: false, | 51 parser.addFlag('help', abbr: 'h', negatable: false, |
| 52 help: 'Print this usage information.'); | 52 help: 'Print this usage information.'); |
| 53 parser.addOption('build-directory', help: 'The build directory to use.'); | 53 parser.addOption('build-directory', help: 'The build directory to use.'); |
| 54 parser.addOption('network', help: 'The network interface to use.', | 54 parser.addOption('network', help: 'The network interface to use.', |
| 55 defaultsTo: '127.0.0.1'); | 55 defaultsTo: '127.0.0.1'); |
| 56 parser.addFlag('csp', help: 'Use Content Security Policy restrictions.', | 56 parser.addFlag('csp', help: 'Use Content Security Policy restrictions.', |
| 57 defaultsTo: false); | 57 defaultsTo: false); |
| 58 parser.addOption('runtime', help: 'The runtime we are using (for csp flags).', |
| 59 defaultsTo: 'none'); |
| 60 |
| 58 var args = parser.parse(new Options().arguments); | 61 var args = parser.parse(new Options().arguments); |
| 59 if (args['help']) { | 62 if (args['help']) { |
| 60 print(parser.getUsage()); | 63 print(parser.getUsage()); |
| 61 } else { | 64 } else { |
| 62 // Pretend we're running test.dart so that TestUtils doesn't get confused | 65 // Pretend we're running test.dart so that TestUtils doesn't get confused |
| 63 // about the "current directory." This is only used if we're trying to run | 66 // about the "current directory." This is only used if we're trying to run |
| 64 // this file independently for local testing. | 67 // this file independently for local testing. |
| 65 TestUtils.testScriptPath = new Path(new Options().script) | 68 TestUtils.testScriptPath = new Path(new Options().script) |
| 66 .directoryPath | 69 .directoryPath |
| 67 .join(new Path('../../test.dart')) | 70 .join(new Path('../../test.dart')) |
| 68 .canonicalize() | 71 .canonicalize() |
| 69 .toNativePath(); | 72 .toNativePath(); |
| 70 var servers = new TestingServers(new Path(args['build-directory']), | 73 var servers = new TestingServers(new Path(args['build-directory']), |
| 71 args['csp']); | 74 args['csp'], |
| 75 args['runtime']); |
| 72 var port = int.parse(args['port']); | 76 var port = int.parse(args['port']); |
| 73 var crossOriginPort = int.parse(args['crossOriginPort']); | 77 var crossOriginPort = int.parse(args['crossOriginPort']); |
| 74 servers.startServers(args['network'], | 78 servers.startServers(args['network'], |
| 75 port: port, | 79 port: port, |
| 76 crossOriginPort: crossOriginPort).then((_) { | 80 crossOriginPort: crossOriginPort).then((_) { |
| 77 DebugLogger.info('Server listening on port ${servers.port}'); | 81 DebugLogger.info('Server listening on port ${servers.port}'); |
| 78 DebugLogger.info('Server listening on port ${servers.crossOriginPort}'); | 82 DebugLogger.info('Server listening on port ${servers.crossOriginPort}'); |
| 79 }); | 83 }); |
| 80 } | 84 } |
| 81 } | 85 } |
| 82 | 86 |
| 83 /** | 87 /** |
| 84 * Runs a set of servers that are initialized specifically for the needs of our | 88 * Runs a set of servers that are initialized specifically for the needs of our |
| 85 * test framework, such as dealing with package-root. | 89 * test framework, such as dealing with package-root. |
| 86 */ | 90 */ |
| 87 class TestingServers { | 91 class TestingServers { |
| 88 List _serverList = []; | 92 List _serverList = []; |
| 89 Path _buildDirectory = null; | 93 Path _buildDirectory = null; |
| 90 final bool useContentSecurityPolicy; | 94 final bool useContentSecurityPolicy; |
| 95 final String runtime; |
| 91 | 96 |
| 92 TestingServers(Path buildDirectory, this.useContentSecurityPolicy) { | 97 TestingServers(Path buildDirectory, |
| 98 this.useContentSecurityPolicy, |
| 99 [String this.runtime = 'none']) { |
| 93 _buildDirectory = TestUtils.absolutePath(buildDirectory); | 100 _buildDirectory = TestUtils.absolutePath(buildDirectory); |
| 94 } | 101 } |
| 95 | 102 |
| 96 int get port => _serverList[0].port; | 103 int get port => _serverList[0].port; |
| 97 int get crossOriginPort => _serverList[1].port; | 104 int get crossOriginPort => _serverList[1].port; |
| 98 | 105 |
| 99 /** | 106 /** |
| 100 * [startServers] will start two Http servers. | 107 * [startServers] will start two Http servers. |
| 101 * The first server listens on [port] and sets | 108 * The first server listens on [port] and sets |
| 102 * "Access-Control-Allow-Origin: *" | 109 * "Access-Control-Allow-Origin: *" |
| 103 * The second server listens on [crossOriginPort] and sets | 110 * The second server listens on [crossOriginPort] and sets |
| 104 * "Access-Control-Allow-Origin: client:port1 | 111 * "Access-Control-Allow-Origin: client:port1 |
| 105 * "Access-Control-Allow-Credentials: true" | 112 * "Access-Control-Allow-Credentials: true" |
| 106 */ | 113 */ |
| 107 Future startServers(String host, {int port: 0, int crossOriginPort: 0}) { | 114 Future startServers(String host, {int port: 0, int crossOriginPort: 0}) { |
| 108 return _startHttpServer(host, port: port).then((server) { | 115 return _startHttpServer(host, port: port).then((server) { |
| 109 return _startHttpServer(host, | 116 return _startHttpServer(host, |
| 110 port: crossOriginPort, | 117 port: crossOriginPort, |
| 111 allowedPort:_serverList[0].port); | 118 allowedPort:_serverList[0].port); |
| 112 }); | 119 }); |
| 113 } | 120 } |
| 114 | 121 |
| 115 String httpServerCommandline() { | 122 String httpServerCommandline() { |
| 116 var dart = TestUtils.dartTestExecutable.toNativePath(); | 123 var dart = TestUtils.dartTestExecutable.toNativePath(); |
| 117 var dartDir = TestUtils.dartDir(); | 124 var dartDir = TestUtils.dartDir(); |
| 118 var script = dartDir.join(new Path("tools/testing/dart/http_server.dart")); | 125 var script = dartDir.join(new Path("tools/testing/dart/http_server.dart")); |
| 119 var buildDirectory = _buildDirectory.toNativePath(); | 126 var buildDirectory = _buildDirectory.toNativePath(); |
| 120 var csp = useContentSecurityPolicy ? '--csp ' : ''; | 127 var csp = useContentSecurityPolicy ? '--csp ' : ''; |
| 121 | |
| 122 return '$dart $script -p $port -c $crossOriginPort $csp' | 128 return '$dart $script -p $port -c $crossOriginPort $csp' |
| 123 '--build-directory=$buildDirectory'; | 129 '--build-directory=$buildDirectory --runtime=$runtime'; |
| 124 } | 130 } |
| 125 | 131 |
| 126 void stopServers() { | 132 void stopServers() { |
| 127 for (var server in _serverList) { | 133 for (var server in _serverList) { |
| 128 server.close(); | 134 server.close(); |
| 129 } | 135 } |
| 130 } | 136 } |
| 131 | 137 |
| 132 Future _startHttpServer(String host, {int port: 0, int allowedPort: -1}) { | 138 Future _startHttpServer(String host, {int port: 0, int allowedPort: -1}) { |
| 133 return HttpServer.bind(host, port).then((HttpServer httpServer) { | 139 return HttpServer.bind(host, port).then((HttpServer httpServer) { |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 response.headers.set('Access-Control-Allow-Credentials', 'true'); | 319 response.headers.set('Access-Control-Allow-Credentials', 'true'); |
| 314 } else { | 320 } else { |
| 315 // No allowedPort specified. Allow from anywhere (but cross-origin | 321 // No allowedPort specified. Allow from anywhere (but cross-origin |
| 316 // requests *with credentials* will fail because you can't use "*"). | 322 // requests *with credentials* will fail because you can't use "*"). |
| 317 response.headers.set("Access-Control-Allow-Origin", "*"); | 323 response.headers.set("Access-Control-Allow-Origin", "*"); |
| 318 } | 324 } |
| 319 if (useContentSecurityPolicy) { | 325 if (useContentSecurityPolicy) { |
| 320 // Chrome respects the standardized Content-Security-Policy header, | 326 // Chrome respects the standardized Content-Security-Policy header, |
| 321 // whereas Firefox and IE10 use X-Content-Security-Policy. Safari | 327 // whereas Firefox and IE10 use X-Content-Security-Policy. Safari |
| 322 // still uses the WebKit- prefixed version. | 328 // still uses the WebKit- prefixed version. |
| 329 var content_header_value = "script-src 'self'; object-src 'self'"; |
| 323 for (var header in ["Content-Security-Policy", | 330 for (var header in ["Content-Security-Policy", |
| 324 "X-Content-Security-Policy", | 331 "X-Content-Security-Policy"]) { |
| 325 "X-WebKit-CSP"]) { | 332 response.headers.set(header, content_header_value); |
| 326 response.headers.set(header, "script-src 'self'; object-src 'self'"); | 333 } |
| 334 if (const ["safari"].contains(runtime)) { |
| 335 response.headers.set("X-WebKit-CSP", content_header_value); |
| 327 } | 336 } |
| 328 } | 337 } |
| 329 if (path.filename.endsWith('.html')) { | 338 if (path.filename.endsWith('.html')) { |
| 330 response.headers.set('Content-Type', 'text/html'); | 339 response.headers.set('Content-Type', 'text/html'); |
| 331 } else if (path.filename.endsWith('.js')) { | 340 } else if (path.filename.endsWith('.js')) { |
| 332 response.headers.set('Content-Type', 'application/javascript'); | 341 response.headers.set('Content-Type', 'application/javascript'); |
| 333 } else if (path.filename.endsWith('.dart')) { | 342 } else if (path.filename.endsWith('.dart')) { |
| 334 response.headers.set('Content-Type', 'application/dart'); | 343 response.headers.set('Content-Type', 'application/dart'); |
| 335 } | 344 } |
| 336 file.openRead().pipe(response).catchError((e) { | 345 file.openRead().pipe(response).catchError((e) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 360 class _Entry { | 369 class _Entry { |
| 361 final String name; | 370 final String name; |
| 362 final String displayName; | 371 final String displayName; |
| 363 | 372 |
| 364 _Entry(this.name, this.displayName); | 373 _Entry(this.name, this.displayName); |
| 365 | 374 |
| 366 int compareTo(_Entry other) { | 375 int compareTo(_Entry other) { |
| 367 return name.compareTo(other.name); | 376 return name.compareTo(other.name); |
| 368 } | 377 } |
| 369 } | 378 } |
| OLD | NEW |