mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-17 13:39:44 +02:00
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:
parent
d658d182e4
commit
bc9faf230a
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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', () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user