Chromium Code Reviews

Side by Side Diff: mojo/public/dart/third_party/shelf_static/lib/src/static_handler.dart

Issue 1346773002: Stop running pub get at gclient sync time and fix build bugs (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
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.
4
5 library shelf_static.static_handler;
6
7 import 'dart:io';
8
9 import 'package:http_parser/http_parser.dart';
10 import 'package:mime/mime.dart' as mime;
11 import 'package:path/path.dart' as p;
12 import 'package:shelf/shelf.dart';
13
14 import 'directory_listing.dart';
15 import 'util.dart';
16
17 // TODO option to exclude hidden files?
18
19 /// Creates a Shelf [Handler] that serves files from the provided
20 /// [fileSystemPath].
21 ///
22 /// Accessing a path containing symbolic links will succeed only if the resolved
23 /// path is within [fileSystemPath]. To allow access to paths outside of
24 /// [fileSystemPath], set [serveFilesOutsidePath] to `true`.
25 ///
26 /// When a existing directory is requested and a [defaultDocument] is specified
27 /// the directory is checked for a file with that name. If it exists, it is
28 /// served.
29 ///
30 /// If no [defaultDocument] is found and [listDirectories] is true, then the
31 /// handler produces a listing of the directory.
32 Handler createStaticHandler(String fileSystemPath,
33 {bool serveFilesOutsidePath: false, String defaultDocument,
34 bool listDirectories: false}) {
35 var rootDir = new Directory(fileSystemPath);
36 if (!rootDir.existsSync()) {
37 throw new ArgumentError('A directory corresponding to fileSystemPath '
38 '"$fileSystemPath" could not be found');
39 }
40
41 fileSystemPath = rootDir.resolveSymbolicLinksSync();
42
43 if (defaultDocument != null) {
44 if (defaultDocument != p.basename(defaultDocument)) {
45 throw new ArgumentError('defaultDocument must be a file name.');
46 }
47 }
48
49 return (Request request) {
50 var segs = [fileSystemPath]..addAll(request.url.pathSegments);
51
52 var fsPath = p.joinAll(segs);
53
54 var entityType = FileSystemEntity.typeSync(fsPath, followLinks: true);
55
56 File file = null;
57
58 if (entityType == FileSystemEntityType.FILE) {
59 file = new File(fsPath);
60 } else if (entityType == FileSystemEntityType.DIRECTORY) {
61 file = _tryDefaultFile(fsPath, defaultDocument);
62 if (file == null && listDirectories) {
63 var uri = request.requestedUri;
64 if (!uri.path.endsWith('/')) return _redirectToAddTrailingSlash(uri);
65 return listDirectory(fileSystemPath, fsPath);
66 }
67 }
68
69 if (file == null) {
70 return new Response.notFound('Not Found');
71 }
72
73 if (!serveFilesOutsidePath) {
74 var resolvedPath = file.resolveSymbolicLinksSync();
75
76 // Do not serve a file outside of the original fileSystemPath
77 if (!p.isWithin(fileSystemPath, resolvedPath)) {
78 return new Response.notFound('Not Found');
79 }
80 }
81
82 // when serving the default document for a directory, if the requested
83 // path doesn't end with '/', redirect to the path with a trailing '/'
84 var uri = request.requestedUri;
85 if (entityType == FileSystemEntityType.DIRECTORY &&
86 !uri.path.endsWith('/')) {
87 return _redirectToAddTrailingSlash(uri);
88 }
89
90 var fileStat = file.statSync();
91 var ifModifiedSince = request.ifModifiedSince;
92
93 if (ifModifiedSince != null) {
94 var fileChangeAtSecResolution = toSecondResolution(fileStat.changed);
95 if (!fileChangeAtSecResolution.isAfter(ifModifiedSince)) {
96 return new Response.notModified();
97 }
98 }
99
100 var headers = <String, String>{
101 HttpHeaders.CONTENT_LENGTH: fileStat.size.toString(),
102 HttpHeaders.LAST_MODIFIED: formatHttpDate(fileStat.changed)
103 };
104
105 var contentType = mime.lookupMimeType(file.path);
106 if (contentType != null) {
107 headers[HttpHeaders.CONTENT_TYPE] = contentType;
108 }
109
110 return new Response.ok(file.openRead(), headers: headers);
111 };
112 }
113
114 Response _redirectToAddTrailingSlash(Uri uri) {
115 var location = new Uri(
116 scheme: uri.scheme,
117 userInfo: uri.userInfo,
118 host: uri.host,
119 port: uri.port,
120 path: uri.path + '/',
121 query: uri.query);
122
123 return new Response.movedPermanently(location.toString());
124 }
125
126 File _tryDefaultFile(String dirPath, String defaultFile) {
127 if (defaultFile == null) return null;
128
129 var filePath = p.join(dirPath, defaultFile);
130
131 var file = new File(filePath);
132
133 if (file.existsSync()) {
134 return file;
135 }
136
137 return null;
138 }
OLDNEW

Powered by Google App Engine