Skip to content

Commit afcdc3d

Browse files
committed
feat: add getAdditionalHeadersCB
Ticket: BG-000000
1 parent 3537128 commit afcdc3d

File tree

3 files changed

+68
-4
lines changed

3 files changed

+68
-4
lines changed

modules/bitgo/test/v2/integration/bitgo.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,4 +634,48 @@ describe('BitGo', function () {
634634
return bitgo.authenticateKnownBalanceTestUser(bitgo.testUserOTP());
635635
});
636636
});
637+
638+
describe('getAdditionalHeadersCb', function () {
639+
let bitgo;
640+
let additionalHeadersCb;
641+
642+
before(function () {
643+
additionalHeadersCb = sinon.spy((method, url, data) => {
644+
return [
645+
{ key: 'X-Custom-Header', value: 'CustomValue' },
646+
{ key: 'X-Another-Header', value: 'AnotherValue' },
647+
];
648+
});
649+
650+
bitgo = new TestBitGo();
651+
bitgo.initializeTestVars();
652+
bitgo = new BitGoJS.BitGo({ getAdditionalHeadersCb: additionalHeadersCb });
653+
});
654+
655+
it('should invoke getAdditionalHeadersCb and apply headers to the request', async function () {
656+
const url = bitgo.url('/test-endpoint');
657+
const method = 'get';
658+
659+
// Mock the request to avoid actual network calls
660+
const mockRequest = sinon.stub(bitgo, 'getAgentRequest').returns({
661+
set: sinon.stub().returnsThis(),
662+
then: sinon.stub().resolves({}),
663+
});
664+
665+
await bitgo.get(url);
666+
667+
// Verify that the callback was called with the correct arguments
668+
sinon.assert.calledOnce(additionalHeadersCb);
669+
sinon.assert.calledWith(additionalHeadersCb, method, url, undefined);
670+
671+
// Verify that the headers were applied to the request
672+
const headers = additionalHeadersCb.returnValues[0];
673+
headers.forEach(({ key, value }) => {
674+
sinon.assert.calledWith(mockRequest().set, key, value);
675+
});
676+
677+
// Restore the stubbed method
678+
mockRequest.restore();
679+
});
680+
});
637681
});

modules/sdk-api/src/bitgoAPI.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
AccessTokenOptions,
4545
AddAccessTokenOptions,
4646
AddAccessTokenResponse,
47+
AdditionalHeadersCallback,
4748
AuthenticateOptions,
4849
AuthenticateWithAuthCodeOptions,
4950
BitGoAPIOptions,
@@ -67,6 +68,7 @@ import {
6768
RegisterPushTokenOptions,
6869
RemoveAccessTokenOptions,
6970
RequestHeaders,
71+
RequestMethods,
7072
SplitSecret,
7173
SplitSecretOptions,
7274
TokenIssuance,
@@ -94,8 +96,6 @@ const PendingApprovals = require('./v1/pendingapprovals');
9496
const TravelRule = require('./v1/travelRule');
9597
const TransactionBuilder = require('./v1/transactionBuilder');
9698

97-
const patchedRequestMethods = ['get', 'post', 'put', 'del', 'patch', 'options'] as const;
98-
9999
export class BitGoAPI implements BitGoBase {
100100
// v1 types
101101
protected _keychains: any;
@@ -130,8 +130,10 @@ export class BitGoAPI implements BitGoBase {
130130
protected _validate: boolean;
131131
public readonly cookiesPropagationEnabled: boolean;
132132
private _customProxyAgent?: Agent;
133+
private getAdditionalHeadersCb?: AdditionalHeadersCallback;
133134

134135
constructor(params: BitGoAPIOptions = {}) {
136+
this.getAdditionalHeadersCb = params.getAdditionalHeadersCb;
135137
this.cookiesPropagationEnabled = false;
136138
if (
137139
!common.validateParams(
@@ -302,7 +304,7 @@ export class BitGoAPI implements BitGoBase {
302304
* @param method - http method for the new request
303305
* @param url - URL for the new request
304306
*/
305-
protected getAgentRequest(method: (typeof patchedRequestMethods)[number], url: string): superagent.SuperAgentRequest {
307+
protected getAgentRequest(method: RequestMethods, url: string): superagent.SuperAgentRequest {
306308
let req: superagent.SuperAgentRequest = superagent[method](url);
307309
if (this.cookiesPropagationEnabled) {
308310
req = req.withCredentials();
@@ -336,7 +338,7 @@ export class BitGoAPI implements BitGoBase {
336338
* headers to any outbound request.
337339
* @param method
338340
*/
339-
private requestPatch(method: (typeof patchedRequestMethods)[number], url: string) {
341+
private requestPatch(method: RequestMethods, url: string) {
340342
const req = this.getAgentRequest(method, url);
341343
if (this._customProxyAgent) {
342344
debug('using custom proxy agent');
@@ -414,6 +416,14 @@ export class BitGoAPI implements BitGoBase {
414416
req.set('HMAC', requestProperties.hmac);
415417
}
416418

419+
if (this.getAdditionalHeadersCb) {
420+
const data = serializeRequestData(req);
421+
const additionalHeaders = this.getAdditionalHeadersCb(method, url, data);
422+
for (const { key, value } of additionalHeaders) {
423+
req.set(key, value);
424+
}
425+
}
426+
417427
/**
418428
* Verify the response before calling the original onfulfilled handler,
419429
* and make sure onrejected is called if a verification error is encountered

modules/sdk-api/src/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import { EnvironmentName, IRequestTracer, V1Network } from '@bitgo/sdk-core';
22
import { ECPairInterface } from '@bitgo/utxo-lib';
33
import { type Agent } from 'http';
4+
5+
const patchedRequestMethods = ['get', 'post', 'put', 'del', 'patch', 'options'] as const;
6+
export type RequestMethods = (typeof patchedRequestMethods)[number];
7+
export type AdditionalHeadersCallback = (
8+
method: RequestMethods,
9+
url: string,
10+
data?: string
11+
) => Array<{ key: string; value: string }>;
12+
413
export {
514
supportedRequestMethods,
615
AuthVersion,
@@ -35,6 +44,7 @@ export interface BitGoAPIOptions {
3544
userAgent?: string;
3645
validate?: boolean;
3746
cookiesPropagationEnabled?: boolean;
47+
getAdditionalHeadersCb?: AdditionalHeadersCallback;
3848
}
3949

4050
export interface AccessTokenOptions {

0 commit comments

Comments
 (0)