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 HtmlEscape; | 10 import 'dart:convert' show HtmlEscape; |
11 | 11 |
12 import 'path.dart'; | |
13 import 'test_suite.dart'; // For TestUtils. | 12 import 'test_suite.dart'; // For TestUtils. |
14 // TODO(efortuna): Rewrite to not use the args library and simply take an | |
15 // expected number of arguments, so test.dart doesn't rely on the args library? | |
16 // See discussion on https://codereview.chromium.org/11931025/. | |
17 import 'vendored_pkg/args/args.dart'; | 13 import 'vendored_pkg/args/args.dart'; |
18 import 'utils.dart'; | 14 import 'utils.dart'; |
| 15 import 'package:package_resolver/package_resolver.dart'; |
19 | 16 |
20 class DispatchingServer { | 17 class DispatchingServer { |
21 HttpServer server; | 18 HttpServer server; |
22 Map<String, Function> _handlers = new Map<String, Function>(); | 19 Map<String, Function> _handlers = new Map<String, Function>(); |
23 Function _notFound; | 20 Function _notFound; |
24 | 21 |
25 DispatchingServer( | 22 DispatchingServer( |
26 this.server, void onError(e), void this._notFound(HttpRequest request)) { | 23 this.server, void onError(e), void this._notFound(HttpRequest request)) { |
27 server.listen(_dispatchRequest, onError: onError); | 24 server.listen(_dispatchRequest, onError: onError); |
28 } | 25 } |
(...skipping 16 matching lines...) Expand all Loading... |
45 } | 42 } |
46 | 43 |
47 /// Interface of the HTTP server: | 44 /// Interface of the HTTP server: |
48 /// | 45 /// |
49 /// /echo: This will stream the data received in the request stream back | 46 /// /echo: This will stream the data received in the request stream back |
50 /// to the client. | 47 /// to the client. |
51 /// /root_dart/X: This will serve the corresponding file from the dart | 48 /// /root_dart/X: This will serve the corresponding file from the dart |
52 /// directory (i.e. '$DartDirectory/X'). | 49 /// directory (i.e. '$DartDirectory/X'). |
53 /// /root_build/X: This will serve the corresponding file from the build | 50 /// /root_build/X: This will serve the corresponding file from the build |
54 /// directory (i.e. '$BuildDirectory/X'). | 51 /// directory (i.e. '$BuildDirectory/X'). |
55 /// /FOO/packages/BAR: This will serve the corresponding file from the packages | 52 /// /FOO/packages/PAZ/BAR: This will serve files from the packages listed in |
56 /// directory (i.e. '$BuildDirectory/packages/BAR') or the | 53 /// the package spec .packages. Supports a package |
57 /// passed-in package root | 54 /// root or custom package spec, and uses [dart_dir]/.packages |
| 55 /// as the default. This will serve file lib/BAR from the package PAZ. |
58 /// /ws: This will upgrade the connection to a WebSocket connection and echo | 56 /// /ws: This will upgrade the connection to a WebSocket connection and echo |
59 /// all data back to the client. | 57 /// all data back to the client. |
60 /// | 58 /// |
61 /// In case a path does not refer to a file but rather to a directory, a | 59 /// In case a path does not refer to a file but rather to a directory, a |
62 /// directory listing will be displayed. | 60 /// directory listing will be displayed. |
63 | 61 |
64 const PREFIX_BUILDDIR = 'root_build'; | 62 const PREFIX_BUILDDIR = 'root_build'; |
65 const PREFIX_DARTDIR = 'root_dart'; | 63 const PREFIX_DARTDIR = 'root_dart'; |
66 | 64 |
67 // TODO(kustermann,ricow): We could change this to the following scheme: | |
68 // http://host:port/root_packages/X -> $BuildDir/packages/X | |
69 // Issue: 8368 | |
70 | |
71 main(List<String> arguments) { | 65 main(List<String> arguments) { |
72 // This script is in [dart]/tools/testing/dart. | 66 // This script is in [dart]/tools/testing/dart. |
73 TestUtils.setDartDirUri(Platform.script.resolve('../../..')); | 67 TestUtils.setDartDirUri(Platform.script.resolve('../../..')); |
74 /** Convenience method for local testing. */ | 68 /** Convenience method for local testing. */ |
75 var parser = new ArgParser(); | 69 var parser = new ArgParser(); |
76 parser.addOption('port', | 70 parser.addOption('port', |
77 abbr: 'p', | 71 abbr: 'p', |
78 help: 'The main server port we wish to respond to requests.', | 72 help: 'The main server port we wish to respond to requests.', |
79 defaultsTo: '0'); | 73 defaultsTo: '0'); |
80 parser.addOption('crossOriginPort', | 74 parser.addOption('crossOriginPort', |
81 abbr: 'c', | 75 abbr: 'c', |
82 help: 'A different port that accepts request from the main server port.', | 76 help: 'A different port that accepts request from the main server port.', |
83 defaultsTo: '0'); | 77 defaultsTo: '0'); |
84 parser.addFlag('help', | 78 parser.addFlag('help', |
85 abbr: 'h', negatable: false, help: 'Print this usage information.'); | 79 abbr: 'h', negatable: false, help: 'Print this usage information.'); |
86 parser.addOption('build-directory', help: 'The build directory to use.'); | 80 parser.addOption('build-directory', help: 'The build directory to use.'); |
87 parser.addOption('package-root', help: 'The package root to use.'); | 81 parser.addOption('package-root', help: 'The package root to use.'); |
88 parser.addOption('packages', help: 'The package spec file to use.'); | 82 parser.addOption('packages', help: 'The package spec file to use.'); |
89 parser.addOption('network', | 83 parser.addOption('network', |
90 help: 'The network interface to use.', defaultsTo: '0.0.0.0'); | 84 help: 'The network interface to use.', defaultsTo: '0.0.0.0'); |
91 parser.addFlag('csp', | 85 parser.addFlag('csp', |
92 help: 'Use Content Security Policy restrictions.', defaultsTo: false); | 86 help: 'Use Content Security Policy restrictions.', defaultsTo: false); |
93 parser.addOption('runtime', | 87 parser.addOption('runtime', |
94 help: 'The runtime we are using (for csp flags).', defaultsTo: 'none'); | 88 help: 'The runtime we are using (for csp flags).', defaultsTo: 'none'); |
95 | 89 |
96 var args = parser.parse(arguments); | 90 var args = parser.parse(arguments); |
97 if (args['help']) { | 91 if (args['help']) { |
98 print(parser.getUsage()); | 92 print(parser.getUsage()); |
99 } else { | 93 } else { |
100 var servers = new TestingServers(new Path(args['build-directory']), | 94 var servers = new TestingServers(args['build-directory'], |
101 args['csp'], args['runtime'], null, args['package-root'], | 95 args['csp'], args['runtime'], null, args['package-root'], |
102 args['packages']); | 96 args['packages']); |
103 var port = int.parse(args['port']); | 97 var port = int.parse(args['port']); |
104 var crossOriginPort = int.parse(args['crossOriginPort']); | 98 var crossOriginPort = int.parse(args['crossOriginPort']); |
105 servers | 99 servers |
106 .startServers(args['network'], | 100 .startServers(args['network'], |
107 port: port, crossOriginPort: crossOriginPort) | 101 port: port, crossOriginPort: crossOriginPort) |
108 .then((_) { | 102 .then((_) { |
109 DebugLogger.info('Server listening on port ${servers.port}'); | 103 DebugLogger.info('Server listening on port ${servers.port}'); |
110 DebugLogger.info('Server listening on port ${servers.crossOriginPort}'); | 104 DebugLogger.info('Server listening on port ${servers.crossOriginPort}'); |
(...skipping 11 matching lines...) Expand all Loading... |
122 "/apple-touch-icon.png", | 116 "/apple-touch-icon.png", |
123 "/apple-touch-icon-precomposed.png", | 117 "/apple-touch-icon-precomposed.png", |
124 "/favicon.ico", | 118 "/favicon.ico", |
125 "/foo", | 119 "/foo", |
126 "/bar", | 120 "/bar", |
127 "/NonExistingFile", | 121 "/NonExistingFile", |
128 "IntentionallyMissingFile", | 122 "IntentionallyMissingFile", |
129 ]; | 123 ]; |
130 | 124 |
131 List _serverList = []; | 125 List _serverList = []; |
132 Path _buildDirectory = null; | 126 Uri _buildDirectory = null; |
133 Path _dartDirectory = null; | 127 Uri _dartDirectory = null; |
134 Path _packageRoot; | 128 Uri _packageRoot; |
135 Path _packages; | 129 Uri _packages; |
136 final bool useContentSecurityPolicy; | 130 final bool useContentSecurityPolicy; |
137 final String runtime; | 131 final String runtime; |
138 DispatchingServer _server; | 132 DispatchingServer _server; |
| 133 SyncPackageResolver _resolver; |
139 | 134 |
140 TestingServers(Path buildDirectory, this.useContentSecurityPolicy, | 135 TestingServers(String buildDirectory, this.useContentSecurityPolicy, |
141 [String this.runtime = 'none', | 136 [String this.runtime = 'none', |
142 String dartDirectory, | 137 String dartDirectory, |
143 String packageRoot, | 138 String packageRoot, |
144 String packages]) { | 139 String packages]) { |
145 _buildDirectory = TestUtils.absolutePath(buildDirectory); | 140 _buildDirectory = Uri.base.resolveUri(new Uri.directory(buildDirectory)); |
146 _dartDirectory = | 141 if (dartDirectory == null) { |
147 dartDirectory == null ? TestUtils.dartDir : new Path(dartDirectory); | 142 _dartDirectory = TestUtils.dartDirUri; |
148 _packageRoot = packageRoot == null | 143 } else { |
149 ? (packages == null ? _buildDirectory.append('packages') : null) | 144 _dartDirectory = Uri.base.resolveUri(new Uri.directory(dartDirectory)); |
150 : new Path(packageRoot); | 145 } |
151 _packages = packages == null ? null : new Path(packages); | 146 if (packageRoot == null ) { |
| 147 if (packages == null ) { |
| 148 _packages = _dartDirectory.resolve('.packages'); |
| 149 } else { |
| 150 _packages = new Uri.file(packages); |
| 151 } |
| 152 } else { |
| 153 _packageRoot = new Uri.directory(packageRoot); |
| 154 } |
152 } | 155 } |
153 | 156 |
154 int get port => _serverList[0].port; | 157 int get port => _serverList[0].port; |
155 int get crossOriginPort => _serverList[1].port; | 158 int get crossOriginPort => _serverList[1].port; |
156 DispatchingServer get server => _server; | 159 DispatchingServer get server => _server; |
157 | 160 |
158 /** | 161 /** |
159 * [startServers] will start two Http servers. | 162 * [startServers] will start two Http servers. |
160 * The first server listens on [port] and sets | 163 * The first server listens on [port] and sets |
161 * "Access-Control-Allow-Origin: *" | 164 * "Access-Control-Allow-Origin: *" |
162 * The second server listens on [crossOriginPort] and sets | 165 * The second server listens on [crossOriginPort] and sets |
163 * "Access-Control-Allow-Origin: client:port1 | 166 * "Access-Control-Allow-Origin: client:port1 |
164 * "Access-Control-Allow-Credentials: true" | 167 * "Access-Control-Allow-Credentials: true" |
165 */ | 168 */ |
166 Future startServers(String host, {int port: 0, int crossOriginPort: 0}) { | 169 Future startServers(String host, |
167 return _startHttpServer(host, port: port).then((server) { | 170 {int port: 0, |
168 _server = server; | 171 int crossOriginPort: 0}) async { |
169 return _startHttpServer(host, | 172 if (_packages != null) { |
170 port: crossOriginPort, allowedPort: _serverList[0].port); | 173 _resolver = await SyncPackageResolver.loadConfig(_packages); |
171 }); | 174 } else { |
| 175 _resolver = new SyncPackageResolver.root(_packageRoot); |
| 176 } |
| 177 _server = await _startHttpServer(host, port: port); |
| 178 await _startHttpServer(host, port: crossOriginPort, |
| 179 allowedPort: _serverList[0].port); |
172 } | 180 } |
173 | 181 |
174 String httpServerCommandline() { | 182 String httpServerCommandline() { |
175 var dart = Platform.resolvedExecutable; | 183 var dart = Platform.resolvedExecutable; |
176 var dartDir = TestUtils.dartDir; | 184 var script = _dartDirectory.resolve('tools/testing/dart/http_server.dart'); |
177 var script = dartDir.join(new Path("tools/testing/dart/http_server.dart")); | 185 var buildDirectory = _buildDirectory.toFilePath(); |
178 var buildDirectory = _buildDirectory.toNativePath(); | 186 var command = [dart, script.toFilePath(), |
179 var csp = useContentSecurityPolicy ? '--csp ' : ''; | 187 '-p', port, |
180 return '$dart $script -p $port -c $crossOriginPort $csp' | 188 '-c', crossOriginPort, |
181 '--build-directory=$buildDirectory --runtime=$runtime ' | 189 '--build-directory=$buildDirectory', |
182 '--package-root=$_packageRoot'; | 190 '--runtime=$runtime']; |
| 191 if (useContentSecurityPolicy) { |
| 192 command.add('--csp'); |
| 193 } |
| 194 if (_packages != null) { |
| 195 command.add('--packages=${_packages.toFilePath()}'); |
| 196 } else if (_packageRoot != null) { |
| 197 command.add('--package-root=${_packageRoot.toFilePath()}'); |
| 198 } |
| 199 return command.join(' '); |
183 } | 200 } |
184 | 201 |
185 void stopServers() { | 202 void stopServers() { |
186 for (var server in _serverList) { | 203 for (var server in _serverList) { |
187 server.close(); | 204 server.close(); |
188 } | 205 } |
189 } | 206 } |
190 | 207 |
191 void _onError(e) { | 208 void _onError(e) { |
192 DebugLogger.error('HttpServer: an error occured', e); | 209 DebugLogger.error('HttpServer: an error occured', e); |
193 } | 210 } |
194 | 211 |
195 Future _startHttpServer(String host, {int port: 0, int allowedPort: -1}) { | 212 Future _startHttpServer(String host, {int port: 0, int allowedPort: -1}) { |
196 return HttpServer.bind(host, port).then((HttpServer httpServer) { | 213 return HttpServer.bind(host, port).then((HttpServer httpServer) { |
197 var server = new DispatchingServer(httpServer, _onError, _sendNotFound); | 214 var server = new DispatchingServer(httpServer, _onError, _sendNotFound); |
198 server.addHandler('/echo', _handleEchoRequest); | 215 server.addHandler('/echo', _handleEchoRequest); |
199 server.addHandler('/ws', _handleWebSocketRequest); | 216 server.addHandler('/ws', _handleWebSocketRequest); |
200 fileHandler(request) { | 217 fileHandler(request) { |
201 _handleFileOrDirectoryRequest(request, allowedPort); | 218 _handleFileOrDirectoryRequest(request, allowedPort); |
202 } | 219 } |
203 server.addHandler('/$PREFIX_BUILDDIR', fileHandler); | 220 server.addHandler('/$PREFIX_BUILDDIR', fileHandler); |
204 server.addHandler('/$PREFIX_DARTDIR', fileHandler); | 221 server.addHandler('/$PREFIX_DARTDIR', fileHandler); |
205 server.addHandler('/packages', fileHandler); | 222 server.addHandler('/packages', fileHandler); |
206 _serverList.add(httpServer); | 223 _serverList.add(httpServer); |
207 return server; | 224 return server; |
208 }); | 225 }); |
209 } | 226 } |
210 | 227 |
211 void _handleFileOrDirectoryRequest(HttpRequest request, int allowedPort) { | 228 _handleFileOrDirectoryRequest(HttpRequest request, |
| 229 int allowedPort) async { |
212 // Enable browsers to cache file/directory responses. | 230 // Enable browsers to cache file/directory responses. |
213 var response = request.response; | 231 var response = request.response; |
214 response.headers | 232 response.headers |
215 .set("Cache-Control", "max-age=$_CACHE_EXPIRATION_IN_SECONDS"); | 233 .set("Cache-Control", "max-age=$_CACHE_EXPIRATION_IN_SECONDS"); |
216 var path = _getFilePathFromRequestPath(request.uri.path); | 234 var path = _getFileUriFromRequestUri(request.uri); |
217 if (path != null) { | 235 if (path != null) { |
218 var file = new File(path.toNativePath()); | 236 var file = new File.fromUri(path); |
219 file.exists().then((exists) { | 237 var directory = new Directory.fromUri(path); |
220 if (exists) { | 238 if (await file.exists()){ |
221 _sendFileContent(request, response, allowedPort, path, file); | 239 _sendFileContent(request, response, allowedPort, file); |
222 } else { | 240 } else if (await directory.exists()) { |
223 var directory = new Directory(path.toNativePath()); | 241 _sendDirectoryListing( |
224 directory.exists().then((exists) { | 242 await _listDirectory(directory), request, response); |
225 if (exists) { | 243 } else { |
226 _listDirectory(directory).then((entries) { | 244 _sendNotFound(request); |
227 _sendDirectoryListing(entries, request, response); | 245 } |
228 }); | |
229 } else { | |
230 _sendNotFound(request); | |
231 } | |
232 }); | |
233 } | |
234 }); | |
235 } else { | 246 } else { |
236 if (request.uri.path == '/') { | 247 if (request.uri.path == '/') { |
237 var entries = [ | 248 var entries = [ |
238 new _Entry('root_dart', 'root_dart/'), | 249 new _Entry('root_dart', 'root_dart/'), |
239 new _Entry('root_build', 'root_build/'), | 250 new _Entry('root_build', 'root_build/'), |
240 new _Entry('echo', 'echo') | 251 new _Entry('echo', 'echo') |
241 ]; | 252 ]; |
242 _sendDirectoryListing(entries, request, response); | 253 _sendDirectoryListing(entries, request, response); |
243 } else { | 254 } else { |
244 _sendNotFound(request); | 255 _sendNotFound(request); |
(...skipping 25 matching lines...) Expand all Loading... |
270 } | 281 } |
271 }, onError: (e) { | 282 }, onError: (e) { |
272 DebugLogger.warning('HttpServer: error while echoing to WebSocket', e); | 283 DebugLogger.warning('HttpServer: error while echoing to WebSocket', e); |
273 }); | 284 }); |
274 }).catchError((e) { | 285 }).catchError((e) { |
275 DebugLogger.warning( | 286 DebugLogger.warning( |
276 'HttpServer: error while transforming to WebSocket', e); | 287 'HttpServer: error while transforming to WebSocket', e); |
277 }); | 288 }); |
278 } | 289 } |
279 | 290 |
280 Path _getFilePathFromRequestPath(String urlRequestPath) { | 291 Uri _getFileUriFromRequestUri(Uri request) { |
281 // Go to the top of the file to see an explanation of the URL path scheme. | 292 // Go to the top of the file to see an explanation of the URL path scheme. |
282 var requestPath = new Path(urlRequestPath.substring(1)).canonicalize(); | 293 List<String> pathSegments = request.normalizePath().pathSegments; |
283 var pathSegments = requestPath.segments(); | 294 if (pathSegments.length == 0) return null; |
284 if (pathSegments.length > 0) { | 295 int packagesIndex = pathSegments.indexOf('packages'); |
285 var basePath; | 296 if (packagesIndex != -1) { |
286 var relativePath; | 297 var packageUri = new Uri(scheme: 'package', |
287 if (pathSegments[0] == PREFIX_BUILDDIR) { | 298 pathSegments: pathSegments.skip(packagesIndex + 1)); |
288 basePath = _buildDirectory; | 299 return _resolver.resolveUri(packageUri); |
289 relativePath = new Path(pathSegments.skip(1).join('/')); | 300 } |
290 } else if (pathSegments[0] == PREFIX_DARTDIR) { | 301 if (pathSegments[0] == PREFIX_BUILDDIR) { |
291 basePath = _dartDirectory; | 302 return _buildDirectory.resolve(pathSegments.skip(1).join('/')); |
292 relativePath = new Path(pathSegments.skip(1).join('/')); | 303 } |
293 } | 304 if (pathSegments[0] == PREFIX_DARTDIR) { |
294 var packagesIndex = pathSegments.indexOf('packages'); | 305 return _dartDirectory.resolve(pathSegments.skip(1).join('/')); |
295 if (packagesIndex != -1) { | |
296 if (_packages != null) { | |
297 // TODO(27065): Package spec file not supported by http server yet | |
298 return null; | |
299 } | |
300 var start = packagesIndex + 1; | |
301 basePath = _packageRoot; | |
302 relativePath = new Path(pathSegments.skip(start).join('/')); | |
303 } | |
304 if (basePath != null && relativePath != null) { | |
305 return basePath.join(relativePath); | |
306 } | |
307 } | 306 } |
308 return null; | 307 return null; |
309 } | 308 } |
310 | 309 |
311 Future<List<_Entry>> _listDirectory(Directory directory) { | 310 Future<List<_Entry>> _listDirectory(Directory directory) { |
312 var completer = new Completer(); | 311 var completer = new Completer(); |
313 var entries = []; | 312 var entries = []; |
314 | 313 |
315 directory.list().listen((FileSystemEntity fse) { | 314 directory.list().listen((FileSystemEntity fse) { |
316 var filename = new Path(fse.path).filename; | 315 var segments = fse.uri.pathSegments; |
317 if (fse is File) { | 316 if (fse is File) { |
| 317 var filename = segments.last; |
318 entries.add(new _Entry(filename, filename)); | 318 entries.add(new _Entry(filename, filename)); |
319 } else if (fse is Directory) { | 319 } else if (fse is Directory) { |
320 entries.add(new _Entry(filename, '$filename/')); | 320 var dirname = segments[segments.length - 2]; |
| 321 entries.add(new _Entry(dirname, '$dirname/')); |
321 } | 322 } |
322 }, onDone: () { | 323 }, onDone: () { |
323 completer.complete(entries); | 324 completer.complete(entries); |
324 }); | 325 }); |
325 return completer.future; | 326 return completer.future; |
326 } | 327 } |
327 | 328 |
328 void _sendDirectoryListing( | 329 void _sendDirectoryListing( |
329 List<_Entry> entries, HttpRequest request, HttpResponse response) { | 330 List<_Entry> entries, HttpRequest request, HttpResponse response) { |
330 response.headers.set('Content-Type', 'text/html'); | 331 response.headers.set('Content-Type', 'text/html'); |
(...skipping 10 matching lines...) Expand all Loading... |
341 var footer = ''' | 342 var footer = ''' |
342 </ul> | 343 </ul> |
343 </code> | 344 </code> |
344 </body> | 345 </body> |
345 </html>'''; | 346 </html>'''; |
346 | 347 |
347 entries.sort(); | 348 entries.sort(); |
348 response.write(header); | 349 response.write(header); |
349 for (var entry in entries) { | 350 for (var entry in entries) { |
350 response.write( | 351 response.write( |
351 '<li><a href="${new Path(request.uri.path).append(entry.name)}">' | 352 '<li><a href="${request.uri}/${entry.name}">' |
352 '${entry.displayName}</a></li>'); | 353 '${entry.displayName}</a></li>'); |
353 } | 354 } |
354 response.write(footer); | 355 response.write(footer); |
355 response.close(); | 356 response.close(); |
356 response.done.catchError((e) { | 357 response.done.catchError((e) { |
357 DebugLogger.warning( | 358 DebugLogger.warning( |
358 'HttpServer: error while closing the response stream', e); | 359 'HttpServer: error while closing the response stream', e); |
359 }); | 360 }); |
360 } | 361 } |
361 | 362 |
362 void _sendFileContent(HttpRequest request, HttpResponse response, | 363 void _sendFileContent(HttpRequest request, HttpResponse response, |
363 int allowedPort, Path path, File file) { | 364 int allowedPort, File file) { |
364 if (allowedPort != -1) { | 365 if (allowedPort != -1) { |
365 var headerOrigin = request.headers.value('Origin'); | 366 var headerOrigin = request.headers.value('Origin'); |
366 var allowedOrigin; | 367 var allowedOrigin; |
367 if (headerOrigin != null) { | 368 if (headerOrigin != null) { |
368 var origin = Uri.parse(headerOrigin); | 369 var origin = Uri.parse(headerOrigin); |
369 // Allow loading from http://*:$allowedPort in browsers. | 370 // Allow loading from http://*:$allowedPort in browsers. |
370 allowedOrigin = '${origin.scheme}://${origin.host}:${allowedPort}'; | 371 allowedOrigin = '${origin.scheme}://${origin.host}:${allowedPort}'; |
371 } else { | 372 } else { |
372 // IE10 appears to be bugged and is not sending the Origin header | 373 // IE10 appears to be bugged and is not sending the Origin header |
373 // when making CORS requests to the same domain but different port. | 374 // when making CORS requests to the same domain but different port. |
(...skipping 15 matching lines...) Expand all Loading... |
389 for (var header in [ | 390 for (var header in [ |
390 "Content-Security-Policy", | 391 "Content-Security-Policy", |
391 "X-Content-Security-Policy" | 392 "X-Content-Security-Policy" |
392 ]) { | 393 ]) { |
393 response.headers.set(header, content_header_value); | 394 response.headers.set(header, content_header_value); |
394 } | 395 } |
395 if (const ["safari"].contains(runtime)) { | 396 if (const ["safari"].contains(runtime)) { |
396 response.headers.set("X-WebKit-CSP", content_header_value); | 397 response.headers.set("X-WebKit-CSP", content_header_value); |
397 } | 398 } |
398 } | 399 } |
399 if (path.filename.endsWith('.html')) { | 400 if (file.path.endsWith('.html')) { |
400 response.headers.set('Content-Type', 'text/html'); | 401 response.headers.set('Content-Type', 'text/html'); |
401 } else if (path.filename.endsWith('.js')) { | 402 } else if (file.path.endsWith('.js')) { |
402 response.headers.set('Content-Type', 'application/javascript'); | 403 response.headers.set('Content-Type', 'application/javascript'); |
403 } else if (path.filename.endsWith('.dart')) { | 404 } else if (file.path.endsWith('.dart')) { |
404 response.headers.set('Content-Type', 'application/dart'); | 405 response.headers.set('Content-Type', 'application/dart'); |
405 } else if (path.filename.endsWith('.css')) { | 406 } else if (file.path.endsWith('.css')) { |
406 response.headers.set('Content-Type', 'text/css'); | 407 response.headers.set('Content-Type', 'text/css'); |
407 } else if (path.filename.endsWith('.xml')) { | 408 } else if (file.path.endsWith('.xml')) { |
408 response.headers.set('Content-Type', 'text/xml'); | 409 response.headers.set('Content-Type', 'text/xml'); |
409 } | 410 } |
410 response.headers.removeAll("X-Frame-Options"); | 411 response.headers.removeAll("X-Frame-Options"); |
411 file.openRead().pipe(response).catchError((e) { | 412 file.openRead().pipe(response).catchError((e) { |
412 DebugLogger.warning( | 413 DebugLogger.warning( |
413 'HttpServer: error while closing the response stream', e); | 414 'HttpServer: error while closing the response stream', e); |
414 }); | 415 }); |
415 } | 416 } |
416 | 417 |
417 void _sendNotFound(HttpRequest request) { | 418 void _sendNotFound(HttpRequest request) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 class _Entry implements Comparable { | 459 class _Entry implements Comparable { |
459 final String name; | 460 final String name; |
460 final String displayName; | 461 final String displayName; |
461 | 462 |
462 _Entry(this.name, this.displayName); | 463 _Entry(this.name, this.displayName); |
463 | 464 |
464 int compareTo(_Entry other) { | 465 int compareTo(_Entry other) { |
465 return name.compareTo(other.name); | 466 return name.compareTo(other.name); |
466 } | 467 } |
467 } | 468 } |
OLD | NEW |