diff --git a/handwritten/storage/src/nodejs-common/util.ts b/handwritten/storage/src/nodejs-common/util.ts index 34b37c30f6a0..e6c4db98b095 100644 --- a/handwritten/storage/src/nodejs-common/util.ts +++ b/handwritten/storage/src/nodejs-common/util.ts @@ -970,6 +970,24 @@ export class Util { delete reqOpts.json.autoPaginate; delete reqOpts.json.autoPaginateVal; reqOpts.json = replaceProjectIdToken(reqOpts.json, projectId); + + const headers = reqOpts.headers || {}; + if ( + typeof (headers as any).set === 'function' && + typeof (headers as any).has === 'function' + ) { + if (!(headers as any).has('content-type')) { + (headers as any).set('Content-Type', 'application/json'); + } + reqOpts.headers = headers; + } else { + const hasContentType = Object.keys(headers).some( + key => key.toLowerCase() === 'content-type' + ); + reqOpts.headers = hasContentType + ? headers + : { ...headers, 'Content-Type': 'application/json' }; + } } reqOpts.uri = replaceProjectIdToken(reqOpts.uri, projectId); diff --git a/handwritten/storage/test/nodejs-common/util.ts b/handwritten/storage/test/nodejs-common/util.ts index 3efc73d11d6c..88e6905ffb52 100644 --- a/handwritten/storage/test/nodejs-common/util.ts +++ b/handwritten/storage/test/nodejs-common/util.ts @@ -1805,6 +1805,64 @@ describe('common/util', () => { assert.deepStrictEqual(decoratedRequest.json, decoratedJson); }); + it('should set Content-Type header on plain headers object when json is set', () => { + const projectId = 'project-id'; + const reqOpts = { + uri: 'http://', + json: {}, + headers: {}, + }; + replaceProjectIdTokenOverride = (x: any) => x; + + const decoratedRequest = util.decorateRequest(reqOpts, projectId); + assert.strictEqual( + (decoratedRequest.headers as any)['Content-Type'], + 'application/json' + ); + }); + + it('should set Content-Type header on Headers instance when json is set', () => { + if (typeof Headers === 'undefined') { + return; + } + const projectId = 'project-id'; + const headersInstance = new Headers(); + const reqOpts = { + uri: 'http://', + json: {}, + headers: headersInstance, + }; + replaceProjectIdTokenOverride = (x: any) => x; + + const decoratedRequest = util.decorateRequest(reqOpts as any, projectId); + assert.strictEqual( + (decoratedRequest.headers as any).get('Content-Type'), + 'application/json' + ); + }); + + it('should not overwrite existing Content-Type header if already present', () => { + const projectId = 'project-id'; + const reqOpts = { + uri: 'http://', + json: {}, + headers: { + 'content-type': 'application/x-protobuf', + }, + }; + replaceProjectIdTokenOverride = (x: any) => x; + + const decoratedRequest = util.decorateRequest(reqOpts, projectId); + assert.strictEqual( + (decoratedRequest.headers as any)['content-type'], + 'application/x-protobuf' + ); + assert.strictEqual( + (decoratedRequest.headers as any)['Content-Type'], + undefined + ); + }); + it('should decorate the request', () => { const projectId = 'project-id'; const reqOpts = {