Hi everyone,
I’ve encountered an issue with handling large numbers in HTTP requests using the HTTP Request node in n8n. Specifically, I’ve noticed that large numbers are being altered due to precision loss. For instance, a number like 997620301473206272
gets changed to 997620301473206300
, which causes problems in my workflow.
The Problem:
When sending HTTP requests, any numeric value larger than Number.MAX_SAFE_INTEGER
(which is 9007199254740991) loses precision. This has led to incorrect data being sent in my requests, which is particularly problematic for IDs or other critical large number values.
Steps I’ve Taken:
To address this, I’ve looked into the HTTP Request node’s code and found a potential solution. I’ve added a function that converts numbers larger than Number.MAX_SAFE_INTEGER
to strings before sending the request. This ensures that the numbers are not altered due to precision issues.
Proposed Solution:
Here’s a brief overview of the changes I made:
- Added a Function to Convert Large Numbers to Strings: The function
convertNumbersToStrings
recursively traverses the data and converts any number exceedingNumber.MAX_SAFE_INTEGER
into a string. - Integrated the Function in the Request Preparation: I updated the
execute
method in theHttpRequestV3
class to call theconvertNumbersToStrings
function before setting therequestOptions.body
.
function convertNumbersToStrings(data: any): any {
if (typeof data === 'number' && data > Number.MAX_SAFE_INTEGER) {
return data.toString();
} else if (Array.isArray(data)) {
return data.map(convertNumbersToStrings);
} else if (typeof data === 'object' && data !== null) {
return Object.fromEntries(
Object.entries(data).map(([key, value]) => [key, convertNumbersToStrings(value)])
);
}
return data;
}
I then used this function within the execute
method to ensure all large numbers are converted before the request is sent.
export class HttpRequestV3 implements INodeType {
// ...
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const nodeVersion = this.getNode().typeVersion;
// ...
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
// ...
const sendBody = this.getNodeParameter('sendBody', itemIndex, false) as boolean;
const bodyContentType = this.getNodeParameter('contentType', itemIndex, '') as string;
const specifyBody = this.getNodeParameter('specifyBody', itemIndex, '') as string;
const bodyParameters = this.getNodeParameter('bodyParameters.parameters', itemIndex, []) as BodyParameter[];
const jsonBodyParameter = this.getNodeParameter('jsonBody', itemIndex, '') as string;
const body = this.getNodeParameter('body', itemIndex, '') as string;
// Get parameters defined in the UI
if (sendBody && bodyParameters) {
if (specifyBody === 'keypair' || bodyContentType === 'multipart-form-data') {
let preparedBody = await prepareRequestBody(bodyParameters, bodyContentType, nodeVersion, parametersToKeyValue);
// Convert large numbers to strings
preparedBody = convertNumbersToStrings(preparedBody);
requestOptions.body = preparedBody;
} else if (specifyBody === 'json') {
if (typeof jsonBodyParameter !== 'object' && jsonBodyParameter !== null) {
try {
JSON.parse(jsonBodyParameter);
} catch {
throw new NodeOperationError(this.getNode(), 'JSON parameter need to be an valid JSON', { itemIndex });
}
let parsedJsonBody = jsonParse(jsonBodyParameter);
parsedJsonBody = convertNumbersToStrings(parsedJsonBody);
requestOptions.body = parsedJsonBody;
} else {
let jsonBody = jsonBodyParameter;
jsonBody = convertNumbersToStrings(jsonBody);
requestOptions.body = jsonBody;
}
} else if (specifyBody === 'string') {
let urlencodedBody = Object.fromEntries(new URLSearchParams(body));
urlencodedBody = convertNumbersToStrings(urlencodedBody);
requestOptions.body = urlencodedBody;
}
}
// ...
}
// ...
}
}
Seeking Feedback and Further Suggestions:
I’m sharing this here to see if anyone else has faced similar issues and to get feedback on this solution. If there’s a more efficient way to handle this within n8n or if there are any potential pitfalls with this approach, I would greatly appreciate your insights.
Thank you!