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:
parent
31c35e1c2c
commit
94b3735c6e
6 changed files with 181 additions and 1 deletions
|
@ -69,5 +69,9 @@ module.exports = {
|
|||
|
||||
get preview() {
|
||||
return shared.pipeline(require('./preview'), localUtils);
|
||||
},
|
||||
|
||||
get oembed() {
|
||||
return shared.pipeline(require('./oembed'), localUtils);
|
||||
}
|
||||
};
|
||||
|
|
102
core/server/api/v2/oembed.js
Normal file
102
core/server/api/v2/oembed.js
Normal 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();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
|
@ -57,5 +57,9 @@ module.exports = {
|
|||
|
||||
get preview() {
|
||||
return require('./preview');
|
||||
},
|
||||
|
||||
get oembed() {
|
||||
return require('./oembed');
|
||||
}
|
||||
};
|
||||
|
|
9
core/server/api/v2/utils/serializers/output/oembed.js
Normal file
9
core/server/api/v2/utils/serializers/output/oembed.js
Normal 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);
|
||||
}
|
||||
};
|
|
@ -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;
|
||||
};
|
||||
|
|
61
core/test/functional/api/v2/admin/oembed_spec.js
Normal file
61
core/test/functional/api/v2/admin/oembed_spec.js
Normal 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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Add table
Reference in a new issue