mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-21 09:52:06 +03:00
8ccf27340b
closes #9786 - Make GET request when url has no provider match - The HEAD request was made in order to send less data over the wire when checking for redirects for urls that do not have an oembed provider match. We are now going to look for provider metatags withing the response of the request - rather than making a HEAD followed by a GET if no redirect is found, this condenses that to a single request. - Try to get OEmbed data from tag if no provider - Here we parse the HTML response of the resource and look for a link tag that will give us the oembed resource url which we can use to fetch the embed html
96 lines
2.7 KiB
JavaScript
96 lines
2.7 KiB
JavaScript
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 = 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};
|
|
};
|
|
|
|
const getOembedUrlFromHTML = function getOembedUrlFromHTML(html) {
|
|
return cheerio('link[type="application/json+oembed"]', html).attr('href');
|
|
};
|
|
|
|
let oembed = {
|
|
read(options) {
|
|
let {url} = options;
|
|
|
|
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();
|
|
});
|
|
}
|
|
};
|
|
|
|
module.exports = oembed;
|