From 27a4ed5b753c05e890d785cb642ae522e84d310c Mon Sep 17 00:00:00 2001 From: Thiyagu K Date: Wed, 3 Jun 2026 09:08:33 +0000 Subject: [PATCH 1/3] feat(storage): set Content-Type to application/json in decorateRequest when json is present and header is missing --- handwritten/storage/src/nodejs-common/util.ts | 15 +++++ .../storage/test/nodejs-common/util.ts | 55 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/handwritten/storage/src/nodejs-common/util.ts b/handwritten/storage/src/nodejs-common/util.ts index 34b37c30f6a0..f113fea149ce 100644 --- a/handwritten/storage/src/nodejs-common/util.ts +++ b/handwritten/storage/src/nodejs-common/util.ts @@ -970,6 +970,21 @@ 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') { + if (!(headers as any).has('content-type')) { + (headers as any).set('Content-Type', 'application/json'); + } + } else { + const hasContentType = Object.keys(headers).some( + key => key.toLowerCase() === 'content-type' + ); + if (!hasContentType) { + (headers as any)['Content-Type'] = 'application/json'; + } + } + reqOpts.headers = headers; } 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..d07bea262533 100644 --- a/handwritten/storage/test/nodejs-common/util.ts +++ b/handwritten/storage/test/nodejs-common/util.ts @@ -1805,6 +1805,61 @@ 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', () => { + 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 = { From 92abd5e165b13f60ae2548a22e5b6e5027456fab Mon Sep 17 00:00:00 2001 From: Thiyagu K Date: Wed, 3 Jun 2026 09:21:07 +0000 Subject: [PATCH 2/3] fix(storage): ensure Headers instance supports 'has' method before setting content-type and skip test if Headers is undefined --- handwritten/storage/src/nodejs-common/util.ts | 5 ++++- handwritten/storage/test/nodejs-common/util.ts | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/handwritten/storage/src/nodejs-common/util.ts b/handwritten/storage/src/nodejs-common/util.ts index f113fea149ce..7c4457f64da0 100644 --- a/handwritten/storage/src/nodejs-common/util.ts +++ b/handwritten/storage/src/nodejs-common/util.ts @@ -972,7 +972,10 @@ export class Util { reqOpts.json = replaceProjectIdToken(reqOpts.json, projectId); const headers = reqOpts.headers || {}; - if (typeof (headers as any).set === 'function') { + 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'); } diff --git a/handwritten/storage/test/nodejs-common/util.ts b/handwritten/storage/test/nodejs-common/util.ts index d07bea262533..88e6905ffb52 100644 --- a/handwritten/storage/test/nodejs-common/util.ts +++ b/handwritten/storage/test/nodejs-common/util.ts @@ -1822,6 +1822,9 @@ describe('common/util', () => { }); 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 = { From f505577b3abbff552ee229a8eeec49f39fac993d Mon Sep 17 00:00:00 2001 From: Thiyagu K Date: Wed, 3 Jun 2026 16:16:47 +0530 Subject: [PATCH 3/3] fix: mutating issue Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- handwritten/storage/src/nodejs-common/util.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/handwritten/storage/src/nodejs-common/util.ts b/handwritten/storage/src/nodejs-common/util.ts index 7c4457f64da0..e6c4db98b095 100644 --- a/handwritten/storage/src/nodejs-common/util.ts +++ b/handwritten/storage/src/nodejs-common/util.ts @@ -979,15 +979,15 @@ export class Util { 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' ); - if (!hasContentType) { - (headers as any)['Content-Type'] = 'application/json'; - } + reqOpts.headers = hasContentType + ? headers + : { ...headers, 'Content-Type': 'application/json' }; } - reqOpts.headers = headers; } reqOpts.uri = replaceProjectIdToken(reqOpts.uri, projectId);