node-http-server – Diff between revs 16 and 17
?pathlinks?
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; |