Skip to content

Commit 0c8dd19

Browse files
authored
Companion option uploadHeaders (#5981)
closes #5921 also improve tests that currently depend on eachother todo - [x] docs transloadit/uppy.io#394
1 parent 5e166a1 commit 0c8dd19

File tree

10 files changed

+127
-78
lines changed

10 files changed

+127
-78
lines changed

.changeset/nine-rice-brake.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@uppy/companion": patch
3+
---
4+
5+
New Companion option `uploadHeaders` which can be used to include a static set of headers with every request sent to all upload destinations.

packages/@uppy/companion/src/server/Uploader.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,18 @@ export default class Uploader {
148148
* @property {number} [chunkSize]
149149
* @property {string} [providerName]
150150
*
151-
* @param {UploaderOptions} options
151+
* @param {UploaderOptions} optionsIn
152152
*/
153-
constructor(options) {
154-
validateOptions(options)
153+
constructor(optionsIn) {
154+
validateOptions(optionsIn)
155+
156+
const options = {
157+
...optionsIn,
158+
headers: {
159+
...optionsIn.headers,
160+
...optionsIn.companionOptions.uploadHeaders,
161+
},
162+
}
155163

156164
this.providerName = options.providerName
157165
this.options = options
@@ -682,7 +690,7 @@ export default class Uploader {
682690
try {
683691
const httpMethod =
684692
(this.options.httpMethod || '').toUpperCase() === 'PUT' ? 'put' : 'post'
685-
const runRequest = await got[httpMethod]
693+
const runRequest = got[httpMethod]
686694

687695
const response = await runRequest(url, reqOptions)
688696

packages/@uppy/companion/src/standalone/helper.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ const getConfigFromEnv = () => {
215215
process.env.COMPANION_TEST_DYNAMIC_OAUTH_CREDENTIALS === 'true',
216216
testDynamicOauthCredentialsSecret:
217217
process.env.COMPANION_TEST_DYNAMIC_OAUTH_CREDENTIALS_SECRET,
218+
uploadHeaders: process.env.COMPANION_UPLOAD_HEADERS
219+
? JSON.parse(process.env.COMPANION_UPLOAD_HEADERS)
220+
: undefined,
218221
}
219222
}
220223

packages/@uppy/companion/test/companion.test.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import nock from 'nock'
22
import request from 'supertest'
3-
import { afterAll, describe, expect, it, test, vi } from 'vitest'
3+
import { afterAll, afterEach, describe, expect, it, test, vi } from 'vitest'
44
import packageJson from '../package.json' with { type: 'json' }
55
import * as tokenService from '../src/server/helpers/jwt.js'
66
import * as defaults from './fixtures/constants.js'
@@ -37,8 +37,10 @@ const authData = {
3737
const token = tokenService.generateEncryptedAuthToken(authData, secret)
3838
const OAUTH_STATE = 'some-cool-nice-encrytpion'
3939

40-
afterAll(() => {
40+
afterEach(() => {
4141
nock.cleanAll()
42+
})
43+
afterAll(() => {
4244
nock.restore()
4345
})
4446

packages/@uppy/companion/test/credentials.test.js

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import nock from 'nock'
22
import request from 'supertest'
3-
import { afterAll, describe, expect, test, vi } from 'vitest'
3+
import {
4+
afterAll,
5+
afterEach,
6+
beforeEach,
7+
describe,
8+
expect,
9+
test,
10+
vi,
11+
} from 'vitest'
412
import * as tokenService from '../src/server/helpers/jwt.js'
513
import { nockZoomRevoke, expects as zoomExpects } from './fixtures/zoom.js'
614
import { getServer } from './mockserver.js'
@@ -21,32 +29,35 @@ const authData = {
2129
}
2230
const token = tokenService.generateEncryptedAuthToken(authData, secret)
2331

24-
afterAll(() => {
32+
afterEach(() => {
2533
nock.cleanAll()
34+
})
35+
afterAll(() => {
2636
nock.restore()
2737
})
2838

2939
describe('providers requests with remote oauth keys', () => {
30-
// mocking request module used to fetch custom oauth credentials
31-
nock('http://localhost:2111')
32-
.post('/zoom-keys')
33-
// @ts-ignore
34-
.reply((uri, { provider, parameters }) => {
35-
if (provider !== 'zoom' || parameters !== 'ZOOM-CREDENTIALS-PARAMS')
36-
return [400]
40+
beforeEach(() => {
41+
// mocking request module used to fetch custom oauth credentials
42+
nock('http://localhost:2111')
43+
.post('/zoom-keys')
44+
// @ts-ignore
45+
.reply((uri, { provider, parameters }) => {
46+
if (provider !== 'zoom' || parameters !== 'ZOOM-CREDENTIALS-PARAMS')
47+
return [400]
3748

38-
return [
39-
200,
40-
{
41-
credentials: {
42-
key: remoteZoomKey,
43-
secret: remoteZoomSecret,
44-
verificationToken: remoteZoomVerificationToken,
49+
return [
50+
200,
51+
{
52+
credentials: {
53+
key: remoteZoomKey,
54+
secret: remoteZoomSecret,
55+
verificationToken: remoteZoomVerificationToken,
56+
},
4557
},
46-
},
47-
]
48-
})
49-
.persist()
58+
]
59+
})
60+
})
5061

5162
test('zoom logout with remote oauth keys happy path', async () => {
5263
nockZoomRevoke({ key: remoteZoomKey, secret: remoteZoomSecret })
@@ -69,6 +80,8 @@ describe('providers requests with remote oauth keys', () => {
6980
})
7081

7182
test('zoom logout with wrong credentials params', async () => {
83+
nockZoomRevoke({ key: remoteZoomKey, secret: remoteZoomSecret })
84+
7285
const params = { params: 'WRONG-ZOOM-CREDENTIALS-PARAMS' }
7386
const encodedParams = Buffer.from(
7487
JSON.stringify(params),

packages/@uppy/companion/test/deauthorization.test.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
import nock from 'nock'
22
import request from 'supertest'
3-
import { afterAll, describe, test, vi } from 'vitest'
3+
import { afterAll, afterEach, beforeEach, describe, test, vi } from 'vitest'
44
import { getServer } from './mockserver.js'
55

66
vi.mock('express-prom-bundle')
77

8-
afterAll(() => {
8+
afterEach(() => {
99
nock.cleanAll()
10+
})
11+
afterAll(() => {
1012
nock.restore()
1113
})
1214

1315
describe('handle deauthorization callback', () => {
14-
nock('https://api.zoom.us').post('/oauth/data/compliance').reply(200)
16+
beforeEach(() => {
17+
nock('https://api.zoom.us').post('/oauth/data/compliance').reply(200)
18+
})
1519

1620
test('providers without support for callback endpoint', async () => {
1721
return request(await getServer())

packages/@uppy/companion/test/http-agent.test.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import nock from 'nock'
2-
import { afterAll, describe, expect, test } from 'vitest'
2+
import { afterAll, afterEach, describe, expect, test } from 'vitest'
33
import {
44
FORBIDDEN_IP_ADDRESS,
55
getProtectedGot,
66
} from '../src/server/helpers/request.js'
77

8-
afterAll(() => {
8+
afterEach(() => {
99
nock.cleanAll()
10+
})
11+
afterAll(() => {
1012
nock.restore()
1113
})
1214

packages/@uppy/companion/test/providers.test.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import nock from 'nock'
22
import request from 'supertest'
3-
import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest'
3+
import {
4+
afterAll,
5+
afterEach,
6+
beforeEach,
7+
describe,
8+
expect,
9+
test,
10+
vi,
11+
} from 'vitest'
412
import * as tokenService from '../src/server/helpers/jwt.js'
513
import * as providerModule from '../src/server/provider/index.js'
614
import * as defaults from './fixtures/constants.js'
@@ -76,16 +84,17 @@ function nockGetCurrentAccount(times = 1) {
7684
})
7785
}
7886

79-
beforeAll(() => {
87+
beforeEach(() => {
8088
const url = new URL(defaults.THUMBNAIL_URL)
8189
nock(url.origin)
8290
.get(url.pathname)
8391
.reply(200, () => '')
84-
.persist()
8592
})
8693

87-
afterAll(() => {
94+
afterEach(() => {
8895
nock.cleanAll()
96+
})
97+
afterAll(() => {
8998
nock.restore()
9099
})
91100

@@ -543,13 +552,6 @@ describe('logout of provider', () => {
543552
await runTest('box')
544553
})
545554

546-
test('dropbox', async () => {
547-
nock('https://api.dropboxapi.com')
548-
.post('/2/auth/token/revoke')
549-
.reply(200, {})
550-
await runTest('dropbox')
551-
})
552-
553555
test('drive', async () => {
554556
nock('https://accounts.google.com')
555557
.post('/o/oauth2/revoke?token=token+value')

packages/@uppy/companion/test/uploader.test.js

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
import { once } from 'node:events'
21
import fs from 'node:fs'
3-
import { createServer } from 'node:http'
42
import { Readable } from 'node:stream'
53
import nock from 'nock'
6-
import { afterAll, describe, expect, test, vi } from 'vitest'
4+
import { afterAll, afterEach, describe, expect, test, vi } from 'vitest'
75
import Emitter from '../src/server/emitter/index.js'
86
import Uploader, { ValidationError } from '../src/server/Uploader.js'
97
import standalone from '../src/standalone/index.js'
@@ -12,8 +10,10 @@ import * as socketClient from './mocksocket.js'
1210
vi.mock('tus-js-client')
1311
vi.mock('express-prom-bundle')
1412

15-
afterAll(() => {
13+
afterEach(() => {
1614
nock.cleanAll()
15+
})
16+
afterAll(() => {
1717
nock.restore()
1818
})
1919

@@ -24,7 +24,7 @@ const { companionOptions } = standalone()
2424

2525
const mockReq = {}
2626

27-
describe('uploader with tus protocol', () => {
27+
describe('uploader', () => {
2828
test('uploader respects uploadUrls', async () => {
2929
const opts = {
3030
endpoint: 'http://localhost/files',
@@ -207,12 +207,14 @@ describe('uploader with tus protocol', () => {
207207
useFormData,
208208
includeSize = true,
209209
address = 'localhost',
210+
// @ts-ignore
211+
extraCompanionOpts,
210212
} = {}) {
211213
const fileContent = Buffer.from('Some file content')
212214
const stream = Readable.from([fileContent])
213215

214216
const opts = {
215-
companionOptions,
217+
companionOptions: { ...companionOptions, ...extraCompanionOpts },
216218
endpoint: `http://${address}`,
217219
protocol: 'multipart',
218220
size: includeSize ? fileContent.length : undefined,
@@ -227,32 +229,33 @@ describe('uploader with tus protocol', () => {
227229
}
228230

229231
test('upload functions with xhr protocol', async () => {
230-
let alreadyCalled = false
231-
// We are creating our own test server for this test
232-
// instead of using nock because of a bug when passing a Node.js stream to got.
233-
// Ref: https://github.com/nock/nock/issues/2595
234-
const server = createServer((req, res) => {
235-
if (alreadyCalled) throw new Error('already called')
236-
alreadyCalled = true
237-
if (req.url === '/' && req.method === 'POST') {
238-
res.writeHead(200)
239-
res.end('OK')
240-
}
241-
}).listen()
242-
try {
243-
await once(server, 'listening')
244-
245-
const ret = await runMultipartTest({
246-
// @ts-ignore
247-
address: `localhost:${server.address().port}`,
248-
})
249-
expect(ret).toMatchObject({
250-
url: null,
251-
extraData: { response: expect.anything(), bytesUploaded: 17 },
252-
})
253-
} finally {
254-
server.close()
255-
}
232+
nock('http://localhost').post('/').reply(200, 'OK')
233+
const ret = await runMultipartTest()
234+
expect(ret).toMatchObject({
235+
url: null,
236+
extraData: { response: expect.anything(), bytesUploaded: 17 },
237+
})
238+
})
239+
240+
test('header companion option gets passed along to destination endpoint', async () => {
241+
nock('http://localhost')
242+
.post('/')
243+
.matchHeader('header-a', '1')
244+
.matchHeader('header-b', '2')
245+
.reply(200, () => '')
246+
247+
const ret = await runMultipartTest({
248+
// @ts-ignore
249+
extraCompanionOpts: {
250+
uploadHeaders: { 'header-a': '1', 'header-b': '2' },
251+
},
252+
})
253+
expect(ret).toMatchObject({
254+
url: null,
255+
extraData: { response: expect.anything(), bytesUploaded: 17 },
256+
})
257+
258+
expect(ret.extraData.response?.headers?.['header-a']).toBeUndefined() // headers sent to destination, not received back
256259
})
257260

258261
const formDataNoMetaMatch =

0 commit comments

Comments
 (0)