Since the site I am working on is an existing one and I'm transferring stuff from a PHP site to Keystone… how do I redirect pages that are now dead?
For example:
Hey @jamlen,
This is pretty easy to solve, we've done it with a few sites ourselves.
For simplicity, I've just added a feature to allow you to set up redirects within Keystone itself, although this will only work for static URLs, e.g. index.php => /
Use it by adding the following to your route configuration (usually /routes/index.js), or your main keystone init file (usually /keystone.js) - anywhere _before_ keystone.start().
keystone.redirect('/index.php', '/');
keystone.redirect('sermons.php', '/');
You can also provide an object of redirect path: destination pairs:
keystone.redirect({
'/index.php': '/',
'sermons.php', '/'
});
Keystone processes redirects just before serving a 404 so they won't impact the performance of your other route handlers.
_note: the redirect functionality is in master but hasn't been released to npm yet, I'll update this issue when it is_
For dynamic routing, set up a route handler as you would for a view. We usually put these in a /routes/redirects/ folder and import it as you would /routes/views/:
// in routes/index.js
app.get('/', routes.views.index);
// etc.
app.all('/sermon.php', routes.redirects.sermon);
And here's an example of the redirect route controller, assuming you look up an old sermon ID in the database and map it to a new id (your solution may be simpler, but I'm providing a more complex example in case you need it)
// in routes/redirects/sermon.js
var keystone = require('keystone'),
Sermon = keystone.list('Sermon');
module.exports = function(req, res) {
Sermon.model.findOne().where('oldId', req.query.id).exec(function(err, sermon) {
if (err) return res.status(500).render('errors/500'); // or however you handle errors
if (!sermon) return res.status(404).render('errors/404'); // or your 404 template path
res.status(301).redirect('/sermon/' +sermon.id);
});
}
Thanks @JedWatson that's great and I'll look at that, I also looked around and found express-redirect which looks nice and might have a go at plumbing it in if you like the look of it for more non-static redirection?
@jamlen good find - I really should have checked for an existing implementation first :)
We could definitely add similar support for parameters, and could build on it to support query arguments on both sides (express-redirect only implements them in the redirection url, so it wouldn't work for your sermon.php?id={sermonId} requirement).
The following would be fairly easy to support:
keystone.redirect({
'/index.php': '/',
'/sermons.php': '/'
'/sermon.php': function(req) { return '/sermon/' + req.query.id }
});
Using the new async dependency injection library I made (/lib/asyncdi.js), we could even add support for callbacks, so the API would also work like this:
keystone.redirect('/sermon.php', function(req, redirect, next) {
// do something async to validate req.query.id and find a valid sermonKey
if (sermonKey) redirect('/sermon/' + sermonKey);
else next(); // continues to standard 404 handler
});
Let me know what you think.
FWIW, I was able to implement the express-redirect plugin with my keystone app by requiring it and just doing
keystone.redirect("/foo", "/bar");
redirect(keystone);
keystone.start();
I definitely like the idea of being able to support query arguments on both sides though, as @JedWatson mentioned above. Would definitely help preserve SEO juice when redeveloping an existing site.
It would be extremely helpful to be able to specify 301 vs 302 redirects with this feature.
If you're already using a reverse proxy from nginx (which I do for all my Node powered sites), I recommend implementing your redirects at that level for better performance, and to keep the details of your old site's configuration out of your new site/application code.
Awesome, thanks @ericelliott
I like this solution better. Worked great!
\( ゚ヮ゚)/
@jamlen @JedWatson Do we need to keep this open tracking some planned work, or should we close this ticket?
We're closing all feature requests to keep the issue tracker unpolluted. From now on submit feature requests on productpains.com!
@JedWatson @andrewlinfoot is there any way to redirect naked subdomain to www subdomain, for example, from https://example.com to https://www.example.com?
@yao23 that's a DNS thing, it has nothing to do with Keystone. Here's a guide for nginx for example.
@mxstbr I have no permission to change the server setting, so achieve it in code:
/* Keystone/routes/middleware.js */
/**
Redirect naked domain (example.com) to full domain (www.example.com)
*/
exports.redirectToFullDomainName = function(req, res, next) {
if(req.headers.host === 'example.com') {
return res.redirect('http://www.example.com'+req.url);
}
next();
};
/* Keystone/routes/index.js */
// Common Middleware
keystone.pre('routes', middleware.redirectToFullDomainName);
keystone.pre('routes', middleware.initLocals);
keystone.pre('render', middleware.flashMessages);
@JedWatson Hi Jed,
I am trying to get all pages on my site: www.findyoga.com.au to redirect to the https instead of http as google is indexing both the secure and non-secure sessions. Is there an easy way to get a redirect happening?
Thanks:)
Hey guys, a bit of a noob question (I can't find anything anywhere). I'm hosting on Heroku, and I'm noticing that my Google search results are showing my https://colinstodd-v2.herokuapp.com in the results. I'm looking to create a 301 redirect to redirect the app to its home page/custom domain http://www.colinstodd.com (or home). Everything is set up correctly, I just want to get rid of the https://colinstodd-v2.herokuapp.com/ from being indexed by Google, and Heroku suggests setting up a 301 redirect. I thought to do keystone.redirect('colinstodd-v2.herokuapp.com', '/'); but that's not working.
Im a bit lost. Sorry to be the noob. FWIW, I'm loving Keystone :)
@cbstodd If the Google results are your only issue, you could do this by placing a canonical tag in the <head> for each of your pages e.g.
<link rel="canonical" href="http://www.colinstodd.com">
This would eventually prevent Google from displaying the Heroku Domain in search results and is better than setting up a redirect as it is often useful to be able to access your site via the Heroku Domain, independently of your own custom domain(s).
Most helpful comment
@cbstodd If the Google results are your only issue, you could do this by placing a canonical tag in the
<head>for each of your pages e.g.<link rel="canonical" href="http://www.colinstodd.com">This would eventually prevent Google from displaying the Heroku Domain in search results and is better than setting up a redirect as it is often useful to be able to access your site via the Heroku Domain, independently of your own custom domain(s).