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

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: Using relative Uri for now. 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 // TODO(ajohnsen): Use HttpRequest.requestedUri once 1.2 is out.
82 request.response.redirect(Uri.parse('${request.uri}/'),
83 status: HttpStatus.MOVED_PERMANENTLY);
70 } else { 84 } else {
71 _serveErrorPage(HttpStatus.NOT_FOUND, request); 85 _serveErrorPage(HttpStatus.NOT_FOUND, request);
72 } 86 }
73 }); 87 });
74 } 88 }
75 89
76 /** 90 /**
77 * Set the [callback] to override the default directory listing. The 91 * Set the [callback] to override the default directory listing. The
78 * [callback] will be called with the [Directory] to be listed and the 92 * [callback] will be called with the [Directory] to be listed and the
79 * [HttpRequest]. 93 * [HttpRequest].
80 */ 94 */
81 void set directoryHandler(void callback(Directory dir, HttpRequest request)) { 95 void set directoryHandler(void callback(Directory dir, HttpRequest request)) {
82 _dirCallback = callback; 96 _dirCallback = callback;
83 } 97 }
84 98
85 /** 99 /**
86 * Set the [callback] to override the error page handler. When [callback] is 100 * Set the [callback] to override the error page handler. When [callback] is
87 * invoked, the `statusCode` property of the response is set. 101 * invoked, the `statusCode` property of the response is set.
88 */ 102 */
89 void set errorPageHandler(void callback(HttpRequest request)) { 103 void set errorPageHandler(void callback(HttpRequest request)) {
90 _errorCallback = callback; 104 _errorCallback = callback;
91 } 105 }
92 106
93 Future<FileSystemEntity> _locateResource(String path, 107 Future _locateResource(String path, Iterator<String> segments) {
94 Iterator<String> segments) {
95 // Don't allow navigating up paths. 108 // Don't allow navigating up paths.
96 if (segments.current == "..") return new Future.value(null); 109 if (segments.current == "..") return new Future.value(null);
97 path = normalize(path); 110 path = normalize(path);
98 // If we jail to root, the relative path can never go up. 111 // If we jail to root, the relative path can never go up.
99 if (jailRoot && split(path).first == "..") return new Future.value(null); 112 if (jailRoot && split(path).first == "..") return new Future.value(null);
100 String fullPath({bool endSlash: false}) { 113 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) 114 return FileSystemEntity.type(fullPath(), followLinks: false)
106 .then((type) { 115 .then((type) {
107 switch (type) { 116 switch (type) {
108 case FileSystemEntityType.FILE: 117 case FileSystemEntityType.FILE:
109 if (segments.current == null) { 118 if (segments.current == null) {
110 return new File(fullPath()); 119 return new File(fullPath());
111 } 120 }
112 break; 121 break;
113 122
114 case FileSystemEntityType.DIRECTORY: 123 case FileSystemEntityType.DIRECTORY:
115 if (segments.current == null) { 124 String dirFullPath() => '${fullPath()}$separator';
116 if (allowDirectoryListing) { 125 var current = segments.current;
117 return new Directory(fullPath(endSlash: true)); 126 if (current == null) {
118 } 127 if (path == '.') return new Directory(dirFullPath());
128 return const _DirectoryRedirect();
129 }
130 bool hasNext = segments.moveNext();
131 if (!hasNext && current == "") {
132 return new Directory(dirFullPath());
119 } else { 133 } else {
120 if (_invalidPathRegExp.hasMatch(segments.current)) break; 134 if (_invalidPathRegExp.hasMatch(current)) break;
121 return _locateResource(join(path, segments.current), 135 return _locateResource(join(path, current), segments);
122 segments..moveNext());
123 } 136 }
124 break; 137 break;
125 138
126 case FileSystemEntityType.LINK: 139 case FileSystemEntityType.LINK:
127 if (followLinks) { 140 if (followLinks) {
128 return new Link(fullPath()).target() 141 return new Link(fullPath()).target()
129 .then((target) { 142 .then((target) {
130 String targetPath = normalize(target); 143 String targetPath = normalize(target);
131 if (isAbsolute(targetPath)) { 144 if (isAbsolute(targetPath)) {
132 // If we jail to root, the path can never be absolute. 145 // If we jail to root, the path can never be absolute.
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 394
382 Future close() => new Future.value(); 395 Future close() => new Future.value();
383 396
384 void setMimeType(var bytes) { 397 void setMimeType(var bytes) {
385 var mimeType = lookupMimeType(path, headerBytes: bytes); 398 var mimeType = lookupMimeType(path, headerBytes: bytes);
386 if (mimeType != null) { 399 if (mimeType != null) {
387 response.headers.contentType = ContentType.parse(mimeType); 400 response.headers.contentType = ContentType.parse(mimeType);
388 } 401 }
389 } 402 }
390 } 403 }
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