node-http-server – Diff between revs 16 and 17

Subversion Repositories:
Rev:
Show entire fileIgnore whitespace
Rev 16 Rev 17
Line 19... Line 19...
19 rootPath.every((e, i) => e === userPath[i])); 19 rootPath.every((e, i) => e === userPath[i]));
20 }); 20 });
21 } 21 }
Line 22... Line 22...
22   22  
23 // Serves files. 23 // Serves files.
24 function files(config, request, response, resource, callback) { 24 function files(config, request, response, requestPath, callback) {
25 // Check if the file is accessible. 25 // Check if the file is accessible.
26 fs.access(resource, fs.constants.R_OK, (error) => { 26 fs.access(requestPath, fs.constants.R_OK, (error) => {
27 if (error) { 27 if (error) {
28 response.statusCode = 403; 28 response.statusCode = 403;
29 response.end(); 29 response.end();
30 return; 30 return;
Line 31... Line 31...
31 } 31 }
32   32  
33 response.setHeader( 33 response.setHeader(
34 'Content-Type', 34 'Content-Type',
Line 35... Line 35...
35 mime.lookup(resource) 35 mime.lookup(requestPath)
36 ); 36 );
37   37  
38 var readStream = fs.createReadStream(resource) 38 var readStream = fs.createReadStream(requestPath)
39 .on('open', () => { 39 .on('open', () => {
40 response.statusCode = 200; 40 response.statusCode = 200;
Line 47... Line 47...
47   47  
48 }); 48 });
Line 49... Line 49...
49 } 49 }
50   50  
51 // Serves a directory listing or the document index in case it exists. 51 // Serves a directory listing or the document index in case it exists.
52 function index(config, request, response, resource, root, callback) { 52 function index(config, request, response, requestPath, requestURL, callback) {
-   53 const root = path.resolve(requestPath, config.site.index);
53 const root = path.resolve(resource, config.site.index); 54 fs.stat(root, (error, stats) => {
-   55 if (error) {
54 fs.stat(root, (error, stats) => { 56 if(config.site.indexing
55 if (error && config.site.indexing 57 .some((directory) =>
56 .some((directory) => directory.toUpperCase() == resource.toUpperCase())) { 58 directory.toUpperCase() === requestURL.toUpperCase())) {
-   59 fs.readdir(requestPath, (error, paths) => {
-   60 if (error) {
-   61 process.nextTick(() => {
-   62 callback('Could not list directory: ' +
-   63 requestPath,
-   64 module.exports.error.level.ERROR
-   65 );
-   66 });
-   67 response.statusCode = 500;
-   68 response.end();
57 fs.readdir(resource, (error, paths) => { 69 return;
58 if (error) { 70 }
59 process.nextTick(() => { 71 process.nextTick(() => {
60 callback('Could not list directory: ' + 72 callback('Directory listing requested for: ' +
61 resource, 73 requestPath,
62 module.exports.error.level.ERROR 74 module.exports.error.level.INFO
63 ); 75 );
-   76 });
64 }); 77 response.statusCode = 200;
65 response.statusCode = 500; -  
66 response.end(); -  
67 return; -  
68 } -  
69 process.nextTick(() => { -  
70 callback('Directory listing requested for: ' + -  
71 resource, -  
72 module.exports.error.level.INFO 78 response.write(JSON.stringify(paths));
73 ); -  
74 }); -  
75 response.statusCode = 200; -  
76 response.write(JSON.stringify(paths)); -  
Line 77... Line 79...
77 response.end(); 79 response.end();
-   80 });
-   81  
78 }); 82 return;
Line 79... Line 83...
79   83 }
80 return; 84
81 } 85 }
82   86  
83 // Serve the document index. 87 // Serve the document index.
84 fs.access(resource, fs.constants.R_OK, (error) => { 88 fs.access(requestPath, fs.constants.R_OK, (error) => {
85 if (error) { 89 if (error) {
86 process.nextTick(() => { 90 process.nextTick(() => {
87 callback('The server was unable to access the filesystem path: ' + 91 callback('The server was unable to access the filesystem path: ' +
88 resource, 92 requestPath,
89 module.exports.error.level.WARN 93 module.exports.error.level.WARN
Line 112... Line 116...
112   116  
113 }); 117 });
114 }); 118 });
Line 115... Line 119...
115 } 119 }
116   120  
117 // Determines whether the requested resource is a directory or a file. 121 // Determines whether the requested filesystem request path is a directory or a file.
118 function serve(config, request, response, resource, callback) { 122 function serve(config, request, response, requestPath, requestURL, callback) {
119 fs.stat(resource, (error, stats) => { 123 fs.stat(requestPath, (error, stats) => {
120 // Document does not exist. 124 // Document does not exist.
121 if (error) { 125 if (error) {
122 response.statusCode = 404; 126 response.statusCode = 404;
123 response.end(); 127 response.end();
Line 124... Line 128...
124 return; 128 return;
125 } 129 }
126   130  
127 switch (stats.isDirectory()) { 131 switch (stats.isDirectory()) {
128 case true: // Directory is requested so provide directory indexes. 132 case true: // Directory is requested so provide directory indexes.
129 index(config, request, response, resource, callback); 133 index(config, request, response, requestPath, requestURL, callback);
130 break; 134 break;
131 default: // Browser requesting file. 135 default: // Browser requesting file.
132 files(config, request, response, resource, callback); 136 files(config, request, response, requestPath, callback);
133 break; 137 break;
Line 153... Line 157...
153 config.auth.digest 157 config.auth.digest
154 ) 158 )
155 }); 159 });
Line 156... Line 160...
156   160  
157 const requestAddress = request.socket.address(); 161 const requestAddress = request.socket.address();
158 const requestedURL = url.parse( 162 const requestURL = url.parse(
159 request.url, true 163 request.url, true
Line 160... Line 164...
160 ); 164 );
161   165  
162 const trimmedPath = requestedURL 166 const trimmedPath = requestURL
163 .pathname 167 .pathname
164 .split('/') 168 .split('/')
165 .filter(Boolean) 169 .filter(Boolean)
166 .join('/'); 170 .join('/');
167 const resource = trimmedPath === '/' ? 171 const requestPath = trimmedPath === '/' ?
Line 168... Line 172...
168 path.join(root, trimmedPath) : 172 path.join(root, trimmedPath) :
169 path.resolve(root, trimmedPath); 173 path.resolve(root, trimmedPath);
170   174  
171 isRooted(resource, root, path.sep, (rooted) => { 175 isRooted(requestPath, root, path.sep, (rooted) => {
172 if (!rooted) { 176 if (!rooted) {
173 process.nextTick(() => { 177 process.nextTick(() => {
174 callback('Attempted path traversal: ' + 178 callback('Attempted path traversal: ' +
175 requestAddress.address + ':' + 179 requestAddress.address + ':' +
176 requestAddress.port + 180 requestAddress.port +
177 ' requesting: ' + 181 ' requesting: ' +
178 requestedURL.pathname, 182 requestURL.pathname,
179 module.exports.error.level.WARN 183 module.exports.error.level.WARN
180 ); 184 );
181 }); 185 });
182 response.statusCode = 404; 186 response.statusCode = 404;
Line 183... Line 187...
183 response.end(); 187 response.end();
184 return; 188 return;
185 } 189 }
186   190  
187 // Check if the requested path requires authentication. 191 // Check if the requested path requires authentication.
188 switch (config.auth.locations.some( 192 switch (config.auth.locations.some(
189 (authPath) => authPath.toUpperCase() === requestedURL.pathname.toUpperCase())) { 193 (authPath) => authPath.toUpperCase() === requestURL.pathname.toUpperCase())) {
190 case true: 194 case true:
191 // Requested location requires authentication. 195 // Requested location requires authentication.
192 authentication.check(request, response, (request, response) => { 196 authentication.check(request, response, (request, response) => {
193 process.nextTick(() => { 197 process.nextTick(() => {
194 callback('Authenticated client: ' + 198 callback('Authenticated client: ' +
195 requestAddress.address + ':' + 199 requestAddress.address + ':' +
196 requestAddress.port + 200 requestAddress.port +
197 ' accessing: ' + 201 ' accessing: ' +
-   202 requestURL.pathname,
-   203 module.exports.error.level.INFO
-   204 );
-   205 });
198 requestedURL.pathname, 206 serve(config,
-   207 request,
-   208 response,
199 module.exports.error.level.INFO 209 requestPath,
200 ); 210 requestURL.pathname,
201 }); 211 callback
202 serve(config, request, response, resource, callback); 212 );
203 }); 213 });
204 break; 214 break;
205 default: 215 default:
206 process.nextTick(() => { 216 process.nextTick(() => {
207 callback('Client: ' + 217 callback('Client: ' +
208 requestAddress.address + ':' + 218 requestAddress.address + ':' +
209 requestAddress.port + 219 requestAddress.port +
210 ' accessing: ' + 220 ' accessing: ' +
-   221 requestURL.pathname,
-   222 module.exports.error.level.INFO
-   223 );
-   224 });
211 requestedURL.pathname, 225 serve(config,
-   226 request,
-   227 response,
212 module.exports.error.level.INFO 228 requestPath,
213 ); 229 requestURL.pathname,
214 }); 230 callback
215 serve(config, request, response, resource, callback); 231 );
216 break; 232 break;