diff --git a/ghost/core/test/e2e-api/admin/oembed.test.js b/ghost/core/test/e2e-api/admin/oembed.test.js
index dfeed17f11fa..f300d71c910b 100644
--- a/ghost/core/test/e2e-api/admin/oembed.test.js
+++ b/ghost/core/test/e2e-api/admin/oembed.test.js
@@ -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);
diff --git a/ghost/oembed-service/lib/OEmbedService.js b/ghost/oembed-service/lib/OEmbedService.js
index 738ff6895dc2..7715cb1facb3 100644
--- a/ghost/oembed-service/lib/OEmbedService.js
+++ b/ghost/oembed-service/lib/OEmbedService.js
@@ -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
+ });
}
}
diff --git a/ghost/oembed-service/test/hello.test.js b/ghost/oembed-service/test/hello.test.js
deleted file mode 100644
index d9b992702844..000000000000
--- a/ghost/oembed-service/test/hello.test.js
+++ /dev/null
@@ -1,7 +0,0 @@
-const assert = require('assert/strict');
-
-describe('Hello world', function () {
- it('Runs a test', function () {
- assert.ok(require('../index'));
- });
-});
diff --git a/ghost/oembed-service/test/oembed-service.test.js b/ghost/oembed-service/test/oembed-service.test.js
new file mode 100644
index 000000000000..1ada49a6fa75
--- /dev/null
+++ b/ghost/oembed-service/test/oembed-service.test.js
@@ -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: ''
+ });
+
+ 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, '');
+ });
+
+ 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');
+ }
+ });
+ });
+});