I have a simple Express server that is serving up some static files. Here is the server:
var express = require('express');
var app = express.createServer();
// Configuration
app.configure(function() {
app.use(express.bodyParser());
app.use(express.staticCache());
app.use(express.static(__dirname + '/public'));
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
// 404
app.get('*', function(req, res) {
res.send('not found', 404);
});
app.listen(3000);
In my public directory I have a file called index.html. Firing up node app.js and then browsing to localhost:3000/index.html shows the static file as expected. Navigating to localhost:3000/ind or localhost:3000/ind\ shows the 404 page as expected.
However, navigating to localhost:3000/index.html\ (note the trailing backslash) crashes my node server with:
stream.js:105
throw er; // Unhandled stream error in pipe.
^
Error: ENOENT, no such file or directory '/home/bill/projects/app/public/index.html\'
Why is the node server crashing instead of just serving up the 404 page? I thought since the file does not exist, the static middleware would just skip it and pass the request on to the routes. I got around it by creating a custom middleware that returns 404 if a trailing backslash exists in the request URL, but I’d like to figure out if I’m missing something here. Thanks!
The reason for this behavior seems to be the difference in how
fs.statandfs.createReadStreamhandle trailing backslashes.When the string
'path/to/public/index.html\\'is given tofs.statin the static middleware, it is ignored (runningstat index.html\on the command line checks for a file namedindex.html, you’d have to runstat index.html\\forindex.html\). Sofs.statthinks the file was found because it thinks you’re asking forindex.html, and doesn’t call the next middleware handler.Later, that string is passed to
fs.createReadStreamwhich thinks it’s looking forindex.html\. It doesn’t find that file and throws said error.Since the functions treat the backslash differently, you can’t really do anything but use some middleware to filter out those requests.