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:
parent
8c54f3cca9
commit
2941932ebe
2 changed files with 52 additions and 25 deletions
|
@ -1,7 +1,7 @@
|
||||||
var crypto = require('crypto'),
|
var crypto = require('crypto'),
|
||||||
downsize = require('downsize'),
|
downsize = require('downsize'),
|
||||||
RSS = require('rss'),
|
RSS = require('rss'),
|
||||||
config = require('../../../config'),
|
url = require('url'),
|
||||||
utils = require('../../../utils'),
|
utils = require('../../../utils'),
|
||||||
errors = require('../../../errors'),
|
errors = require('../../../errors'),
|
||||||
i18n = require('../../../i18n'),
|
i18n = require('../../../i18n'),
|
||||||
|
@ -18,14 +18,6 @@ var crypto = require('crypto'),
|
||||||
getFeedXml,
|
getFeedXml,
|
||||||
feedCache = {};
|
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) {
|
function handleError(next) {
|
||||||
return function handleError(err) {
|
return function handleError(err) {
|
||||||
return next(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) {
|
getFeedXml = function getFeedXml(path, data) {
|
||||||
var dataHash = crypto.createHash('md5').update(JSON.stringify(data)).digest('hex');
|
var dataHash = crypto.createHash('md5').update(JSON.stringify(data)).digest('hex');
|
||||||
if (!feedCache[path] || feedCache[path].hash !== dataHash) {
|
if (!feedCache[path] || feedCache[path].hash !== dataHash) {
|
||||||
|
@ -161,7 +139,8 @@ generate = function generate(req, res, next) {
|
||||||
// Initialize RSS
|
// Initialize RSS
|
||||||
var pageParam = req.params.page !== undefined ? req.params.page : 1,
|
var pageParam = req.params.page !== undefined ? req.params.page : 1,
|
||||||
slugParam = req.params.slug,
|
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;
|
channelConfig = res.locals.channel;
|
||||||
|
|
||||||
// Ensure we at least have an empty object for postOptions
|
// 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.feedUrl = utils.url.urlFor({relativeUrl: baseUrl, secure: req.secure}, true);
|
||||||
data.secure = req.secure;
|
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.set('Content-Type', 'text/xml; charset=UTF-8');
|
||||||
res.send(feedXml);
|
res.send(feedXml);
|
||||||
});
|
});
|
||||||
|
|
|
@ -349,6 +349,33 @@ describe('RSS', function () {
|
||||||
}).should.be.true();
|
}).should.be.true();
|
||||||
apiTagStub.calledOnce.should.be.true();
|
apiTagStub.calledOnce.should.be.true();
|
||||||
xmlData.should.match(/<channel><title><!\[CDATA\[Magic - Test\]\]><\/title>/);
|
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();
|
done();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -367,6 +394,27 @@ describe('RSS', function () {
|
||||||
apiBrowseStub.calledWith({page: 1, filter: 'author:\'joe\'', include: 'author,tags'}).should.be.true();
|
apiBrowseStub.calledWith({page: 1, filter: 'author:\'joe\'', include: 'author,tags'}).should.be.true();
|
||||||
apiUserStub.calledOnce.should.be.true();
|
apiUserStub.calledOnce.should.be.true();
|
||||||
xmlData.should.match(/<channel><title><!\[CDATA\[Joe Blogs - Test\]\]><\/title>/);
|
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();
|
done();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue