0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-10 23:36:14 -05:00

Added oembed controller to v2 api (#10057)

refs #9866

- Added oembed controller to v2 API
This commit is contained in:
Rishabh Garg 2018-11-02 14:02:26 +05:30 committed by Naz Gargol
parent 31c35e1c2c
commit 94b3735c6e
6 changed files with 181 additions and 1 deletions

View file

@ -69,5 +69,9 @@ module.exports = {
get preview() {
return shared.pipeline(require('./preview'), localUtils);
},
get oembed() {
return shared.pipeline(require('./oembed'), localUtils);
}
};

View file

@ -0,0 +1,102 @@
const common = require('../../lib/common');
const {extract, hasProvider} = require('oembed-parser');
const Promise = require('bluebird');
const request = require('../../lib/request');
const cheerio = require('cheerio');
const findUrlWithProvider = (url) => {
let provider;
// build up a list of URL variations to test against because the oembed
// providers list is not always up to date with scheme or www vs non-www
let baseUrl = url.replace(/^\/\/|^https?:\/\/(?:www\.)?/, '');
let testUrls = [
`http://${baseUrl}`,
`https://${baseUrl}`,
`http://www.${baseUrl}`,
`https://www.${baseUrl}`
];
for (let testUrl of testUrls) {
provider = hasProvider(testUrl);
if (provider) {
url = testUrl;
break;
}
}
return {url, provider};
};
const getOembedUrlFromHTML = (html) => {
return cheerio('link[type="application/json+oembed"]', html).attr('href');
};
module.exports = {
docName: 'oembed',
read: {
permissions: false,
data: [
'url'
],
options: [],
query({data}) {
let {url} = data;
if (!url || !url.trim()) {
return Promise.reject(new common.errors.BadRequestError({
message: common.i18n.t('errors.api.oembed.noUrlProvided')
}));
}
function unknownProvider() {
return Promise.reject(new common.errors.ValidationError({
message: common.i18n.t('errors.api.oembed.unknownProvider')
}));
}
function knownProvider(url) {
return extract(url).catch((err) => {
return Promise.reject(new common.errors.InternalServerError({
message: err.message
}));
});
}
let provider;
({url, provider} = findUrlWithProvider(url));
if (provider) {
return knownProvider(url);
}
// see if the URL is a redirect to cater for shortened urls
return request(url, {
method: 'GET',
timeout: 2 * 1000,
followRedirect: true
}).then((response) => {
if (response.url !== url) {
({url, provider} = findUrlWithProvider(response.url));
return provider ? knownProvider(url) : unknownProvider();
}
const oembedUrl = getOembedUrlFromHTML(response.body);
if (!oembedUrl) {
return unknownProvider();
}
return request(oembedUrl, {
method: 'GET',
json: true
}).then((response) => {
return response.body;
});
}).catch(() => {
return unknownProvider();
});
}
}
};

View file

@ -57,5 +57,9 @@ module.exports = {
get preview() {
return require('./preview');
},
get oembed() {
return require('./oembed');
}
};

View file

@ -0,0 +1,9 @@
const debug = require('ghost-ignition').debug('api:v2:utils:serializers:output:oembed');
module.exports = {
all(res, apiConfig, frame) {
debug('all');
frame.response = res;
debug(frame.response);
}
};

View file

@ -226,7 +226,7 @@ module.exports = function apiRoutes() {
router.del('/webhooks/:id', mw.authAdminAPI, apiv2.http(apiv2.webhooks.destroy));
// ## Oembed (fetch response from oembed provider)
router.get('/oembed', mw.authAdminAPI, api.http(api.oembed.read));
router.get('/oembed', mw.authAdminAPI, apiv2.http(apiv2.oembed.read));
return router;
};

View file

@ -0,0 +1,61 @@
const nock = require('nock');
const should = require('should');
const supertest = require('supertest');
const testUtils = require('../../../../utils');
const config = require('../../../../../../core/server/config');
const localUtils = require('./utils');
const ghost = testUtils.startGhost;
describe('Oembed API', function () {
let ghostServer, request;
before(function () {
return ghost()
.then((_ghostServer) => {
ghostServer = _ghostServer;
request = supertest.agent(config.get('url'));
})
.then(() => {
return localUtils.doAuth(request);
});
});
describe('success', function () {
it('can fetch an embed', function (done) {
let requestMock = nock('https://www.youtube.com')
.get('/oembed')
.query(true)
.reply(200, {
html: '<iframe width="480" height="270" src="https://www.youtube.com/embed/E5yFcdPAGv0?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>',
thumbnail_width: 480,
width: 480,
author_url: 'https://www.youtube.com/user/gorillaz',
height: 270,
thumbnail_height: 360,
provider_name: 'YouTube',
title: 'Gorillaz - Humility (Official Video)',
provider_url: 'https://www.youtube.com/',
author_name: 'Gorillaz',
version: '1.0',
thumbnail_url: 'https://i.ytimg.com/vi/E5yFcdPAGv0/hqdefault.jpg',
type: 'video'
});
request.get(localUtils.API.getApiQuery('oembed/?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DE5yFcdPAGv0'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
return done(err);
}
requestMock.isDone().should.be.true();
should.exist(res.body.html);
done();
});
});
});
});