Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion packages/nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,18 @@ export class HttpRequestV3 implements INodeType {
};
return accumulator;
}
accumulator[cur.name] = cur.value;

// Handle duplicate parameter names by accumulating them into arrays
if (accumulator[cur.name] === undefined) {
// Key doesn't exist yet → just assign
accumulator[cur.name] = cur.value;
} else if (Array.isArray(accumulator[cur.name])) {
// Key exists and is already array → append
accumulator[cur.name].push(cur.value);
} else {
// Key exists but is not array → convert to array
accumulator[cur.name] = [accumulator[cur.name], cur.value];
}
return accumulator;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,105 @@ describe('HttpRequestV3', () => {
);
});

describe('Query Parameters Handling', () => {
it('should handle duplicate query parameter names by accumulating them into arrays', async () => {
(executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]);
(executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => {
switch (paramName) {
case 'method':
return 'GET';
case 'url':
return baseUrl;
case 'authentication':
return 'none';
case 'sendQuery':
return true;
case 'specifyQuery':
return 'keypair';
case 'queryParameters.parameters':
// Simulate user entering multiple parameters with the same name
return [
{ name: 'q_organization_keyword_tags[]', value: 'financial' },
{ name: 'q_organization_keyword_tags[]', value: 'investment' },
{ name: 'category', value: 'business' }, // single parameter for comparison
{ name: 'q_organization_keyword_tags[]', value: 'banking' }, // third duplicate
];
case 'options':
return options;
default:
return undefined;
}
});

const response = {
headers: { 'content-type': 'application/json' },
body: Buffer.from(JSON.stringify({ success: true })),
};
(executeFunctions.helpers.request as jest.Mock).mockResolvedValue(response);

const result = await node.execute.call(executeFunctions);

// Verify the request was made with proper query parameters
expect(executeFunctions.helpers.request).toHaveBeenCalledWith(
expect.objectContaining({
qs: {
'q_organization_keyword_tags[]': ['financial', 'investment', 'banking'], // Should be an array
category: 'business', // Single value should remain a string
},
}),
);

expect(result).toEqual([[{ json: { success: true }, pairedItem: { item: 0 } }]]);
});

it('should handle single query parameters normally (backward compatibility)', async () => {
(executeFunctions.getInputData as jest.Mock).mockReturnValue([{ json: {} }]);
(executeFunctions.getNodeParameter as jest.Mock).mockImplementation((paramName: string) => {
switch (paramName) {
case 'method':
return 'GET';
case 'url':
return baseUrl;
case 'authentication':
return 'none';
case 'sendQuery':
return true;
case 'specifyQuery':
return 'keypair';
case 'queryParameters.parameters':
return [
{ name: 'category', value: 'business' },
{ name: 'limit', value: '10' },
];
case 'options':
return options;
default:
return undefined;
}
});

const response = {
headers: { 'content-type': 'application/json' },
body: Buffer.from(JSON.stringify({ success: true })),
};
(executeFunctions.helpers.request as jest.Mock).mockResolvedValue(response);

const result = await node.execute.call(executeFunctions);

// Verify single parameters are handled as strings (backward compatibility)
expect(executeFunctions.helpers.request).toHaveBeenCalledWith(
expect.objectContaining({
qs: {
category: 'business',
limit: '10',
},
}),
);

expect(result).toEqual([[{ json: { success: true }, pairedItem: { item: 0 } }]]);
});
});

describe('Authentication Handling', () => {
const authenticationTypes = [
{
Expand Down