mirror of
https://github.com/transloadit/uppy.git
synced 2026-01-23 02:25:07 +00:00
Companion option uploadHeaders (#5981)
closes #5921 also improve tests that currently depend on eachother todo - [x] docs https://github.com/transloadit/uppy.io/pull/394
This commit is contained in:
parent
5e166a101d
commit
0c8dd19dc2
10 changed files with 126 additions and 77 deletions
5
.changeset/nine-rice-brake.md
Normal file
5
.changeset/nine-rice-brake.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@uppy/companion": patch
|
||||
---
|
||||
|
||||
New Companion option `uploadHeaders` which can be used to include a static set of headers with every request sent to all upload destinations.
|
||||
|
|
@ -148,10 +148,18 @@ export default class Uploader {
|
|||
* @property {number} [chunkSize]
|
||||
* @property {string} [providerName]
|
||||
*
|
||||
* @param {UploaderOptions} options
|
||||
* @param {UploaderOptions} optionsIn
|
||||
*/
|
||||
constructor(options) {
|
||||
validateOptions(options)
|
||||
constructor(optionsIn) {
|
||||
validateOptions(optionsIn)
|
||||
|
||||
const options = {
|
||||
...optionsIn,
|
||||
headers: {
|
||||
...optionsIn.headers,
|
||||
...optionsIn.companionOptions.uploadHeaders,
|
||||
},
|
||||
}
|
||||
|
||||
this.providerName = options.providerName
|
||||
this.options = options
|
||||
|
|
@ -682,7 +690,7 @@ export default class Uploader {
|
|||
try {
|
||||
const httpMethod =
|
||||
(this.options.httpMethod || '').toUpperCase() === 'PUT' ? 'put' : 'post'
|
||||
const runRequest = await got[httpMethod]
|
||||
const runRequest = got[httpMethod]
|
||||
|
||||
const response = await runRequest(url, reqOptions)
|
||||
|
||||
|
|
|
|||
|
|
@ -215,6 +215,9 @@ const getConfigFromEnv = () => {
|
|||
process.env.COMPANION_TEST_DYNAMIC_OAUTH_CREDENTIALS === 'true',
|
||||
testDynamicOauthCredentialsSecret:
|
||||
process.env.COMPANION_TEST_DYNAMIC_OAUTH_CREDENTIALS_SECRET,
|
||||
uploadHeaders: process.env.COMPANION_UPLOAD_HEADERS
|
||||
? JSON.parse(process.env.COMPANION_UPLOAD_HEADERS)
|
||||
: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import nock from 'nock'
|
||||
import request from 'supertest'
|
||||
import { afterAll, describe, expect, it, test, vi } from 'vitest'
|
||||
import { afterAll, afterEach, describe, expect, it, test, vi } from 'vitest'
|
||||
import packageJson from '../package.json' with { type: 'json' }
|
||||
import * as tokenService from '../src/server/helpers/jwt.js'
|
||||
import * as defaults from './fixtures/constants.js'
|
||||
|
|
@ -37,8 +37,10 @@ const authData = {
|
|||
const token = tokenService.generateEncryptedAuthToken(authData, secret)
|
||||
const OAUTH_STATE = 'some-cool-nice-encrytpion'
|
||||
|
||||
afterAll(() => {
|
||||
afterEach(() => {
|
||||
nock.cleanAll()
|
||||
})
|
||||
afterAll(() => {
|
||||
nock.restore()
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
import nock from 'nock'
|
||||
import request from 'supertest'
|
||||
import { afterAll, describe, expect, test, vi } from 'vitest'
|
||||
import {
|
||||
afterAll,
|
||||
afterEach,
|
||||
beforeEach,
|
||||
describe,
|
||||
expect,
|
||||
test,
|
||||
vi,
|
||||
} from 'vitest'
|
||||
import * as tokenService from '../src/server/helpers/jwt.js'
|
||||
import { nockZoomRevoke, expects as zoomExpects } from './fixtures/zoom.js'
|
||||
import { getServer } from './mockserver.js'
|
||||
|
|
@ -21,32 +29,35 @@ const authData = {
|
|||
}
|
||||
const token = tokenService.generateEncryptedAuthToken(authData, secret)
|
||||
|
||||
afterAll(() => {
|
||||
afterEach(() => {
|
||||
nock.cleanAll()
|
||||
})
|
||||
afterAll(() => {
|
||||
nock.restore()
|
||||
})
|
||||
|
||||
describe('providers requests with remote oauth keys', () => {
|
||||
// mocking request module used to fetch custom oauth credentials
|
||||
nock('http://localhost:2111')
|
||||
.post('/zoom-keys')
|
||||
// @ts-ignore
|
||||
.reply((uri, { provider, parameters }) => {
|
||||
if (provider !== 'zoom' || parameters !== 'ZOOM-CREDENTIALS-PARAMS')
|
||||
return [400]
|
||||
beforeEach(() => {
|
||||
// mocking request module used to fetch custom oauth credentials
|
||||
nock('http://localhost:2111')
|
||||
.post('/zoom-keys')
|
||||
// @ts-ignore
|
||||
.reply((uri, { provider, parameters }) => {
|
||||
if (provider !== 'zoom' || parameters !== 'ZOOM-CREDENTIALS-PARAMS')
|
||||
return [400]
|
||||
|
||||
return [
|
||||
200,
|
||||
{
|
||||
credentials: {
|
||||
key: remoteZoomKey,
|
||||
secret: remoteZoomSecret,
|
||||
verificationToken: remoteZoomVerificationToken,
|
||||
return [
|
||||
200,
|
||||
{
|
||||
credentials: {
|
||||
key: remoteZoomKey,
|
||||
secret: remoteZoomSecret,
|
||||
verificationToken: remoteZoomVerificationToken,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
.persist()
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
test('zoom logout with remote oauth keys happy path', async () => {
|
||||
nockZoomRevoke({ key: remoteZoomKey, secret: remoteZoomSecret })
|
||||
|
|
@ -69,6 +80,8 @@ describe('providers requests with remote oauth keys', () => {
|
|||
})
|
||||
|
||||
test('zoom logout with wrong credentials params', async () => {
|
||||
nockZoomRevoke({ key: remoteZoomKey, secret: remoteZoomSecret })
|
||||
|
||||
const params = { params: 'WRONG-ZOOM-CREDENTIALS-PARAMS' }
|
||||
const encodedParams = Buffer.from(
|
||||
JSON.stringify(params),
|
||||
|
|
|
|||
|
|
@ -1,17 +1,21 @@
|
|||
import nock from 'nock'
|
||||
import request from 'supertest'
|
||||
import { afterAll, describe, test, vi } from 'vitest'
|
||||
import { afterAll, afterEach, beforeEach, describe, test, vi } from 'vitest'
|
||||
import { getServer } from './mockserver.js'
|
||||
|
||||
vi.mock('express-prom-bundle')
|
||||
|
||||
afterAll(() => {
|
||||
afterEach(() => {
|
||||
nock.cleanAll()
|
||||
})
|
||||
afterAll(() => {
|
||||
nock.restore()
|
||||
})
|
||||
|
||||
describe('handle deauthorization callback', () => {
|
||||
nock('https://api.zoom.us').post('/oauth/data/compliance').reply(200)
|
||||
beforeEach(() => {
|
||||
nock('https://api.zoom.us').post('/oauth/data/compliance').reply(200)
|
||||
})
|
||||
|
||||
test('providers without support for callback endpoint', async () => {
|
||||
return request(await getServer())
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
import nock from 'nock'
|
||||
import { afterAll, describe, expect, test } from 'vitest'
|
||||
import { afterAll, afterEach, describe, expect, test } from 'vitest'
|
||||
import {
|
||||
FORBIDDEN_IP_ADDRESS,
|
||||
getProtectedGot,
|
||||
} from '../src/server/helpers/request.js'
|
||||
|
||||
afterAll(() => {
|
||||
afterEach(() => {
|
||||
nock.cleanAll()
|
||||
})
|
||||
afterAll(() => {
|
||||
nock.restore()
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
import nock from 'nock'
|
||||
import request from 'supertest'
|
||||
import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest'
|
||||
import {
|
||||
afterAll,
|
||||
afterEach,
|
||||
beforeEach,
|
||||
describe,
|
||||
expect,
|
||||
test,
|
||||
vi,
|
||||
} from 'vitest'
|
||||
import * as tokenService from '../src/server/helpers/jwt.js'
|
||||
import * as providerModule from '../src/server/provider/index.js'
|
||||
import * as defaults from './fixtures/constants.js'
|
||||
|
|
@ -76,16 +84,17 @@ function nockGetCurrentAccount(times = 1) {
|
|||
})
|
||||
}
|
||||
|
||||
beforeAll(() => {
|
||||
beforeEach(() => {
|
||||
const url = new URL(defaults.THUMBNAIL_URL)
|
||||
nock(url.origin)
|
||||
.get(url.pathname)
|
||||
.reply(200, () => '')
|
||||
.persist()
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
afterEach(() => {
|
||||
nock.cleanAll()
|
||||
})
|
||||
afterAll(() => {
|
||||
nock.restore()
|
||||
})
|
||||
|
||||
|
|
@ -543,13 +552,6 @@ describe('logout of provider', () => {
|
|||
await runTest('box')
|
||||
})
|
||||
|
||||
test('dropbox', async () => {
|
||||
nock('https://api.dropboxapi.com')
|
||||
.post('/2/auth/token/revoke')
|
||||
.reply(200, {})
|
||||
await runTest('dropbox')
|
||||
})
|
||||
|
||||
test('drive', async () => {
|
||||
nock('https://accounts.google.com')
|
||||
.post('/o/oauth2/revoke?token=token+value')
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
import { once } from 'node:events'
|
||||
import fs from 'node:fs'
|
||||
import { createServer } from 'node:http'
|
||||
import { Readable } from 'node:stream'
|
||||
import nock from 'nock'
|
||||
import { afterAll, describe, expect, test, vi } from 'vitest'
|
||||
import { afterAll, afterEach, describe, expect, test, vi } from 'vitest'
|
||||
import Emitter from '../src/server/emitter/index.js'
|
||||
import Uploader, { ValidationError } from '../src/server/Uploader.js'
|
||||
import standalone from '../src/standalone/index.js'
|
||||
|
|
@ -12,8 +10,10 @@ import * as socketClient from './mocksocket.js'
|
|||
vi.mock('tus-js-client')
|
||||
vi.mock('express-prom-bundle')
|
||||
|
||||
afterAll(() => {
|
||||
afterEach(() => {
|
||||
nock.cleanAll()
|
||||
})
|
||||
afterAll(() => {
|
||||
nock.restore()
|
||||
})
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ const { companionOptions } = standalone()
|
|||
|
||||
const mockReq = {}
|
||||
|
||||
describe('uploader with tus protocol', () => {
|
||||
describe('uploader', () => {
|
||||
test('uploader respects uploadUrls', async () => {
|
||||
const opts = {
|
||||
endpoint: 'http://localhost/files',
|
||||
|
|
@ -207,12 +207,14 @@ describe('uploader with tus protocol', () => {
|
|||
useFormData,
|
||||
includeSize = true,
|
||||
address = 'localhost',
|
||||
// @ts-ignore
|
||||
extraCompanionOpts,
|
||||
} = {}) {
|
||||
const fileContent = Buffer.from('Some file content')
|
||||
const stream = Readable.from([fileContent])
|
||||
|
||||
const opts = {
|
||||
companionOptions,
|
||||
companionOptions: { ...companionOptions, ...extraCompanionOpts },
|
||||
endpoint: `http://${address}`,
|
||||
protocol: 'multipart',
|
||||
size: includeSize ? fileContent.length : undefined,
|
||||
|
|
@ -227,32 +229,33 @@ describe('uploader with tus protocol', () => {
|
|||
}
|
||||
|
||||
test('upload functions with xhr protocol', async () => {
|
||||
let alreadyCalled = false
|
||||
// We are creating our own test server for this test
|
||||
// instead of using nock because of a bug when passing a Node.js stream to got.
|
||||
// Ref: https://github.com/nock/nock/issues/2595
|
||||
const server = createServer((req, res) => {
|
||||
if (alreadyCalled) throw new Error('already called')
|
||||
alreadyCalled = true
|
||||
if (req.url === '/' && req.method === 'POST') {
|
||||
res.writeHead(200)
|
||||
res.end('OK')
|
||||
}
|
||||
}).listen()
|
||||
try {
|
||||
await once(server, 'listening')
|
||||
nock('http://localhost').post('/').reply(200, 'OK')
|
||||
const ret = await runMultipartTest()
|
||||
expect(ret).toMatchObject({
|
||||
url: null,
|
||||
extraData: { response: expect.anything(), bytesUploaded: 17 },
|
||||
})
|
||||
})
|
||||
|
||||
const ret = await runMultipartTest({
|
||||
// @ts-ignore
|
||||
address: `localhost:${server.address().port}`,
|
||||
})
|
||||
expect(ret).toMatchObject({
|
||||
url: null,
|
||||
extraData: { response: expect.anything(), bytesUploaded: 17 },
|
||||
})
|
||||
} finally {
|
||||
server.close()
|
||||
}
|
||||
test('header companion option gets passed along to destination endpoint', async () => {
|
||||
nock('http://localhost')
|
||||
.post('/')
|
||||
.matchHeader('header-a', '1')
|
||||
.matchHeader('header-b', '2')
|
||||
.reply(200, () => '')
|
||||
|
||||
const ret = await runMultipartTest({
|
||||
// @ts-ignore
|
||||
extraCompanionOpts: {
|
||||
uploadHeaders: { 'header-a': '1', 'header-b': '2' },
|
||||
},
|
||||
})
|
||||
expect(ret).toMatchObject({
|
||||
url: null,
|
||||
extraData: { response: expect.anything(), bytesUploaded: 17 },
|
||||
})
|
||||
|
||||
expect(ret.extraData.response?.headers?.['header-a']).toBeUndefined() // headers sent to destination, not received back
|
||||
})
|
||||
|
||||
const formDataNoMetaMatch =
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import nock from 'nock'
|
||||
import request from 'supertest'
|
||||
import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest'
|
||||
import { afterAll, afterEach, describe, expect, test, vi } from 'vitest'
|
||||
|
||||
import { getServer } from './mockserver.js'
|
||||
|
||||
|
|
@ -18,14 +18,15 @@ vi.mock('../src/server/helpers/request.js', async () => {
|
|||
const getMockServer = async () =>
|
||||
getServer({ COMPANION_CLIENT_SOCKET_CONNECT_TIMEOUT: '0' })
|
||||
|
||||
beforeAll(() => {
|
||||
const nockUrl = () =>
|
||||
nock('http://url.myendpoint.com')
|
||||
.get('/files')
|
||||
.reply(200, () => '')
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
afterEach(() => {
|
||||
nock.cleanAll()
|
||||
})
|
||||
afterAll(() => {
|
||||
nock.restore()
|
||||
})
|
||||
|
||||
|
|
@ -52,6 +53,8 @@ describe('url meta', () => {
|
|||
})
|
||||
|
||||
test.each(invalids)('return 400 for invalid url', async (urlCase) => {
|
||||
nockUrl()
|
||||
|
||||
return request(await getMockServer())
|
||||
.post('/url/meta')
|
||||
.set('Content-Type', 'application/json')
|
||||
|
|
@ -65,6 +68,8 @@ describe('url meta', () => {
|
|||
|
||||
describe('url get', () => {
|
||||
test('url download gets instanitated', async () => {
|
||||
nockUrl()
|
||||
|
||||
return request(await getMockServer())
|
||||
.post('/url/get')
|
||||
.set('Content-Type', 'application/json')
|
||||
|
|
@ -80,6 +85,8 @@ describe('url get', () => {
|
|||
test.each(invalids)(
|
||||
'downloads are not instantiated for invalid urls',
|
||||
async (urlCase) => {
|
||||
nockUrl()
|
||||
|
||||
return request(await getMockServer())
|
||||
.post('/url/get')
|
||||
.set('Content-Type', 'application/json')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue