Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: pkg/http_server/lib/src/virtual_directory.dart

Issue 119453005: Make VirtualDirectory redirect if the directory-path does not end with a tailing slash. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/http_server/test/utils.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
8 // Used for signal a directory redirecting, where a tailing slash is missing.
9 class _DirectoryRedirect {
10 const _DirectoryRedirect();
11 }
12
7 /** 13 /**
8 * A [VirtualDirectory] can serve files and directory-listing from a root path, 14 * A [VirtualDirectory] can serve files and directory-listing from a root path,
9 * to [HttpRequest]s. 15 * to [HttpRequest]s.
10 * 16 *
11 * The [VirtualDirectory] providing secure handling of request uris and 17 * The [VirtualDirectory] providing secure handling of request uris and
12 * file-system links, correct mime-types and custom error pages. 18 * file-system links, correct mime-types and custom error pages.
13 */ 19 */
14 class VirtualDirectory { 20 class VirtualDirectory {
15 final String root; 21 final String root;
16 22
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 void serveRequest(HttpRequest request) { 65 void serveRequest(HttpRequest request) {
60 _locateResource('.', request.uri.pathSegments.iterator..moveNext()) 66 _locateResource('.', request.uri.pathSegments.iterator..moveNext())
61 .then((entity) { 67 .then((entity) {
62 if (entity == null) { 68 if (entity == null) {
63 _serveErrorPage(HttpStatus.NOT_FOUND, request); 69 _serveErrorPage(HttpStatus.NOT_FOUND, request);
64 return; 70 return;
65 } 71 }
66 if (entity is File) { 72 if (entity is File) {
67 serveFile(entity, request); 73 serveFile(entity, request);
68 } else if (entity is Directory) { 74 } else if (entity is Directory) {
69 _serveDirectory(entity, request); 75 if (allowDirectoryListing) {
76 _serveDirectory(entity, request);
77 } else {
78 _serveErrorPage(HttpStatus.NOT_FOUND, request);
79 }
80 } else if (entity is _DirectoryRedirect) {
81 request.response.redirect(Uri.parse('${request.uri}/'),
Søren Gjesse 2014/01/06 13:18:08 According to RFC 2616 section 14.30 the redirect l
Anders Johnsen 2014/01/09 09:32:25 Done.
82 status: HttpStatus.MOVED_PERMANENTLY);
70 } else { 83 } else {
71 _serveErrorPage(HttpStatus.NOT_FOUND, request); 84 _serveErrorPage(HttpStatus.NOT_FOUND, request);
72 } 85 }
73 }); 86 });
74 } 87 }
75 88
76 /** 89 /**
77 * Set the [callback] to override the default directory listing. The 90 * Set the [callback] to override the default directory listing. The
78 * [callback] will be called with the [Directory] to be listed and the 91 * [callback] will be called with the [Directory] to be listed and the
79 * [HttpRequest]. 92 * [HttpRequest].
80 */ 93 */
81 void set directoryHandler(void callback(Directory dir, HttpRequest request)) { 94 void set directoryHandler(void callback(Directory dir, HttpRequest request)) {
82 _dirCallback = callback; 95 _dirCallback = callback;
83 } 96 }
84 97
85 /** 98 /**
86 * Set the [callback] to override the error page handler. When [callback] is 99 * Set the [callback] to override the error page handler. When [callback] is
87 * invoked, the `statusCode` property of the response is set. 100 * invoked, the `statusCode` property of the response is set.
88 */ 101 */
89 void set errorPageHandler(void callback(HttpRequest request)) { 102 void set errorPageHandler(void callback(HttpRequest request)) {
90 _errorCallback = callback; 103 _errorCallback = callback;
91 } 104 }
92 105
93 Future<FileSystemEntity> _locateResource(String path, 106 Future _locateResource(String path, Iterator<String> segments) {
94 Iterator<String> segments) {
95 // Don't allow navigating up paths. 107 // Don't allow navigating up paths.
96 if (segments.current == "..") return new Future.value(null); 108 if (segments.current == "..") return new Future.value(null);
97 path = normalize(path); 109 path = normalize(path);
98 // If we jail to root, the relative path can never go up. 110 // If we jail to root, the relative path can never go up.
99 if (jailRoot && split(path).first == "..") return new Future.value(null); 111 if (jailRoot && split(path).first == "..") return new Future.value(null);
100 String fullPath({bool endSlash: false}) { 112 String fullPath() => join(root, path);
101 var p = join(root, path);
102 if (endSlash && path != ".") p = "$p$separator";
103 return p;
104 }
105 return FileSystemEntity.type(fullPath(), followLinks: false) 113 return FileSystemEntity.type(fullPath(), followLinks: false)
106 .then((type) { 114 .then((type) {
107 switch (type) { 115 switch (type) {
108 case FileSystemEntityType.FILE: 116 case FileSystemEntityType.FILE:
109 if (segments.current == null) { 117 if (segments.current == null) {
110 return new File(fullPath()); 118 return new File(fullPath());
111 } 119 }
112 break; 120 break;
113 121
114 case FileSystemEntityType.DIRECTORY: 122 case FileSystemEntityType.DIRECTORY:
115 if (segments.current == null) { 123 String dirFullPath() => '${fullPath()}$separator';
116 if (allowDirectoryListing) { 124 var current = segments.current;
117 return new Directory(fullPath(endSlash: true)); 125 if (current == null) {
118 } 126 if (path == '.') return new Directory(dirFullPath());
127 return const _DirectoryRedirect();
128 }
129 bool hasNext = segments.moveNext();
130 if (!hasNext && current == "") {
131 return new Directory(dirFullPath());
119 } else { 132 } else {
120 if (_invalidPathRegExp.hasMatch(segments.current)) break; 133 if (_invalidPathRegExp.hasMatch(current)) break;
121 return _locateResource(join(path, segments.current), 134 return _locateResource(join(path, current), segments);
122 segments..moveNext());
123 } 135 }
124 break; 136 break;
125 137
126 case FileSystemEntityType.LINK: 138 case FileSystemEntityType.LINK:
127 if (followLinks) { 139 if (followLinks) {
128 return new Link(fullPath()).target() 140 return new Link(fullPath()).target()
129 .then((target) { 141 .then((target) {
130 String targetPath = normalize(target); 142 String targetPath = normalize(target);
131 if (isAbsolute(targetPath)) { 143 if (isAbsolute(targetPath)) {
132 // If we jail to root, the path can never be absolute. 144 // If we jail to root, the path can never be absolute.
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 393
382 Future close() => new Future.value(); 394 Future close() => new Future.value();
383 395
384 void setMimeType(var bytes) { 396 void setMimeType(var bytes) {
385 var mimeType = lookupMimeType(path, headerBytes: bytes); 397 var mimeType = lookupMimeType(path, headerBytes: bytes);
386 if (mimeType != null) { 398 if (mimeType != null) {
387 response.headers.contentType = ContentType.parse(mimeType); 399 response.headers.contentType = ContentType.parse(mimeType);
388 } 400 }
389 } 401 }
390 } 402 }
OLDNEW
« no previous file with comments | « no previous file | pkg/http_server/test/utils.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698