Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forward request to alternate request handler instead of redirect

I'm using Node.js with express and already know the existence of response.redirect().

However, I'm looking for more of a forward() functionality similar to java that takes the same parameters as redirect, but internally forwards the request instead of having the client perform the redirect.

To clarify, I am not doing a proxy to a different server. I'd like to forward('/other/path') directly within the same app instance

It wasn't apparently obvious how to do this from the express documentation. Any help?

like image 267
user1328174 Avatar asked Aug 08 '13 21:08

user1328174


4 Answers

You just need to invoke the corresponding route handler function.

Option 1: route multiple paths to the same handler function

function getDogs(req, res, next) {
  //...
}}
app.get('/dogs', getDogs);
app.get('/canines', getDogs);

Option 2: Invoke a separate handler function manually/conditionally

app.get('/canines', function (req, res, next) {
   if (something) {
      //process one way
   } else {
      //do a manual "forward"
      getDogs(req, res, next);
   }
});

Option 3: call next('route')

If you carefully order your router patterns, you can call next('route'), which may achieve what you want. It basically says to express 'keep moving on down the router pattern list', instead of a call to next(), which says to express 'move down the middleware list (past the router)`.

like image 184
Peter Lyons Avatar answered Oct 30 '22 21:10

Peter Lyons


You can implement forward (aka rewrite) functionality by changing request url property and calling next('route').

Note that the handler performing forward needs to be configured before other routes which you perform forwards to.

This is example of forwarding all *.html documents to routes without .html extension (suffix).

function forwards(req, res, next) {
    if (/(?:.+?)\.html$/.test(req.url)) {
        req.url = req.url.replace(/\.html$/, '');
    }
    next('route');
}

You call next('route') as the last operation. The next('route') passes control to subsequent routes.

As mentioned above, you need to configure forwards handler as one of the first handlers.

app.get('*', forwards);
// ...
app.get('/someroute', handler);

The above example will return the same content for /someroute as well as /someroute.html. You could also provide an object with a set of forward rules ({ '/path1': '/newpath1', '/path2': '/newpath2' }) and use them in forward mechanism.

Note that regular expression used in forwards function is simplified for mechanism presentation purposes. You would need to extend it (or perform check on req.path) if you would like to use querystring parameters etc.

I hope that will help.

like image 21
Tom Avatar answered Oct 30 '22 20:10

Tom


For Express 4+

Using the next function does not work if the next handler is not added in the right order. Instead of using next, I use the router to register the handlers and call

app.get("/a/path", function(req, res){
    req.url = "/another/path";
    app.handle(req, res);
}

Or for HTML5 mode of React/Angular

const dir = process.env.DIR || './build';

// Configure http server
let app = express();
app.use('/', express.static(dir));

// This route sends a 404 when looking for a missing file (ie a URL with a dot in it)
app.all('/*\.*', function (req, res) {
    res.status(404).send('404 Not found');
});

// This route deals enables HTML5Mode by forwarding "missing" links to the index.html
app.all('/**', function (req, res) {
    req.url = 'index.html';
    app.handle(req, res);
});
like image 15
Loren Avatar answered Oct 30 '22 22:10

Loren


Using the next function does not work if the next handler is not added in the right order. Instead of using next, I use the router to register the handlers and call

router.get("/a/path", function(req, res){
    req.url = "/another/path";
    router.handle(req, res);
}
like image 11
Quoc Quach Avatar answered Oct 30 '22 21:10

Quoc Quach