Problem with running order of endpoints in Express with conflicting paths

Asked

Viewed 43 times

2

I have this question about endpoints express bred.

In this first section, the endpoint /anuncios/:search must search in the fields descricao and nome by the text reported. Therefore, a call /anuncios/carro will return all results with carro in the name or description.

app.get('/anuncios/:search', function (req, res) {
    let search = req.params.search;
  
    if (!search) {
        return res.status(400).send({message: 'Nada encontrado para ' +search });
    }
    else
    {  
        search = '%' +search.replace(' ', '%') +'%';

        dbConn.query(
            'SELECT * FROM anuncios where (descricao LIKE ?) '
            +'OR (nome LIKE ?)', 
                [search, search], function(err, result){
                res.send(result)
        });
    }  
});

Already this second endpoint, it must search for the informed ID. This way, when giving a GET /anuncios/id/2, the API returns the ID 2 ad.

app.get('/anuncios/id/:id', function (req, res) {
    let id = req.params.id;
  
    if (!id) {
        return res.status(400).send({message: 'Nenhum ID informado'});
    }
    else
    {  
        dbConn.query(
            'SELECT * FROM anuncios where id = ?', [id], 
            function(err, result){
                res.send(result)                
            }
        );
    }  
});  

My problem is when I make a call with an empty ID (GET /anuncios/id/). In this case, the API is doing a query in the first endpoint, searching for names and descriptions with the ID provided in the text.

How should I make that call without this problem?

1 answer

3


This is not a bug. It is working as the code "sent". Remember that code is nothing more than a series of instructions to a computer.

The point is that Express runs the handlers of each route according to the order in which they were defined. Thus, Handler that comes first in the code will be executed first. See the Express routing documentation to learn more.

When you put the Handler of /anuncios/:search, Express will have "registered" first. So when you ask the server for /anuncios/id/ ("Empty ID"), it will find that the ID is a valid term for searching.

To get around this, just reverse the order of the handlers, in order to also make the presence of the ID parameter optional (for this we use the question mark):

//           Campo ID é agora opcional
//                       ↓
app.get('/anuncios/id/:id?', function (req, res) {
  const id = req.params.id;

  // Não esqueça de tratar o caso do ID não ter sido informado:
  if (!id) {
    res.status(400).send('Erro. Você deve informar um ID.');
    return;
  }

  res.send(`Procurado pelo ID: "${id}".`);
});

app.get('/anuncios/:search', function (req, res) {
  const search = req.params.search;

  res.send(`Procurado pelo termo: "${search}".`);
});

The only problem with this approach is that you will now not be able to search for entities from the term ID, since it is "reserved".

To get around this (possible) problem, you can also create two endpoints a little more distinct. Something like:

  • /anuncios/id/:id, who would search for the ID.
  • /anucios/termo/:termo, who would search for some search term.
  • 1

    Thanks, Luiz! It was very clear the idea now!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.