From 71e19d221329f426cc9fe5e691cb694f37e56276 Mon Sep 17 00:00:00 2001 From: Andrew Williamson Date: Tue, 24 Jan 2023 14:16:48 +0100 Subject: [PATCH] add trailing slash to amo-base-url & enforce within submit-addon Client (#2621) fixes https://github.com/mozilla/web-ext/issues/2579 --- src/program.js | 4 +++- src/util/submit-addon.js | 4 ++++ tests/unit/test-cmd/test.sign.js | 3 ++- tests/unit/test-util/test.submit-addon.js | 23 ++++++++++++++++++++--- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/program.js b/src/program.js index 2d975798ef..e9446bbaaa 100644 --- a/src/program.js +++ b/src/program.js @@ -48,6 +48,8 @@ type ExecuteOptions = { globalEnv?: string | void, }; +export const AMO_BASE_URL = 'https://addons.mozilla.org/api/v5/'; + /* * The command line program. */ @@ -568,7 +570,7 @@ Example: $0 --help run. 'amo-base-url': { describe: 'Signing API URL prefix - only used with `use-submission-api`', - default: 'https://addons.mozilla.org/api/v5', + default: AMO_BASE_URL, demandOption: true, type: 'string', }, diff --git a/src/util/submit-addon.js b/src/util/submit-addon.js index b108b857d0..49b230a48f 100644 --- a/src/util/submit-addon.js +++ b/src/util/submit-addon.js @@ -90,6 +90,10 @@ export default class Client { userAgentString, }: ClientConstructorParams) { this.apiAuth = apiAuth; + if (!baseUrl.pathname.endsWith('/')) { + baseUrl = new URL(baseUrl.href); + baseUrl.pathname += '/'; + } this.apiUrl = new URL('addons/', baseUrl); this.validationCheckInterval = validationCheckInterval; this.validationCheckTimeout = validationCheckTimeout; diff --git a/tests/unit/test-cmd/test.sign.js b/tests/unit/test-cmd/test.sign.js index c33c0bf8d7..a883331190 100644 --- a/tests/unit/test-cmd/test.sign.js +++ b/tests/unit/test-cmd/test.sign.js @@ -9,6 +9,7 @@ import { assert } from 'chai'; import * as sinon from 'sinon'; import { UsageError, WebExtError } from '../../../src/errors.js'; +import { AMO_BASE_URL } from '../../../src/program.js'; import { getManifestId } from '../../../src/util/manifest.js'; import { saveIdToFile } from '../../../src/util/submit-addon.js'; import { withTempDir } from '../../../src/util/temp-dir.js'; @@ -23,7 +24,7 @@ import type { ExtensionManifestApplications } from '../../../src/util/manifest'; describe('sign', () => { function getStubs() { const signingConfig = { - amoBaseUrl: 'http://not-the-real-amo.com/api/v5', + amoBaseUrl: AMO_BASE_URL, apiKey: 'AMO JWT issuer', apiSecret: 'AMO JWT secret', apiUrlPrefix: 'http://not-the-real-amo.com/api/v4', diff --git a/tests/unit/test-util/test.submit-addon.js b/tests/unit/test-util/test.submit-addon.js index 5a97f86e47..5838029958 100644 --- a/tests/unit/test-util/test.submit-addon.js +++ b/tests/unit/test-util/test.submit-addon.js @@ -8,6 +8,7 @@ import { afterEach, before, beforeEach, describe, it } from 'mocha'; import * as sinon from 'sinon'; import { File, FormData, Response } from 'node-fetch'; +import { AMO_BASE_URL } from '../../../src/program.js'; import Client, { JwtApiAuth, saveIdToFile, @@ -69,7 +70,7 @@ describe('util.submit-addon', () => { const signAddonDefaults = { apiKey: 'some-key', apiSecret: 'ffff', - amoBaseUrl: 'https://some.url/api/v5', + amoBaseUrl: AMO_BASE_URL, timeout: 1, downloadDir: '/some-dir/', xpiPath: '/some.xpi', @@ -81,7 +82,7 @@ describe('util.submit-addon', () => { it('creates Client with parameters', async () => { const apiKey = 'fooKey'; const apiSecret = '4321'; - const amoBaseUrl = 'https://foo.host/api/v5'; + const amoBaseUrl = AMO_BASE_URL; const baseUrl = new URL(amoBaseUrl); const downloadDir = '/foo'; const clientSpy = sinon.spy(Client); @@ -186,7 +187,7 @@ describe('util.submit-addon', () => { }); describe('Client', () => { - const baseUrl = new URL('http://not-a-real-amo-api.com/api/v5'); + const baseUrl = new URL(AMO_BASE_URL); const apiAuth = new JwtApiAuth({ apiKey: 'fake-api-key', @@ -241,6 +242,22 @@ describe('util.submit-addon', () => { getAuthHeaderSpy.resetHistory(); }); + it('adds a missing trailing slash to baseUrl before setting apiUrl', () => { + const noSlashBaseUrl = new URL('http://url.without/trailing/slash'); + const client = new Client({ ...clientDefaults, baseUrl: noSlashBaseUrl }); + assert.equal( + client.apiUrl.href, + new URL(`${noSlashBaseUrl.href}/addons/`).href + ); + }); + + it('drops extra characters on baseUrl before setting apiUrl', () => { + const cleanUrl = 'http://url.with/extra'; + const extraBaseUrl = new URL(`${cleanUrl}?#`); + const client = new Client({ ...clientDefaults, baseUrl: extraBaseUrl }); + assert.equal(client.apiUrl.href, new URL(`${cleanUrl}/addons/`).href); + }); + describe('doUploadSubmit', () => { it('submits the xpi', async () => { const client = new Client(clientDefaults);