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 |