Hung Ho
Hung Ho

Reputation: 31

Express.js routing with optional param?

I have two situations to get data from DB

  1. To show normal data

    http://exampleapp.com/task/{{taskId}}
    
  2. To edit data via posting

    http://exampleapp.com/task/{{taskId}}/?state={{app.state}}
    

Both url have the same http://exampleapp.com/task/{{taskId}} just a little bit different with last phrase ?state={{app.state}}

I use Express routing as followed:

app.get('/task/:taskId/(?state=:status(pending|cancel|confirmed|deleted))?', routes.task.show);

But I dont know why it does not work ?

For example error: Cannot GET /task/51d2c53f329b8e0000000001 when going to h**p://exampleapp.com/task/51d2c53f329b8e0000000001

Upvotes: 1

Views: 4981

Answers (3)

josh3736
josh3736

Reputation: 144912

Query strings cannot be defined in routes. You access query string parameters from req.query.

app.get('/task/:taskId', function(req, res) {
    if (req.query.state == 'pending') { ... }
});

However, if you're modifying a task, this is not the appropriate way to do it. GET requests SHOULD be idempotent: the request SHOULD NOT modify state. That's what POST requests are for.

app.get('/task/:taskId', function(req, res) {
    // show task info based on `req.params.taskId`
});

app.post('/task/:taskId', function(req, res) {
    // set task `req.params.taskId` to state `req.body.state`
});

You could either have a <form> that posts to the task, or make an ajax request:

$.post('/task/1', { state: 'pending' }, function() { ... });

Upvotes: 2

Nick Mitchinson
Nick Mitchinson

Reputation: 5480

Your problem is that query strings are not considered in routing. You will either have to redesign your urls (ie, include the state into the url itself, instead of the query string) or check the query string in your route handler function.

Upvotes: 0

gustavohenke
gustavohenke

Reputation: 41440

According to the Express API, you cannot mix RegExp routes with string routes.

You should do something like this (I'm assuming taskId is an integer):

app.get(/^\/task/([0-9]+)/(?state=:status(pending|cancel|confirmed|deleted))?, routes.task.show);

However, I don't see why you cannot only check if req.query.state is defined in your route. It's probably less error prone and easier:

app.get("/task/:taskId", function( req, res, next ) {
  if (req.query.state) {
    // Do things
  }

  next();
});

Upvotes: 1

Related Questions