fix(Google Cloud Storage Node): Preserve request headers on object create (#35218)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Elias Meire <elias@meire.dev>
This commit is contained in:
Rushikesh Patil 2026-09-25 14:20:32 +00:00 committed by GitHub
parent d658d182e4
commit bc9faf230a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 59 additions and 3 deletions

View File

@ -362,9 +362,12 @@ export const objectOperations: INodeProperties[] = [
// Without this, names containing '/', spaces, or '#' produce a 404.
requestOptions.url = `/b/${bucketName}/o/${encodeURIComponent(objectName)}`;
requestOptions.qs = projection ? { projection } : {};
requestOptions.headers = this.getNodeParameter(
'encryptionHeaders',
) as IDataObject;
// Merge rather than replace: the service-account preSend has already put the
// bearer token on these headers, and dropping it makes this request anonymous.
requestOptions.headers = {
...requestOptions.headers,
...(this.getNodeParameter('encryptionHeaders') as IDataObject),
};
delete requestOptions.body;
return requestOptions;

View File

@ -326,6 +326,59 @@ describe('Google Cloud Storage - Create object resumable upload (preSend)', () =
expect(result.method).toBe('GET');
expect(result.url).toBe('/b/my-bucket/o/my-object');
});
it('keeps the bearer token on the follow-up metadata request', async () => {
const fileSize = 100;
setupParamsServiceAccount();
assertBinaryData.mockReturnValue({ id: 'binary-id', mimeType: 'image/png' });
getBinaryMetadata.mockResolvedValue({ mimeType: 'image/png', fileSize });
getBinaryStream.mockResolvedValue(Readable.from([Buffer.alloc(fileSize, 'a')]));
httpRequest
.mockResolvedValueOnce({
headers: { location: 'https://storage.googleapis.com/upload/session-sa' },
body: {},
})
.mockResolvedValue({ statusCode: 200 });
const result = await bodySend.call(ctx, {
...baseOptions,
headers: { Authorization: 'Bearer sa-token' },
});
expect(result.headers).toEqual({ Authorization: 'Bearer sa-token' });
});
it('merges encryption headers into the follow-up metadata request', async () => {
const fileSize = 100;
ctx.getNodeParameter
.mockReturnValueOnce('my-object') // objectName → metadata
.mockReturnValueOnce({}) // createData
.mockReturnValueOnce(true) // createFromBinary
.mockReturnValueOnce('data') // createBinaryPropertyName
.mockReturnValueOnce('my-bucket') // bucketName → resumable path
.mockReturnValueOnce('my-object') // objectName → resumable path
.mockReturnValueOnce('serviceAccount') // authentication
.mockReturnValueOnce({ 'x-goog-encryption-algorithm': 'AES256' }); // encryptionHeaders
assertBinaryData.mockReturnValue({ id: 'binary-id', mimeType: 'image/png' });
getBinaryMetadata.mockResolvedValue({ mimeType: 'image/png', fileSize });
getBinaryStream.mockResolvedValue(Readable.from([Buffer.alloc(fileSize, 'a')]));
httpRequest
.mockResolvedValueOnce({
headers: { location: 'https://storage.googleapis.com/upload/session-sa' },
body: {},
})
.mockResolvedValue({ statusCode: 200 });
const result = await bodySend.call(ctx, {
...baseOptions,
headers: { Authorization: 'Bearer sa-token' },
});
expect(result.headers).toEqual({
Authorization: 'Bearer sa-token',
'x-goog-encryption-algorithm': 'AES256',
});
});
});
describe('final GET request', () => {