ppalmeida
ppalmeida

Reputation: 2954

expressjs route: specific route is not recognized

folks.

I am doing just a very simple API (localhost development), and I am curious why the last route is never got by ExpressJS server.

Here are the routes:

var express = require('express');
var bodyParser = require('body-parser');
var router = express();

// (...) other variables defined here...

router.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', 'localhost');
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});

// Works great!
router.get('/', function(req, res) {
  res.render('index');
});

// Works great!
router.get('/api/states', function(req, res) {
  res.json(states);
});

// Works great!
router.get('/api/cities/:state', function(req, res, state) {
  res.json(cities);
});

// Never Works!!
router.get('/api/stores/:state/:city', function(req, res, state, city) {
  res.json('{"result": true}');
});

router.use(express.static(__dirname + '/../../www'));
router.set('views', __dirname + '/../../www');
router.engine('html', require('ejs').renderFile);
router.set('view engine', 'html');
router.listen(process.env.PORT || 9000);

From my app I call these URLs to the last route:

http://localhost/api/stores/sp/city_name

It is always 404.

I simply can not realise why this is 404. The last route, witch never worked, is basically a copy from the previous route (that works great).

Could someone point what I am doing wrong here?

ps: the last route should accept a third optional parameter. I also had tried this:

// Never Works!!
router.get('/api/stores/:state/:city/*?', function(req, res, state, city) {
  res.json('{"result": true}');
});

But, if I can not do it work with two defined parameters, it will not work with extra optional parameters, right?

Any advice is very appreciate.

Thank you.

Upvotes: 1

Views: 829

Answers (1)

undefined
undefined

Reputation: 2214

You have too many arguments in your handler--function handlers that take four arguments are reserved for error handling, i.e. only called when somewhere in the middleware chain next(error) was called, or a exception was caught. Read the docs for further info.

// Remove `state` and `city` arguments, access via `req.params.*`
router.get('/api/stores/:state/:city', function(req, res) {
  var state = req.params.state
  var city = req.params.city
  res.json('{"result": true}');
});

The reason you are not getting a 404 for the other handler is because you're accepting three arguments. So I should point out the state argument will not be what you expect, it will be a function to invoke the next middleware, commonly named next.

// NOPE! function (req, res, state)
router.get('/api/cities/:state', function(req, res) { 
   var state = req.params.state
   res.json(cities);
});

// Common middleware handler, third parameter is a function that when invoked will call the next middleware
router.get('/some/uri', function (req, res, next) {
   doSomethingAsync()
     .then(data => { 
        req.data = data 
        next()
      })
      .catch(err => next(err))
  })

Upvotes: 1

Related Questions