Gleb Gleb - 1 month ago 18
Javascript Question

Express JS router sometimes returns 404 and sometimes 200

I use angular 2 and express js. So for all requests which is not css, images, js, video I send index.html file. My router code:

router.get(/\/(?!((.*\.html$)|(.*\.css$)|(.*\.mp4)|(.*\.woff)|(.*\.js$)|(.*\.map$)|(.*\.jpg$)|(.*\.jpeg$)|(.*\.png$)|(.*\.gif$))).+$/gmi,
ensureConnect.ensureLoggedIn({ redirectTo: '/' }),
function(req, res) {
res
.set('Content-Type', 'text/html')
.sendFile(../dist/index.html);
});


For root router '/' it works perfect, but if I try open another page (e.g. '/product/am-0596157134') it sometimes open page, but sometimes returns 404 (Cannot GET /product/am-0596157134)

So I tried to reload page twice and for the 1st reload it returns 404 and for the 2nd one - it returns 200. Here is log:


::ffff:127.0.0.1 - - [10/Nov/2016:11:46:24 +0000] "GET /product/am-0596157134 HTTP/1.1" 404 34 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36"

::ffff:127.0.0.1 - - [10/Nov/2016:11:46:25 +0000] "GET /product/am-0596157134 HTTP/1.1" 200 2299 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36"


Any ideas why it happens, and how to fix it?

Answer

TL;DR: remove the g flag from the regular expression.

When you use /g, the regular expression keeps an internal state (stored in the lastIndex property) to be able to find successive matches.

In your case, this state is maintained between requests, so for the first request a match is performed, the last index gets updated, and when a new request comes in, matching starts from that last index. When it doesn't match (and it probably won't), the state it reset and a new request will match again.