2

I would like to understand how the Express middleware works under certain conditions. If the following two paths (identically named) are defined together:

app.get('/test', function(req, res){
    res.send ('A response...');
});

app.get('/test', function(req, res){
    res.send ('Another response...');
});

a call to /test will only return "A response..." and not the text of the second response. I originally understood that the body will be regarded as a middleware functions and be executed in sequence. Is it correct that the second definition does not get loaded at all, because there is already a definition for /test?

Alternatively, is there a way to remove the first definition while listening, and to add the second definition afterwards - without restarting the node session?

Matthys
  • 21
  • 2
  • The first route matched is executed, the other is ignored Check the answer here: https://stackoverflow.com/questions/32603818/order-of-router-precedence-in-express-js "Alternatively, is there a way to remove the first definition while listening, and to add the " not that I know – fedeteka Aug 12 '20 at 14:27

1 Answers1

3

First of all, Let me clear you the scenario that happens.

Route handlers for all endpoints are stored in one global array. Express.js recursively iterates through and invokes all handlers until it finds the right route handler.

A global array is not the ideal data structure for this use case. It’s unclear why Express.js chose not to use a constant time data structure like a map to store its handlers. Each request requires an expensive O(n) look up in the route array in order to find its route handler

Express.js even allows you to set many identical route handlers for a route. You can unwittingly set a request chain like so.

[a, b, c, c, c, c, d, e, f, g, h]

Requests for route c would terminate at the first occurrence of the c handler (position 2 in the array). However, requests for d would only terminate at position 6 in the array, having needless spent time spinning through a, b and multiple instances of c. Thus leading to the increase of latencies as each handler is invoked.

It would have been nice for Express.js to throw an error whenever there’s more than one route handler chain for a route. At this point the leading hypothesis is that the handler array increases in size with time, thus leading to the increase of latencies as each handler is invoked. Most likely there is leak of handlers somewhere in our code, possibly due to the duplicate handler issue.

Using similar routes can affect the global performance of the server.

Now, If you mean to achieve different purpose with your same route you can define params in one of your route and remove the other, like this :-

app.get('/test/:type', function(req, res){
    if(req.params['type'] == 'A')
    res.send ('A response...');
    else
    res.send ('Another response...');
});

Example Call made from frontend :-

{{yourAPIServer}}/test/A
Response should be: A response...

Same behavior can also be achieved using query parameters.

app.get('/test', function(req, res){
    if(req.query['type'] == 'A')
    res.send ('A response...');
    else
    res.send ('Another response...');
});

Example Call made from frontend :-

{{yourAPIServer}}/test?type=B
Response should be: Another response...

I have tried to make you understand most of the things possible.

d1fficult
  • 931
  • 8
  • 18
  • Thanks Abhijeet for the good information. You said "Route handlers for all endpoints are stored in one global array." Do you know the name of this global array? – Matthys Aug 13 '20 at 16:11
  • Wait! Go check this blog out, it will give you more insights by showing some of the internal express code which uses things like layers object for each route. https://www.sohamkamani.com/blog/2018/05/30/understanding-how-expressjs-works – d1fficult Aug 13 '20 at 17:23