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

🐛 Fixed HTTP 500 responses when oembed endpoint receives error

fixes https://github.com/TryGhost/Product/issues/4237

- this fixes the fact that we return a HTTP 500 response when the oembed
  library receives an error, such as a 401 or 403
- includes special handling for cases where we want to return a slightly
  different error message
- also adds unit tests for @tryghost/oembed-service package
This commit is contained in:
Daniel Lockyer 2024-03-12 10:36:34 +01:00 committed by Daniel Lockyer
parent 6842d599e9
commit 5fa4496d52
4 changed files with 110 additions and 15 deletions

View file

@ -107,7 +107,7 @@ describe('Oembed API', function () {
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(401);
.expect(422);
requestMock.isDone().should.be.true();
should.exist(res.body.errors);

View file

@ -10,6 +10,7 @@ const messages = {
noUrlProvided: 'No url provided.',
insufficientMetadata: 'URL contains insufficient metadata.',
unknownProvider: 'No provider found for supplied URL.',
unableToFetchOembed: 'Unable to fetch requested embed.',
unauthorized: 'URL contains a private resource.'
};
@ -101,15 +102,17 @@ class OEmbedService {
try {
return await extract(url);
} catch (err) {
if (err.message === 'Request failed with error code 401') {
throw new errors.UnauthorizedError({
message: messages.unauthorized
});
} else {
throw new errors.InternalServerError({
message: err.message
if (err.message === 'Request failed with error code 401' || err.message === 'Request failed with error code 403') {
throw new errors.ValidationError({
message: tpl(messages.unableToFetchOembed),
context: messages.unauthorized
});
}
throw new errors.ValidationError({
message: tpl(messages.unableToFetchOembed),
context: err.message
});
}
}

View file

@ -1,7 +0,0 @@
const assert = require('assert/strict');
describe('Hello world', function () {
it('Runs a test', function () {
assert.ok(require('../index'));
});
});

View file

@ -0,0 +1,99 @@
const assert = require('assert/strict');
const nock = require('nock');
const OembedService = require('../');
describe('oembed-service', function () {
/** @type {OembedService} */
let oembedService;
before(function () {
oembedService = new OembedService({});
nock.disableNetConnect();
});
afterEach(function () {
nock.cleanAll();
});
describe('known provider', function () {
it('should return data if successful', async function () {
nock('https://www.youtube.com')
.get('/oembed')
.query(true)
.reply(200, {
title: 'Test Title',
author_name: 'Test Author',
author_url: 'https://www.youtube.com/user/testauthor',
html: '<iframe src="https://www.youtube.com/embed/1234"></iframe>'
});
const response = await oembedService.knownProvider('https://www.youtube.com/watch?v=1234');
assert.equal(response.title, 'Test Title');
assert.equal(response.author_name, 'Test Author');
assert.equal(response.author_url, 'https://www.youtube.com/user/testauthor');
assert.equal(response.html, '<iframe src="https://www.youtube.com/embed/1234"></iframe>');
});
it('should return a ValidationError if upstream 401s', async function () {
nock('https://www.youtube.com')
.get('/oembed')
.query(true)
.reply(401);
try {
await oembedService.knownProvider('https://www.youtube.com/watch?v=1234');
} catch (error) {
assert.equal(error.name, 'ValidationError');
assert.equal(error.statusCode, 422);
assert.equal(error.context, 'URL contains a private resource.');
}
});
it('should return a ValidationError if upstream 403s', async function () {
nock('https://www.youtube.com')
.get('/oembed')
.query(true)
.reply(403);
try {
await oembedService.knownProvider('https://www.youtube.com/watch?v=1234');
} catch (error) {
assert.equal(error.name, 'ValidationError');
assert.equal(error.statusCode, 422);
assert.equal(error.context, 'URL contains a private resource.');
}
});
it('should return a ValidationError if upstream 404s', async function () {
nock('https://www.youtube.com')
.get('/oembed')
.query(true)
.reply(404);
try {
await oembedService.knownProvider('https://www.youtube.com/watch?v=1234');
} catch (error) {
assert.equal(error.name, 'ValidationError');
assert.equal(error.statusCode, 422);
assert.equal(error.context, 'Request failed with error code 404');
}
});
it('should return a ValidationError if upstream 500s', async function () {
nock('https://www.youtube.com')
.get('/oembed')
.query(true)
.reply(500);
try {
await oembedService.knownProvider('https://www.youtube.com/watch?v=1234');
} catch (error) {
assert.equal(error.name, 'ValidationError');
assert.equal(error.statusCode, 422);
assert.equal(error.context, 'Request failed with error code 500');
}
});
});
});