31

I would like to rewrite my URLs on my ExpressJS website. I've used this plugin, https://github.com/joehewitt/express-rewrite, but it doesn't work...

However, I might have made a mistake...

My app.js file :

var express = require('express')
    , index = require('./routes/index.js')
    , admin = require('./routes/admin.js')
    , contact = require('./routes/contact.js')
    , posts = require('./routes/posts.js')
    , http = require('http')
    , path = require('path')
    , hash = require('./auth').hash
    , db = require('./models')
    , favicons = require('connect-favicons')
    , rewriter = require('express-rewrite');


var app = express();

app.configure(function () {
    app.set('port', process.env.PORT || 3000);
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');
    app.use(express.favicon(__dirname + '/public/images/FAVICON.ico'));
    app.use(favicons(__dirname + '/public/images/apple-touch-icon.png'));
    app.use(express.logger('dev'));
    app.use(express.bodyParser());
    app.use(express.static(path.join(__dirname, 'public')));
    app.use(express.cookieParser());
    app.use(express.cookieSession({
            secret: 'SECRET',
            cookie: { access: false }
        })
    );
    app.use(rewriter);
    app.use(app.router);
    app.use(function(req, res, next){
        res.render('404.jade', {
            title: "404 - Page Not Found",
            showFullNav: false,
            status: 404,
            url: req.url
        });
    });
});

app.configure('development', function () {
    app.use(express.errorHandler());
});

app.get('/', index.index);

app.get('/toto', rewriter.rewrite('/heytoto'));

db.sequelize.sync().complete(function(err) {
    if (err) {
        throw err
    } else {
        http.createServer(app).listen(app.get('port'), function(){
            console.log('Express server listening on port ' + app.get('port'))
        })
    }
});

My error message :

Express
500 TypeError: Object function app(req, res){ app.handle(req, res); } has no method 'match'
at Object.rewriter [as handle] (/Users/anthonycluse/Sites/Anthony-Cluse-Express/node_modules/express-rewrite/rewrite.js:3:26)
at next (/Users/anthonycluse/Sites/Anthony-Cluse-Express/node_modules/express/node_modules/connect/lib/proto.js:199:15)
at Object.cookieSession [as handle] (/Users/anthonycluse/Sites/Anthony-Cluse-Express/node_modules/express/node_modules/connect/lib/middleware/cookieSession.js:113:5)
at next (/Users/anthonycluse/Sites/Anthony-Cluse-Express/node_modules/express/node_modules/connect/lib/proto.js:199:15)
at Object.cookieParser [as handle] (/Users/anthonycluse/Sites/Anthony-Cluse-Express/node_modules/express/node_modules/connect/lib/middleware/cookieParser.js:60:5)
at next (/Users/anthonycluse/Sites/Anthony-Cluse-Express/node_modules/express/node_modules/connect/lib/proto.js:199:15)
at resume (/Users/anthonycluse/Sites/Anthony-Cluse-Express/node_modules/express/node_modules/connect/lib/middleware/static.js:60:7)
at SendStream.error (/Users/anthonycluse/Sites/Anthony-Cluse-Express/node_modules/express/node_modules/connect/lib/middleware/static.js:73:37)
at SendStream.EventEmitter.emit (events.js:126:20)
at SendStream.error (/Users/anthonycluse/Sites/Anthony-Cluse-Express/node_modules/express/node_modules/send/lib/send.js:147:51)
tonymx227
  • 5,293
  • 16
  • 48
  • 91

6 Answers6

45

You could rewrite the URL before you get to the handler you want to use.

app.use(function(req, res, next) {
   if (req.url === '/toto') {
     req.url = '/heytoto';
   }
   next();
});

app.get('/heytoto', ...);

I've used a similar method to do URL rewrites with regular expressions.

Bryan
  • 1,613
  • 16
  • 18
42

So I had sort of the same issue. I wrote an app that uses the history API on browsers and I wanted to rewrite all non-static URLs back to index.html. So for static files I did:

app.configure(function() {
  app.use('/', express.static(__dirname + '/'));
});

But then for the history API generated paths I did:

app.get('*', function(request, response, next) {
  response.sendfile(__dirname + '/index.html');
});

This meant that any request that wasn't a file or directory in / (such as a URL generated by the history API) wouldn't be rewritten or redirected but instead the index.html file will be served and that then does all the JS routing magic.

Hopefully that's close to what you're looking for?

Ahmed Nuaman
  • 12,662
  • 15
  • 55
  • 87
  • I can't get it work, can help me? http://stackoverflow.com/questions/27971489/refresh-specific-page-with-angular-express-and-jade-using-html5mode?noredirect=1#comment44494193_27971489 – Leandro Hoffmann Jan 21 '15 at 12:28
  • what I can do if I need rewrite using regexp ? http://stackoverflow.com/questions/38117026/expressjs-rewrite-regex – bodley Jun 30 '16 at 08:41
  • 1
    but due this if hit simple http request that returns json ..... at this time index.html will also be called .so this is not nice solution. – vijay Feb 28 '17 at 10:25
6

A solution that works without response.sendfile(..) is to use a rewrite middleware that is inserted prior to app.use(express.static(..)) like this:

// forward all requests to /s/* to /index.html

app.use(function(req, res, next) {

  if (/\/s\/[^\/]+/.test(req.url)) {
    req.url = '/index.html';
  }

  next();
});

// insert express.static(...)

This way, expressjs properly recognizes the rewrite. The static middleware will then take care of serving the file.

nre
  • 1,299
  • 11
  • 24
1

1) Your rewrite middleware must appear before the middleware/function that will handle the request.

Won't work:

app.use('/hello', () => sayHello() );
app.use(() => rewriteURLToHello()); //it's too late to try to rewrite a URL to /hello

Will work:

app.use(() => rewriteURLToHello()); //we can rewrite a URL to /hello
app.use('/hello', () => sayHello() ); //rewritten URL will be handled here

2) Your middleware must not be bound to the path you're trying to rewrite

Won't work:

app.use('/hello', (req, res, next) => {
  //'/hello' has been trimmed from req.url
  //req.url is / if the request was for /hello
  req.url = '/goodbye'; //technically setting full path to /hello/goodbye
  next(); //will only call other middleware in the /hello chain
});
app.use('/goodbye', () => sayBye()); //won't work

Will work:

app.use((req, res, next) => {    //runs for every path. Same as .use('/',
  //'/hello' has NOT been trimmed from req.url
  //req.url is /hello if the request was for /hello
  if (req.url.startsWith('/hello')) { 
    req.url = '/goodbye'; //full path now /goodbye
  }
  next(); //will continue calling all middleware
});
app.use('/goodbye', () => sayBye()); //will work
Codebling
  • 10,764
  • 2
  • 38
  • 66
0

you could check the url with an if condition and use app.redirect to redirect to a certain url.

Rubin bhandari
  • 1,873
  • 15
  • 20
-2

Try this:

app.get('/toto', function(req, res) {
  res.redirect('/heytoto');
});
  • 3
    Yea but it's a redirection... And I wanna rewrite my urls I don't wanna use the "res.redirect()" function. – tonymx227 Jun 01 '13 at 20:04