Node crash using express and static middleware when URL contains a trailing backslash
Problem
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!
Solution
The reason for this behavior seems to be the difference in how fs.stat
and fs.createReadStream
handle trailing backslashes.
When the string 'path/to/public/index.html\\'
is given to fs.stat
in the static middleware, it is ignored (running stat index.html\
on the command line checks for a file named index.html
, you'd have to run stat index.html\\
for index.html\
). So fs.stat
thinks the file was found because it thinks you're asking for index.html
, and doesn't call the next middleware handler.
Later, that string is passed to fs.createReadStream
which thinks it's looking for index.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.
Discussion
View additional discussion.