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 part of http_server; | 5 part of http_server; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A [VirtualDirectory] can serve files and directory-listing from a root path, | 8 * A [VirtualDirectory] can serve files and directory-listing from a root path, |
| 9 * to [HttpRequest]s. | 9 * to [HttpRequest]s. |
| 10 * | 10 * |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 68 Function _errorCallback; | 68 Function _errorCallback; |
| 69 Function _dirCallback; | 69 Function _dirCallback; |
| 70 | 70 |
| 71 _VirtualDirectory(this.root); | 71 _VirtualDirectory(this.root); |
| 72 | 72 |
| 73 void serve(Stream<HttpRequest> requests) { | 73 void serve(Stream<HttpRequest> requests) { |
| 74 requests.listen(serveRequest); | 74 requests.listen(serveRequest); |
| 75 } | 75 } |
| 76 | 76 |
| 77 void serveRequest(HttpRequest request) { | 77 void serveRequest(HttpRequest request) { |
| 78 var path = new Path(request.uri.path).canonicalize(); | 78 _locateResource(new Path('.'), request.uri.pathSegments) |
| 79 | |
| 80 if (!path.isAbsolute) { | |
| 81 return _serveErrorPage(HttpStatus.NOT_FOUND, request); | |
| 82 } | |
| 83 | |
| 84 _locateResource(new Path('.'), path.segments()) | |
| 85 .then((entity) { | 79 .then((entity) { |
| 86 if (entity == null) { | 80 if (entity == null) { |
| 87 _serveErrorPage(HttpStatus.NOT_FOUND, request); | 81 _serveErrorPage(HttpStatus.NOT_FOUND, request); |
| 88 return; | 82 return; |
| 89 } | 83 } |
| 90 if (entity is File) { | 84 if (entity is File) { |
| 91 _serveFile(entity, request); | 85 _serveFile(entity, request); |
| 92 } else if (entity is Directory) { | 86 } else if (entity is Directory) { |
| 93 _serveDirectory(entity, request); | 87 _serveDirectory(entity, request); |
| 94 } else { | 88 } else { |
| 95 _serveErrorPage(HttpStatus.NOT_FOUND, request); | 89 _serveErrorPage(HttpStatus.NOT_FOUND, request); |
| 96 } | 90 } |
| 97 }); | 91 }); |
| 98 } | 92 } |
| 99 | 93 |
| 100 void setDirectoryHandler(void callback(Directory dir, HttpRequest request)) { | 94 void setDirectoryHandler(void callback(Directory dir, HttpRequest request)) { |
| 101 _dirCallback = callback; | 95 _dirCallback = callback; |
| 102 } | 96 } |
| 103 | 97 |
| 104 void setErrorPageHandler(void callback(HttpRequest request)) { | 98 void setErrorPageHandler(void callback(HttpRequest request)) { |
| 105 _errorCallback = callback; | 99 _errorCallback = callback; |
| 106 } | 100 } |
| 107 | 101 |
| 108 Future<FileSystemEntity> _locateResource(Path path, | 102 Future<FileSystemEntity> _locateResource(Path path, |
| 109 Iterable<String> segments) { | 103 Iterable<String> segments) { |
| 104 path = path.canonicalize(); | |
|
Lasse Reichstein Nielsen
2013/07/02 07:31:14
So you canonicalize after each segment is added.
W
Anders Johnsen
2013/07/02 11:08:07
Yes, that's the idea.
| |
| 105 if (path.segments().first == "..") return new Future.value(null); | |
| 110 Path fullPath() => new Path(root).join(path); | 106 Path fullPath() => new Path(root).join(path); |
| 111 return FileSystemEntity.type(fullPath().toNativePath(), followLinks: false) | 107 return FileSystemEntity.type(fullPath().toNativePath(), followLinks: false) |
| 112 .then((type) { | 108 .then((type) { |
| 113 switch (type) { | 109 switch (type) { |
| 114 case FileSystemEntityType.FILE: | 110 case FileSystemEntityType.FILE: |
| 115 if (segments.isEmpty) return new File.fromPath(fullPath()); | 111 if (segments.isEmpty) return new File.fromPath(fullPath()); |
| 116 break; | 112 break; |
| 117 | 113 |
| 118 case FileSystemEntityType.DIRECTORY: | 114 case FileSystemEntityType.DIRECTORY: |
| 119 if (segments.isEmpty) { | 115 if (segments.isEmpty) { |
| 120 if (allowDirectoryListing) { | 116 if (allowDirectoryListing) { |
| 121 return new Directory.fromPath(fullPath()); | 117 return new Directory.fromPath(fullPath()); |
| 122 } | 118 } |
| 123 } else { | 119 } else { |
| 124 return _locateResource(path.append(segments.first), | 120 return _locateResource(path.append(segments.first), |
| 125 segments.skip(1)); | 121 segments.skip(1)); |
|
Lasse Reichstein Nielsen
2013/07/02 07:31:14
Ick. That's no way to treat an iterable.
Consider
Anders Johnsen
2013/07/02 11:08:07
Done.
| |
| 126 } | 122 } |
| 127 break; | 123 break; |
| 128 | 124 |
| 129 case FileSystemEntityType.LINK: | 125 case FileSystemEntityType.LINK: |
| 130 if (followLinks) { | 126 if (followLinks) { |
| 131 return new Link.fromPath(fullPath()).target() | 127 return new Link.fromPath(fullPath()).target() |
| 132 .then((target) { | 128 .then((target) { |
| 133 var targetPath = new Path(target).canonicalize(); | 129 var targetPath = new Path(target).canonicalize(); |
| 134 if (targetPath.isAbsolute) return null; | 130 if (targetPath.isAbsolute) return null; |
| 135 targetPath = | 131 targetPath = path.directoryPath.join(targetPath); |
| 136 path.directoryPath.join(targetPath).canonicalize(); | 132 return _locateResource(targetPath, segments); |
| 137 if (targetPath.segments().isEmpty || | |
| 138 targetPath.segments().first == '..') return null; | |
| 139 if (segments.isEmpty) { | |
| 140 return _locateResource(targetPath, []); | |
| 141 } | |
| 142 return _locateResource(targetPath.append(segments.first), | |
| 143 segments.skip(1)); | |
| 144 }); | 133 }); |
| 145 } | 134 } |
| 146 break; | 135 break; |
| 147 } | 136 } |
| 148 // Return `null` on fall-through, to indicate NOT_FOUND. | 137 // Return `null` on fall-through, to indicate NOT_FOUND. |
| 149 return null; | 138 return null; |
| 150 }); | 139 }); |
| 151 } | 140 } |
| 152 | 141 |
| 153 void _serveFile(File file, HttpRequest request) { | 142 void _serveFile(File file, HttpRequest request) { |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 372 | 361 |
| 373 Future close() => new Future.value(); | 362 Future close() => new Future.value(); |
| 374 | 363 |
| 375 void setMimeType(var bytes) { | 364 void setMimeType(var bytes) { |
| 376 var mimeType = lookupMimeType(path, headerBytes: bytes); | 365 var mimeType = lookupMimeType(path, headerBytes: bytes); |
| 377 if (mimeType != null) { | 366 if (mimeType != null) { |
| 378 response.headers.contentType = ContentType.parse(mimeType); | 367 response.headers.contentType = ContentType.parse(mimeType); |
| 379 } | 368 } |
| 380 } | 369 } |
| 381 } | 370 } |
| OLD | NEW |