0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00

Removed hardcoded url structures from RSS (#9113)

refs #5091

- This removes hardcoded config to generate feed urls
- This means that RSS feeds work properly for custom channels
- Remaining assumption is that paginated feeds will end /pageNum/
- Added extra tests
- Don't pass through query params
This commit is contained in:
Hannah Wolfe 2017-10-09 15:08:53 +01:00 committed by Katharina Irrgang
parent 8c54f3cca9
commit 2941932ebe
2 changed files with 52 additions and 25 deletions

View file

@ -1,7 +1,7 @@
var crypto = require('crypto'),
downsize = require('downsize'),
RSS = require('rss'),
config = require('../../../config'),
url = require('url'),
utils = require('../../../utils'),
errors = require('../../../errors'),
i18n = require('../../../i18n'),
@ -18,14 +18,6 @@ var crypto = require('crypto'),
getFeedXml,
feedCache = {};
function isTag(req) {
return req.originalUrl.indexOf(utils.url.urlJoin('/', config.get('routeKeywords').tag, '/')) !== -1;
}
function isAuthor(req) {
return req.originalUrl.indexOf(utils.url.urlJoin('/', config.get('routeKeywords').author, '/')) !== -1;
}
function handleError(next) {
return function handleError(err) {
return next(err);
@ -53,20 +45,6 @@ function getData(channelOpts, slugParam) {
});
}
function getBaseUrl(req, slugParam) {
var baseUrl = utils.url.getSubdir();
if (isTag(req)) {
baseUrl = utils.url.urlJoin(baseUrl, config.get('routeKeywords').tag, slugParam, 'rss/');
} else if (isAuthor(req)) {
baseUrl = utils.url.urlJoin(baseUrl, config.get('routeKeywords').author, slugParam, 'rss/');
} else {
baseUrl = utils.url.urlJoin(baseUrl, 'rss/');
}
return baseUrl;
}
getFeedXml = function getFeedXml(path, data) {
var dataHash = crypto.createHash('md5').update(JSON.stringify(data)).digest('hex');
if (!feedCache[path] || feedCache[path].hash !== dataHash) {
@ -161,7 +139,8 @@ generate = function generate(req, res, next) {
// Initialize RSS
var pageParam = req.params.page !== undefined ? req.params.page : 1,
slugParam = req.params.slug,
baseUrl = getBaseUrl(req, slugParam),
// Base URL needs to be the URL for the feed without pagination:
baseUrl = url.parse(req.originalUrl).pathname.replace(new RegExp('/' + pageParam + '/$'), '/'),
channelConfig = res.locals.channel;
// Ensure we at least have an empty object for postOptions
@ -184,7 +163,7 @@ generate = function generate(req, res, next) {
data.feedUrl = utils.url.urlFor({relativeUrl: baseUrl, secure: req.secure}, true);
data.secure = req.secure;
return getFeedXml(req.originalUrl, data).then(function then(feedXml) {
return getFeedXml(baseUrl, data).then(function then(feedXml) {
res.set('Content-Type', 'text/xml; charset=UTF-8');
res.send(feedXml);
});

View file

@ -349,6 +349,33 @@ describe('RSS', function () {
}).should.be.true();
apiTagStub.calledOnce.should.be.true();
xmlData.should.match(/<channel><title><!\[CDATA\[Magic - Test\]\]><\/title>/);
xmlData.should.match(/<atom:link href="http:\/\/my-ghost-blog.com\/tag\/magic\/rss\/" rel="self" type="application\/rss\+xml"\/>/);
done();
};
rss(req, res, failTest(done));
});
it('should process the data correctly for a paginated tag feed', function (done) {
// setup
req.originalUrl = '/tag/magic/rss/2/';
req.params.slug = 'magic';
req.params.page = '2';
res.locals.channel = channelConfig.get('tag');
res.locals.channel.isRSS = true;
// test
res.send = function send(xmlData) {
apiBrowseStub.calledOnce.should.be.true();
apiBrowseStub.calledWith({
page: '2',
filter: 'tags:\'magic\'+tags.visibility:\'public\'',
include: 'author,tags'
}).should.be.true();
apiTagStub.calledOnce.should.be.true();
xmlData.should.match(/<channel><title><!\[CDATA\[Magic - Test\]\]><\/title>/);
xmlData.should.match(/<atom:link href="http:\/\/my-ghost-blog.com\/tag\/magic\/rss\/" rel="self" type="application\/rss\+xml"\/>/);
done();
};
@ -367,6 +394,27 @@ describe('RSS', function () {
apiBrowseStub.calledWith({page: 1, filter: 'author:\'joe\'', include: 'author,tags'}).should.be.true();
apiUserStub.calledOnce.should.be.true();
xmlData.should.match(/<channel><title><!\[CDATA\[Joe Blogs - Test\]\]><\/title>/);
xmlData.should.match(/<atom:link href="http:\/\/my-ghost-blog.com\/author\/joe\/rss\/" rel="self" type="application\/rss\+xml"\/>/);
done();
};
rss(req, res, failTest(done));
});
it('should process the data correctly for a paginated author feed', function (done) {
req.originalUrl = '/author/joe/rss/2/';
req.params.slug = 'joe';
req.params.page = '2';
res.locals.channel = channelConfig.get('author');
res.locals.channel.isRSS = true;
// test
res.send = function send(xmlData) {
apiBrowseStub.calledOnce.should.be.true();
apiBrowseStub.calledWith({page: '2', filter: 'author:\'joe\'', include: 'author,tags'}).should.be.true();
apiUserStub.calledOnce.should.be.true();
xmlData.should.match(/<channel><title><!\[CDATA\[Joe Blogs - Test\]\]><\/title>/);
xmlData.should.match(/<atom:link href="http:\/\/my-ghost-blog.com\/author\/joe\/rss\/" rel="self" type="application\/rss\+xml"\/>/);
done();
};