mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
🎨 Koenig - Added support for shortened URLs in embed card (#9781)
refs https://github.com/TryGhost/Ghost/issues/9724 - perform a HEAD request on a url if we don't find a matching provider, following any redirects until we hit success response before looking up providers for the resulting url
This commit is contained in:
parent
860718f584
commit
cfd9ff3993
2 changed files with 91 additions and 23 deletions
|
@ -1,6 +1,31 @@
|
|||
const common = require('../lib/common');
|
||||
const {extract, hasProvider} = require('oembed-parser');
|
||||
const Promise = require('bluebird');
|
||||
const request = require('../lib/request');
|
||||
|
||||
const findUrlWithProvider = function 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};
|
||||
};
|
||||
|
||||
let oembed = {
|
||||
read(options) {
|
||||
|
@ -12,34 +37,41 @@ let oembed = {
|
|||
}));
|
||||
}
|
||||
|
||||
// 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 base = url.replace(/^\/\/|^https?:\/\/(?:www\.)?/, '');
|
||||
let testUrls = [
|
||||
`http://${base}`,
|
||||
`https://${base}`,
|
||||
`http://www.${base}`,
|
||||
`https://www.${base}`
|
||||
];
|
||||
let provider;
|
||||
for (let testUrl of testUrls) {
|
||||
provider = hasProvider(testUrl);
|
||||
if (provider) {
|
||||
url = testUrl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!provider) {
|
||||
function unknownProvider() {
|
||||
return Promise.reject(new common.errors.ValidationError({
|
||||
message: common.i18n.t('errors.api.oembed.unknownProvider')
|
||||
}));
|
||||
}
|
||||
|
||||
return extract(url).catch((err) => {
|
||||
return Promise.reject(new common.errors.InternalServerError({
|
||||
message: err.message
|
||||
}));
|
||||
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: 'HEAD',
|
||||
timeout: 2 * 1000,
|
||||
followRedirect: true
|
||||
}).then((response) => {
|
||||
if (response.url !== url) {
|
||||
({url, provider} = findUrlWithProvider(response.url));
|
||||
return provider ? knownProvider(url) : unknownProvider();
|
||||
}
|
||||
|
||||
return unknownProvider();
|
||||
}).catch(() => {
|
||||
return unknownProvider();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -39,6 +39,38 @@ describe('API: oembed', function () {
|
|||
}).catch(done);
|
||||
});
|
||||
|
||||
it('follows redirects to get base url', function (done) {
|
||||
let redirectMock = nock('https://youtu.be')
|
||||
.intercept('/yHohwmrxrto', 'HEAD')
|
||||
.reply(302, undefined, {
|
||||
// eslint-disable-next-line
|
||||
'Location': 'https://www.youtube.com/watch?v=yHohwmrxrto&feature=youtu.be'
|
||||
});
|
||||
|
||||
let videoMock = nock('https://www.youtube.com')
|
||||
.intercept('/watch', 'HEAD')
|
||||
.query({v: 'yHohwmrxrto', feature: 'youtu.be'})
|
||||
.reply(200);
|
||||
|
||||
let requestMock = nock('https://www.youtube.com')
|
||||
.get('/oembed')
|
||||
.query(true)
|
||||
.reply(200, {
|
||||
html: 'test'
|
||||
});
|
||||
|
||||
OembedAPI.read({url: 'https://youtu.be/yHohwmrxrto'})
|
||||
.then((results) => {
|
||||
redirectMock.isDone().should.be.true;
|
||||
videoMock.isDone().should.be.true;
|
||||
requestMock.isDone().should.be.true;
|
||||
should.exist(results);
|
||||
should.exist(results.html);
|
||||
results.html.should.eql('test');
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
it('returns error for missing url', function (done) {
|
||||
OembedAPI.read({url: ''})
|
||||
.then(() => {
|
||||
|
@ -50,6 +82,10 @@ describe('API: oembed', function () {
|
|||
});
|
||||
|
||||
it('returns error for unsupported provider', function (done) {
|
||||
nock('http://example.com')
|
||||
.intercept('/unknown', 'HEAD')
|
||||
.reply(200);
|
||||
|
||||
OembedAPI.read({url: 'http://example.com/unknown'})
|
||||
.then(() => {
|
||||
done(new Error('Fetch oembed with unknown url provider should error'));
|
||||
|
|
Loading…
Add table
Reference in a new issue