| 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 // Used for signal a directory redirecting, where a tailing slash is missing. | 8 // Used for signal a directory redirecting, where a tailing slash is missing. |
| 9 class _DirectoryRedirect { | 9 class _DirectoryRedirect { |
| 10 const _DirectoryRedirect(); | 10 const _DirectoryRedirect(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 * to other resources within the [root] directory. | 34 * to other resources within the [root] directory. |
| 35 */ | 35 */ |
| 36 bool followLinks = true; | 36 bool followLinks = true; |
| 37 | 37 |
| 38 /** | 38 /** |
| 39 * Set or get if the [VirtualDirectory] should jail the root. When the root is | 39 * Set or get if the [VirtualDirectory] should jail the root. When the root is |
| 40 * not jailed, links can be followed to outside the [root] directory. | 40 * not jailed, links can be followed to outside the [root] directory. |
| 41 */ | 41 */ |
| 42 bool jailRoot = true; | 42 bool jailRoot = true; |
| 43 | 43 |
| 44 final List<String> _pathPrefixSegments; |
| 45 |
| 46 |
| 44 final RegExp _invalidPathRegExp = new RegExp("[\\\/\x00]"); | 47 final RegExp _invalidPathRegExp = new RegExp("[\\\/\x00]"); |
| 45 | 48 |
| 46 _ErrorCallback _errorCallback; | 49 _ErrorCallback _errorCallback; |
| 47 _DirCallback _dirCallback; | 50 _DirCallback _dirCallback; |
| 48 | 51 |
| 52 static List<String> _parsePathPrefix(String pathPrefix) { |
| 53 if (pathPrefix == null) return <String>[]; |
| 54 return new Uri(path: pathPrefix).pathSegments |
| 55 .where((segment) => segment.isNotEmpty) |
| 56 .toList(); |
| 57 } |
| 58 |
| 49 /* | 59 /* |
| 50 * Create a new [VirtualDirectory] for serving static file content of | 60 * Create a new [VirtualDirectory] for serving static file content of |
| 51 * the path [root]. | 61 * the path [root]. |
| 52 * | 62 * |
| 53 * The [root] is not required to exist. If the [root] doesn't exist at time of | 63 * The [root] is not required to exist. If the [root] doesn't exist at time of |
| 54 * a request, a 404 is generated. | 64 * a request, a 404 response is generated. |
| 65 * |
| 66 * If [pathPrefix] is set, [pathPrefix] will indicate the expected path prefix |
| 67 * of incoming requests. When locating the resource on disk, the prefix will |
| 68 * be trimmed from the requests uri, before locating the actual resource. |
| 69 * If the requests uri doesn't start with [pathPrefix], a 404 response is |
| 70 * generated. |
| 55 */ | 71 */ |
| 56 VirtualDirectory(this.root); | 72 VirtualDirectory(this.root, {String pathPrefix}) |
| 73 : _pathPrefixSegments = _parsePathPrefix(pathPrefix); |
| 57 | 74 |
| 58 /** | 75 /** |
| 59 * Serve a [Stream] of [HttpRequest]s, in this [VirtualDirectory]. | 76 * Serve a [Stream] of [HttpRequest]s, in this [VirtualDirectory]. |
| 60 */ | 77 */ |
| 61 StreamSubscription<HttpRequest> serve(Stream<HttpRequest> requests) => | 78 StreamSubscription<HttpRequest> serve(Stream<HttpRequest> requests) => |
| 62 requests.listen(serveRequest); | 79 requests.listen(serveRequest); |
| 63 | 80 |
| 64 /** | 81 /** |
| 65 * Serve a single [HttpRequest], in this [VirtualDirectory]. | 82 * Serve a single [HttpRequest], in this [VirtualDirectory]. |
| 66 */ | 83 */ |
| 67 Future serveRequest(HttpRequest request) { | 84 Future serveRequest(HttpRequest request) { |
| 68 return _locateResource('.', request.uri.pathSegments.iterator..moveNext()) | 85 var iterator = request.uri.pathSegments.iterator; |
| 86 for (var segment in _pathPrefixSegments) { |
| 87 if (!iterator.moveNext() || iterator.current != segment) { |
| 88 _serveErrorPage(HttpStatus.NOT_FOUND, request); |
| 89 return request.response.done; |
| 90 } |
| 91 } |
| 92 return _locateResource('.', iterator..moveNext()) |
| 69 .then((entity) { | 93 .then((entity) { |
| 70 if (entity is File) { | 94 if (entity is File) { |
| 71 serveFile(entity, request); | 95 serveFile(entity, request); |
| 72 } else if (entity is Directory) { | 96 } else if (entity is Directory) { |
| 73 if (allowDirectoryListing) { | 97 if (allowDirectoryListing) { |
| 74 _serveDirectory(entity, request); | 98 _serveDirectory(entity, request); |
| 75 } else { | 99 } else { |
| 76 _serveErrorPage(HttpStatus.NOT_FOUND, request); | 100 _serveErrorPage(HttpStatus.NOT_FOUND, request); |
| 77 } | 101 } |
| 78 } else if (entity is _DirectoryRedirect) { | 102 } else if (entity is _DirectoryRedirect) { |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 | 444 |
| 421 Future close() => new Future.value(); | 445 Future close() => new Future.value(); |
| 422 | 446 |
| 423 void setMimeType(List<int> bytes) { | 447 void setMimeType(List<int> bytes) { |
| 424 var mimeType = lookupMimeType(path, headerBytes: bytes); | 448 var mimeType = lookupMimeType(path, headerBytes: bytes); |
| 425 if (mimeType != null) { | 449 if (mimeType != null) { |
| 426 response.headers.contentType = ContentType.parse(mimeType); | 450 response.headers.contentType = ContentType.parse(mimeType); |
| 427 } | 451 } |
| 428 } | 452 } |
| 429 } | 453 } |
| OLD | NEW |