n8n-nodes-base 1.68.0 → 1.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/build.tsbuildinfo +1 -1
  2. package/dist/nodes/ExecuteWorkflow/ExecuteWorkflow.node.js +53 -6
  3. package/dist/nodes/ExecuteWorkflow/ExecuteWorkflow.node.js.map +1 -1
  4. package/dist/nodes/Files/ReadWriteFile/actions/read.operation.js +1 -0
  5. package/dist/nodes/Files/ReadWriteFile/actions/read.operation.js.map +1 -1
  6. package/dist/nodes/Files/ReadWriteFile/helpers/utils.d.ts +1 -0
  7. package/dist/nodes/Files/ReadWriteFile/helpers/utils.js +5 -0
  8. package/dist/nodes/Files/ReadWriteFile/helpers/utils.js.map +1 -1
  9. package/dist/nodes/Form/Form.node.js +26 -16
  10. package/dist/nodes/Form/Form.node.js.map +1 -1
  11. package/dist/nodes/Form/interfaces.d.ts +6 -0
  12. package/dist/nodes/Form/interfaces.js.map +1 -1
  13. package/dist/nodes/Google/GenericFunctions.d.ts +2 -1
  14. package/dist/nodes/Google/GenericFunctions.js +12 -0
  15. package/dist/nodes/Google/GenericFunctions.js.map +1 -1
  16. package/dist/nodes/Google/Sheet/GoogleSheetsTrigger.node.js +2 -2
  17. package/dist/nodes/Google/Sheet/GoogleSheetsTrigger.node.js.map +1 -1
  18. package/dist/nodes/Google/Sheet/v2/actions/sheet/Sheet.resource.js +2 -2
  19. package/dist/nodes/Google/Sheet/v2/actions/sheet/Sheet.resource.js.map +1 -1
  20. package/dist/nodes/Google/YouTube/YouTube.node.js +3 -15
  21. package/dist/nodes/Google/YouTube/YouTube.node.js.map +1 -1
  22. package/dist/nodes/Google/constants.d.ts +1 -0
  23. package/dist/nodes/Google/constants.js +2 -1
  24. package/dist/nodes/Google/constants.js.map +1 -1
  25. package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.js +366 -343
  26. package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.js.map +1 -1
  27. package/dist/nodes/HttpRequest/test/node/workflow.use_error_output.json +97 -0
  28. package/dist/nodes/Merge/v2/utils.d.ts +6 -0
  29. package/dist/nodes/Merge/v3/helpers/utils.d.ts +6 -0
  30. package/dist/types/nodes.json +4 -4
  31. package/package.json +4 -4
@@ -64,6 +64,7 @@ class HttpRequestV3 {
64
64
  uri: '',
65
65
  };
66
66
  let returnItems = [];
67
+ const errorItems = {};
67
68
  const requestPromises = [];
68
69
  let fullResponse = false;
69
70
  let autoDetectResponseFormat = false;
@@ -72,400 +73,415 @@ class HttpRequestV3 {
72
73
  });
73
74
  const requests = [];
74
75
  for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
75
- if (authentication === 'genericCredentialType') {
76
- genericCredentialType = this.getNodeParameter('genericAuthType', 0);
77
- if (genericCredentialType === 'httpBasicAuth') {
78
- httpBasicAuth = await this.getCredentials('httpBasicAuth', itemIndex);
76
+ try {
77
+ if (authentication === 'genericCredentialType') {
78
+ genericCredentialType = this.getNodeParameter('genericAuthType', 0);
79
+ if (genericCredentialType === 'httpBasicAuth') {
80
+ httpBasicAuth = await this.getCredentials('httpBasicAuth', itemIndex);
81
+ }
82
+ else if (genericCredentialType === 'httpDigestAuth') {
83
+ httpDigestAuth = await this.getCredentials('httpDigestAuth', itemIndex);
84
+ }
85
+ else if (genericCredentialType === 'httpHeaderAuth') {
86
+ httpHeaderAuth = await this.getCredentials('httpHeaderAuth', itemIndex);
87
+ }
88
+ else if (genericCredentialType === 'httpQueryAuth') {
89
+ httpQueryAuth = await this.getCredentials('httpQueryAuth', itemIndex);
90
+ }
91
+ else if (genericCredentialType === 'httpCustomAuth') {
92
+ httpCustomAuth = await this.getCredentials('httpCustomAuth', itemIndex);
93
+ }
94
+ else if (genericCredentialType === 'oAuth1Api') {
95
+ oAuth1Api = await this.getCredentials('oAuth1Api', itemIndex);
96
+ }
97
+ else if (genericCredentialType === 'oAuth2Api') {
98
+ oAuth2Api = await this.getCredentials('oAuth2Api', itemIndex);
99
+ }
79
100
  }
80
- else if (genericCredentialType === 'httpDigestAuth') {
81
- httpDigestAuth = await this.getCredentials('httpDigestAuth', itemIndex);
101
+ else if (authentication === 'predefinedCredentialType') {
102
+ nodeCredentialType = this.getNodeParameter('nodeCredentialType', itemIndex);
103
+ }
104
+ const provideSslCertificates = this.getNodeParameter('provideSslCertificates', itemIndex, false);
105
+ if (provideSslCertificates) {
106
+ sslCertificates = await this.getCredentials('httpSslAuth', itemIndex);
107
+ }
108
+ const requestMethod = this.getNodeParameter('method', itemIndex);
109
+ const sendQuery = this.getNodeParameter('sendQuery', itemIndex, false);
110
+ const queryParameters = this.getNodeParameter('queryParameters.parameters', itemIndex, []);
111
+ const specifyQuery = this.getNodeParameter('specifyQuery', itemIndex, 'keypair');
112
+ const jsonQueryParameter = this.getNodeParameter('jsonQuery', itemIndex, '');
113
+ const sendBody = this.getNodeParameter('sendBody', itemIndex, false);
114
+ const bodyContentType = this.getNodeParameter('contentType', itemIndex, '');
115
+ const specifyBody = this.getNodeParameter('specifyBody', itemIndex, '');
116
+ const bodyParameters = this.getNodeParameter('bodyParameters.parameters', itemIndex, []);
117
+ const jsonBodyParameter = this.getNodeParameter('jsonBody', itemIndex, '');
118
+ const body = this.getNodeParameter('body', itemIndex, '');
119
+ const sendHeaders = this.getNodeParameter('sendHeaders', itemIndex, false);
120
+ const headerParameters = this.getNodeParameter('headerParameters.parameters', itemIndex, []);
121
+ const specifyHeaders = this.getNodeParameter('specifyHeaders', itemIndex, 'keypair');
122
+ const jsonHeadersParameter = this.getNodeParameter('jsonHeaders', itemIndex, '');
123
+ const { redirect, batching, proxy, timeout, allowUnauthorizedCerts, queryParameterArrays, response, lowercaseHeaders, } = this.getNodeParameter('options', itemIndex, {});
124
+ const url = this.getNodeParameter('url', itemIndex);
125
+ const responseFormat = response?.response?.responseFormat || 'autodetect';
126
+ fullResponse = response?.response?.fullResponse || false;
127
+ autoDetectResponseFormat = responseFormat === 'autodetect';
128
+ const batchSize = batching?.batch?.batchSize > 0 ? batching?.batch?.batchSize : 1;
129
+ const batchInterval = batching?.batch.batchInterval;
130
+ if (itemIndex > 0 && batchSize >= 0 && batchInterval > 0) {
131
+ if (itemIndex % batchSize === 0) {
132
+ await (0, n8n_workflow_1.sleep)(batchInterval);
133
+ }
82
134
  }
83
- else if (genericCredentialType === 'httpHeaderAuth') {
84
- httpHeaderAuth = await this.getCredentials('httpHeaderAuth', itemIndex);
135
+ requestOptions = {
136
+ headers: {},
137
+ method: requestMethod,
138
+ uri: url,
139
+ gzip: true,
140
+ rejectUnauthorized: !allowUnauthorizedCerts || false,
141
+ followRedirect: false,
142
+ resolveWithFullResponse: true,
143
+ };
144
+ if (requestOptions.method !== 'GET' && nodeVersion >= 4.1) {
145
+ requestOptions = { ...requestOptions, followAllRedirects: false };
85
146
  }
86
- else if (genericCredentialType === 'httpQueryAuth') {
87
- httpQueryAuth = await this.getCredentials('httpQueryAuth', itemIndex);
147
+ const defaultRedirect = nodeVersion >= 4 && redirect === undefined;
148
+ if (redirect?.redirect?.followRedirects || defaultRedirect) {
149
+ requestOptions.followRedirect = true;
150
+ requestOptions.followAllRedirects = true;
88
151
  }
89
- else if (genericCredentialType === 'httpCustomAuth') {
90
- httpCustomAuth = await this.getCredentials('httpCustomAuth', itemIndex);
152
+ if (redirect?.redirect?.maxRedirects || defaultRedirect) {
153
+ requestOptions.maxRedirects = redirect?.redirect?.maxRedirects;
91
154
  }
92
- else if (genericCredentialType === 'oAuth1Api') {
93
- oAuth1Api = await this.getCredentials('oAuth1Api', itemIndex);
155
+ if (response?.response?.neverError) {
156
+ requestOptions.simple = false;
94
157
  }
95
- else if (genericCredentialType === 'oAuth2Api') {
96
- oAuth2Api = await this.getCredentials('oAuth2Api', itemIndex);
158
+ if (proxy) {
159
+ requestOptions.proxy = proxy;
97
160
  }
98
- }
99
- else if (authentication === 'predefinedCredentialType') {
100
- nodeCredentialType = this.getNodeParameter('nodeCredentialType', itemIndex);
101
- }
102
- const provideSslCertificates = this.getNodeParameter('provideSslCertificates', itemIndex, false);
103
- if (provideSslCertificates) {
104
- sslCertificates = await this.getCredentials('httpSslAuth', itemIndex);
105
- }
106
- const requestMethod = this.getNodeParameter('method', itemIndex);
107
- const sendQuery = this.getNodeParameter('sendQuery', itemIndex, false);
108
- const queryParameters = this.getNodeParameter('queryParameters.parameters', itemIndex, []);
109
- const specifyQuery = this.getNodeParameter('specifyQuery', itemIndex, 'keypair');
110
- const jsonQueryParameter = this.getNodeParameter('jsonQuery', itemIndex, '');
111
- const sendBody = this.getNodeParameter('sendBody', itemIndex, false);
112
- const bodyContentType = this.getNodeParameter('contentType', itemIndex, '');
113
- const specifyBody = this.getNodeParameter('specifyBody', itemIndex, '');
114
- const bodyParameters = this.getNodeParameter('bodyParameters.parameters', itemIndex, []);
115
- const jsonBodyParameter = this.getNodeParameter('jsonBody', itemIndex, '');
116
- const body = this.getNodeParameter('body', itemIndex, '');
117
- const sendHeaders = this.getNodeParameter('sendHeaders', itemIndex, false);
118
- const headerParameters = this.getNodeParameter('headerParameters.parameters', itemIndex, []);
119
- const specifyHeaders = this.getNodeParameter('specifyHeaders', itemIndex, 'keypair');
120
- const jsonHeadersParameter = this.getNodeParameter('jsonHeaders', itemIndex, '');
121
- const { redirect, batching, proxy, timeout, allowUnauthorizedCerts, queryParameterArrays, response, lowercaseHeaders, } = this.getNodeParameter('options', itemIndex, {});
122
- const url = this.getNodeParameter('url', itemIndex);
123
- const responseFormat = response?.response?.responseFormat || 'autodetect';
124
- fullResponse = response?.response?.fullResponse || false;
125
- autoDetectResponseFormat = responseFormat === 'autodetect';
126
- const batchSize = batching?.batch?.batchSize > 0 ? batching?.batch?.batchSize : 1;
127
- const batchInterval = batching?.batch.batchInterval;
128
- if (itemIndex > 0 && batchSize >= 0 && batchInterval > 0) {
129
- if (itemIndex % batchSize === 0) {
130
- await (0, n8n_workflow_1.sleep)(batchInterval);
161
+ if (timeout) {
162
+ requestOptions.timeout = timeout;
131
163
  }
132
- }
133
- requestOptions = {
134
- headers: {},
135
- method: requestMethod,
136
- uri: url,
137
- gzip: true,
138
- rejectUnauthorized: !allowUnauthorizedCerts || false,
139
- followRedirect: false,
140
- resolveWithFullResponse: true,
141
- };
142
- if (requestOptions.method !== 'GET' && nodeVersion >= 4.1) {
143
- requestOptions = { ...requestOptions, followAllRedirects: false };
144
- }
145
- const defaultRedirect = nodeVersion >= 4 && redirect === undefined;
146
- if (redirect?.redirect?.followRedirects || defaultRedirect) {
147
- requestOptions.followRedirect = true;
148
- requestOptions.followAllRedirects = true;
149
- }
150
- if (redirect?.redirect?.maxRedirects || defaultRedirect) {
151
- requestOptions.maxRedirects = redirect?.redirect?.maxRedirects;
152
- }
153
- if (response?.response?.neverError) {
154
- requestOptions.simple = false;
155
- }
156
- if (proxy) {
157
- requestOptions.proxy = proxy;
158
- }
159
- if (timeout) {
160
- requestOptions.timeout = timeout;
161
- }
162
- else {
163
- requestOptions.timeout = 300_000;
164
- }
165
- if (sendQuery && queryParameterArrays) {
166
- Object.assign(requestOptions, {
167
- qsStringifyOptions: { arrayFormat: queryParameterArrays },
168
- });
169
- }
170
- const parametersToKeyValue = async (accumulator, cur) => {
171
- if (cur.parameterType === 'formBinaryData') {
172
- if (!cur.inputDataFieldName)
164
+ else {
165
+ requestOptions.timeout = 300_000;
166
+ }
167
+ if (sendQuery && queryParameterArrays) {
168
+ Object.assign(requestOptions, {
169
+ qsStringifyOptions: { arrayFormat: queryParameterArrays },
170
+ });
171
+ }
172
+ const parametersToKeyValue = async (accumulator, cur) => {
173
+ if (cur.parameterType === 'formBinaryData') {
174
+ if (!cur.inputDataFieldName)
175
+ return accumulator;
176
+ const binaryData = this.helpers.assertBinaryData(itemIndex, cur.inputDataFieldName);
177
+ let uploadData;
178
+ const itemBinaryData = items[itemIndex].binary[cur.inputDataFieldName];
179
+ if (itemBinaryData.id) {
180
+ uploadData = await this.helpers.getBinaryStream(itemBinaryData.id);
181
+ }
182
+ else {
183
+ uploadData = Buffer.from(itemBinaryData.data, n8n_workflow_1.BINARY_ENCODING);
184
+ }
185
+ accumulator[cur.name] = {
186
+ value: uploadData,
187
+ options: {
188
+ filename: binaryData.fileName,
189
+ contentType: binaryData.mimeType,
190
+ },
191
+ };
173
192
  return accumulator;
174
- const binaryData = this.helpers.assertBinaryData(itemIndex, cur.inputDataFieldName);
175
- let uploadData;
176
- const itemBinaryData = items[itemIndex].binary[cur.inputDataFieldName];
177
- if (itemBinaryData.id) {
178
- uploadData = await this.helpers.getBinaryStream(itemBinaryData.id);
179
- }
180
- else {
181
- uploadData = Buffer.from(itemBinaryData.data, n8n_workflow_1.BINARY_ENCODING);
182
193
  }
183
- accumulator[cur.name] = {
184
- value: uploadData,
185
- options: {
186
- filename: binaryData.fileName,
187
- contentType: binaryData.mimeType,
188
- },
189
- };
194
+ accumulator[cur.name] = cur.value;
190
195
  return accumulator;
196
+ };
197
+ if (sendBody && bodyParameters) {
198
+ if (specifyBody === 'keypair' || bodyContentType === 'multipart-form-data') {
199
+ requestOptions.body = await (0, GenericFunctions_1.prepareRequestBody)(bodyParameters, bodyContentType, nodeVersion, parametersToKeyValue);
200
+ }
201
+ else if (specifyBody === 'json') {
202
+ if (typeof jsonBodyParameter !== 'object' && jsonBodyParameter !== null) {
203
+ try {
204
+ JSON.parse(jsonBodyParameter);
205
+ }
206
+ catch {
207
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'JSON parameter needs to be valid JSON', {
208
+ itemIndex,
209
+ });
210
+ }
211
+ requestOptions.body = (0, n8n_workflow_1.jsonParse)(jsonBodyParameter);
212
+ }
213
+ else {
214
+ requestOptions.body = jsonBodyParameter;
215
+ }
216
+ }
217
+ else if (specifyBody === 'string') {
218
+ requestOptions.body = Object.fromEntries(new URLSearchParams(body));
219
+ }
191
220
  }
192
- accumulator[cur.name] = cur.value;
193
- return accumulator;
194
- };
195
- if (sendBody && bodyParameters) {
196
- if (specifyBody === 'keypair' || bodyContentType === 'multipart-form-data') {
197
- requestOptions.body = await (0, GenericFunctions_1.prepareRequestBody)(bodyParameters, bodyContentType, nodeVersion, parametersToKeyValue);
221
+ if (sendBody && ['PATCH', 'POST', 'PUT', 'GET'].includes(requestMethod)) {
222
+ if (bodyContentType === 'multipart-form-data') {
223
+ requestOptions.formData = requestOptions.body;
224
+ delete requestOptions.body;
225
+ }
226
+ else if (bodyContentType === 'form-urlencoded') {
227
+ requestOptions.form = requestOptions.body;
228
+ delete requestOptions.body;
229
+ }
230
+ else if (bodyContentType === 'binaryData') {
231
+ const inputDataFieldName = this.getNodeParameter('inputDataFieldName', itemIndex);
232
+ let uploadData;
233
+ let contentLength;
234
+ const itemBinaryData = this.helpers.assertBinaryData(itemIndex, inputDataFieldName);
235
+ if (itemBinaryData.id) {
236
+ uploadData = await this.helpers.getBinaryStream(itemBinaryData.id);
237
+ const metadata = await this.helpers.getBinaryMetadata(itemBinaryData.id);
238
+ contentLength = metadata.fileSize;
239
+ }
240
+ else {
241
+ uploadData = Buffer.from(itemBinaryData.data, n8n_workflow_1.BINARY_ENCODING);
242
+ contentLength = uploadData.length;
243
+ }
244
+ requestOptions.body = uploadData;
245
+ requestOptions.headers = {
246
+ ...requestOptions.headers,
247
+ 'content-length': contentLength,
248
+ 'content-type': itemBinaryData.mimeType ?? 'application/octet-stream',
249
+ };
250
+ }
251
+ else if (bodyContentType === 'raw') {
252
+ requestOptions.body = body;
253
+ }
198
254
  }
199
- else if (specifyBody === 'json') {
200
- if (typeof jsonBodyParameter !== 'object' && jsonBodyParameter !== null) {
255
+ if (sendQuery && queryParameters) {
256
+ if (specifyQuery === 'keypair') {
257
+ requestOptions.qs = await (0, GenericFunctions_1.reduceAsync)(queryParameters, parametersToKeyValue);
258
+ }
259
+ else if (specifyQuery === 'json') {
201
260
  try {
202
- JSON.parse(jsonBodyParameter);
261
+ JSON.parse(jsonQueryParameter);
203
262
  }
204
263
  catch {
205
264
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'JSON parameter needs to be valid JSON', {
206
265
  itemIndex,
207
266
  });
208
267
  }
209
- requestOptions.body = (0, n8n_workflow_1.jsonParse)(jsonBodyParameter);
210
- }
211
- else {
212
- requestOptions.body = jsonBodyParameter;
268
+ requestOptions.qs = (0, n8n_workflow_1.jsonParse)(jsonQueryParameter);
213
269
  }
214
270
  }
215
- else if (specifyBody === 'string') {
216
- requestOptions.body = Object.fromEntries(new URLSearchParams(body));
217
- }
218
- }
219
- if (sendBody && ['PATCH', 'POST', 'PUT', 'GET'].includes(requestMethod)) {
220
- if (bodyContentType === 'multipart-form-data') {
221
- requestOptions.formData = requestOptions.body;
222
- delete requestOptions.body;
223
- }
224
- else if (bodyContentType === 'form-urlencoded') {
225
- requestOptions.form = requestOptions.body;
226
- delete requestOptions.body;
227
- }
228
- else if (bodyContentType === 'binaryData') {
229
- const inputDataFieldName = this.getNodeParameter('inputDataFieldName', itemIndex);
230
- let uploadData;
231
- let contentLength;
232
- const itemBinaryData = this.helpers.assertBinaryData(itemIndex, inputDataFieldName);
233
- if (itemBinaryData.id) {
234
- uploadData = await this.helpers.getBinaryStream(itemBinaryData.id);
235
- const metadata = await this.helpers.getBinaryMetadata(itemBinaryData.id);
236
- contentLength = metadata.fileSize;
271
+ if (sendHeaders && headerParameters) {
272
+ let additionalHeaders = {};
273
+ if (specifyHeaders === 'keypair') {
274
+ additionalHeaders = await (0, GenericFunctions_1.reduceAsync)(headerParameters.filter((header) => header.name), parametersToKeyValue);
237
275
  }
238
- else {
239
- uploadData = Buffer.from(itemBinaryData.data, n8n_workflow_1.BINARY_ENCODING);
240
- contentLength = uploadData.length;
276
+ else if (specifyHeaders === 'json') {
277
+ try {
278
+ JSON.parse(jsonHeadersParameter);
279
+ }
280
+ catch {
281
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'JSON parameter needs to be valid JSON', {
282
+ itemIndex,
283
+ });
284
+ }
285
+ additionalHeaders = (0, n8n_workflow_1.jsonParse)(jsonHeadersParameter);
241
286
  }
242
- requestOptions.body = uploadData;
243
287
  requestOptions.headers = {
244
288
  ...requestOptions.headers,
245
- 'content-length': contentLength,
246
- 'content-type': itemBinaryData.mimeType ?? 'application/octet-stream',
289
+ ...(lowercaseHeaders === undefined || lowercaseHeaders
290
+ ? (0, utilities_1.keysToLowercase)(additionalHeaders)
291
+ : additionalHeaders),
247
292
  };
248
293
  }
249
- else if (bodyContentType === 'raw') {
250
- requestOptions.body = body;
294
+ if (autoDetectResponseFormat || responseFormat === 'file') {
295
+ requestOptions.encoding = null;
296
+ requestOptions.json = false;
297
+ requestOptions.useStream = true;
251
298
  }
252
- }
253
- if (sendQuery && queryParameters) {
254
- if (specifyQuery === 'keypair') {
255
- requestOptions.qs = await (0, GenericFunctions_1.reduceAsync)(queryParameters, parametersToKeyValue);
299
+ else if (bodyContentType === 'raw') {
300
+ requestOptions.json = false;
301
+ requestOptions.useStream = true;
256
302
  }
257
- else if (specifyQuery === 'json') {
258
- try {
259
- JSON.parse(jsonQueryParameter);
260
- }
261
- catch {
262
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'JSON parameter needs to be valid JSON', {
263
- itemIndex,
264
- });
265
- }
266
- requestOptions.qs = (0, n8n_workflow_1.jsonParse)(jsonQueryParameter);
303
+ else {
304
+ requestOptions.json = true;
267
305
  }
268
- }
269
- if (sendHeaders && headerParameters) {
270
- let additionalHeaders = {};
271
- if (specifyHeaders === 'keypair') {
272
- additionalHeaders = await (0, GenericFunctions_1.reduceAsync)(headerParameters.filter((header) => header.name), parametersToKeyValue);
273
- }
274
- else if (specifyHeaders === 'json') {
275
- try {
276
- JSON.parse(jsonHeadersParameter);
277
- }
278
- catch {
279
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'JSON parameter needs to be valid JSON', {
280
- itemIndex,
281
- });
306
+ if (bodyContentType === 'raw') {
307
+ if (requestOptions.headers === undefined) {
308
+ requestOptions.headers = {};
282
309
  }
283
- additionalHeaders = (0, n8n_workflow_1.jsonParse)(jsonHeadersParameter);
284
- }
285
- requestOptions.headers = {
286
- ...requestOptions.headers,
287
- ...(lowercaseHeaders === undefined || lowercaseHeaders
288
- ? (0, utilities_1.keysToLowercase)(additionalHeaders)
289
- : additionalHeaders),
290
- };
291
- }
292
- if (autoDetectResponseFormat || responseFormat === 'file') {
293
- requestOptions.encoding = null;
294
- requestOptions.json = false;
295
- requestOptions.useStream = true;
296
- }
297
- else if (bodyContentType === 'raw') {
298
- requestOptions.json = false;
299
- requestOptions.useStream = true;
300
- }
301
- else {
302
- requestOptions.json = true;
303
- }
304
- if (bodyContentType === 'raw') {
305
- if (requestOptions.headers === undefined) {
306
- requestOptions.headers = {};
307
- }
308
- const rawContentType = this.getNodeParameter('rawContentType', itemIndex);
309
- requestOptions.headers['content-type'] = rawContentType;
310
- }
311
- const authDataKeys = {};
312
- (0, GenericFunctions_1.setAgentOptions)(requestOptions, sslCertificates);
313
- if (requestOptions.agentOptions) {
314
- authDataKeys.agentOptions = Object.keys(requestOptions.agentOptions);
315
- }
316
- if (httpBasicAuth !== undefined) {
317
- requestOptions.auth = {
318
- user: httpBasicAuth.user,
319
- pass: httpBasicAuth.password,
320
- };
321
- authDataKeys.auth = ['pass'];
322
- }
323
- if (httpHeaderAuth !== undefined) {
324
- requestOptions.headers[httpHeaderAuth.name] = httpHeaderAuth.value;
325
- authDataKeys.headers = [httpHeaderAuth.name];
326
- }
327
- if (httpQueryAuth !== undefined) {
328
- if (!requestOptions.qs) {
329
- requestOptions.qs = {};
330
- }
331
- requestOptions.qs[httpQueryAuth.name] = httpQueryAuth.value;
332
- authDataKeys.qs = [httpQueryAuth.name];
333
- }
334
- if (httpDigestAuth !== undefined) {
335
- requestOptions.auth = {
336
- user: httpDigestAuth.user,
337
- pass: httpDigestAuth.password,
338
- sendImmediately: false,
339
- };
340
- authDataKeys.auth = ['pass'];
341
- }
342
- if (httpCustomAuth !== undefined) {
343
- const customAuth = (0, n8n_workflow_1.jsonParse)(httpCustomAuth.json || '{}', { errorMessage: 'Invalid Custom Auth JSON' });
344
- if (customAuth.headers) {
345
- requestOptions.headers = { ...requestOptions.headers, ...customAuth.headers };
346
- authDataKeys.headers = Object.keys(customAuth.headers);
347
- }
348
- if (customAuth.body) {
349
- requestOptions.body = { ...requestOptions.body, ...customAuth.body };
350
- authDataKeys.body = Object.keys(customAuth.body);
351
- }
352
- if (customAuth.qs) {
353
- requestOptions.qs = { ...requestOptions.qs, ...customAuth.qs };
354
- authDataKeys.qs = Object.keys(customAuth.qs);
310
+ const rawContentType = this.getNodeParameter('rawContentType', itemIndex);
311
+ requestOptions.headers['content-type'] = rawContentType;
312
+ }
313
+ const authDataKeys = {};
314
+ (0, GenericFunctions_1.setAgentOptions)(requestOptions, sslCertificates);
315
+ if (requestOptions.agentOptions) {
316
+ authDataKeys.agentOptions = Object.keys(requestOptions.agentOptions);
317
+ }
318
+ if (httpBasicAuth !== undefined) {
319
+ requestOptions.auth = {
320
+ user: httpBasicAuth.user,
321
+ pass: httpBasicAuth.password,
322
+ };
323
+ authDataKeys.auth = ['pass'];
355
324
  }
356
- }
357
- if (requestOptions.headers.accept === undefined) {
358
- if (responseFormat === 'json') {
359
- requestOptions.headers.accept = 'application/json,text/*;q=0.99';
325
+ if (httpHeaderAuth !== undefined) {
326
+ requestOptions.headers[httpHeaderAuth.name] = httpHeaderAuth.value;
327
+ authDataKeys.headers = [httpHeaderAuth.name];
360
328
  }
361
- else if (responseFormat === 'text') {
362
- requestOptions.headers.accept =
363
- 'application/json,text/html,application/xhtml+xml,application/xml,text/*;q=0.9, */*;q=0.1';
364
- }
365
- else {
366
- requestOptions.headers.accept =
367
- 'application/json,text/html,application/xhtml+xml,application/xml,text/*;q=0.9, image/*;q=0.8, */*;q=0.7';
329
+ if (httpQueryAuth !== undefined) {
330
+ if (!requestOptions.qs) {
331
+ requestOptions.qs = {};
332
+ }
333
+ requestOptions.qs[httpQueryAuth.name] = httpQueryAuth.value;
334
+ authDataKeys.qs = [httpQueryAuth.name];
335
+ }
336
+ if (httpDigestAuth !== undefined) {
337
+ requestOptions.auth = {
338
+ user: httpDigestAuth.user,
339
+ pass: httpDigestAuth.password,
340
+ sendImmediately: false,
341
+ };
342
+ authDataKeys.auth = ['pass'];
368
343
  }
369
- }
370
- requests.push({
371
- options: requestOptions,
372
- authKeys: authDataKeys,
373
- credentialType: nodeCredentialType,
374
- });
375
- if (pagination && pagination.paginationMode !== 'off') {
376
- let continueExpression = '={{false}}';
377
- if (pagination.paginationCompleteWhen === 'receiveSpecificStatusCodes') {
378
- const statusCodesWhenCompleted = pagination.statusCodesWhenComplete
379
- .split(',')
380
- .map((item) => parseInt(item.trim()));
381
- continueExpression = `={{ !${JSON.stringify(statusCodesWhenCompleted)}.includes($response.statusCode) }}`;
382
- }
383
- else if (pagination.paginationCompleteWhen === 'responseIsEmpty') {
384
- continueExpression =
385
- '={{ Array.isArray($response.body) ? $response.body.length : !!$response.body }}';
344
+ if (httpCustomAuth !== undefined) {
345
+ const customAuth = (0, n8n_workflow_1.jsonParse)(httpCustomAuth.json || '{}', { errorMessage: 'Invalid Custom Auth JSON' });
346
+ if (customAuth.headers) {
347
+ requestOptions.headers = { ...requestOptions.headers, ...customAuth.headers };
348
+ authDataKeys.headers = Object.keys(customAuth.headers);
349
+ }
350
+ if (customAuth.body) {
351
+ requestOptions.body = { ...requestOptions.body, ...customAuth.body };
352
+ authDataKeys.body = Object.keys(customAuth.body);
353
+ }
354
+ if (customAuth.qs) {
355
+ requestOptions.qs = { ...requestOptions.qs, ...customAuth.qs };
356
+ authDataKeys.qs = Object.keys(customAuth.qs);
357
+ }
386
358
  }
387
- else {
388
- if (!pagination.completeExpression.length || pagination.completeExpression[0] !== '=') {
389
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid or empty Complete Expression');
359
+ if (requestOptions.headers.accept === undefined) {
360
+ if (responseFormat === 'json') {
361
+ requestOptions.headers.accept = 'application/json,text/*;q=0.99';
362
+ }
363
+ else if (responseFormat === 'text') {
364
+ requestOptions.headers.accept =
365
+ 'application/json,text/html,application/xhtml+xml,application/xml,text/*;q=0.9, */*;q=0.1';
366
+ }
367
+ else {
368
+ requestOptions.headers.accept =
369
+ 'application/json,text/html,application/xhtml+xml,application/xml,text/*;q=0.9, image/*;q=0.8, */*;q=0.7';
390
370
  }
391
- continueExpression = `={{ !(${pagination.completeExpression.trim().slice(3, -2)}) }}`;
392
371
  }
393
- const paginationData = {
394
- continue: continueExpression,
395
- request: {},
396
- requestInterval: pagination.requestInterval,
397
- };
398
- if (pagination.paginationMode === 'updateAParameterInEachRequest') {
399
- paginationData.request = {};
400
- const { parameters } = pagination.parameters;
401
- if (parameters.length === 1 && parameters[0].name === '' && parameters[0].value === '') {
402
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), "At least one entry with 'Name' and 'Value' filled must be included in 'Parameters' to use 'Update a Parameter in Each Request' mode ");
403
- }
404
- pagination.parameters.parameters.forEach((parameter, index) => {
405
- if (!paginationData.request[parameter.type]) {
406
- paginationData.request[parameter.type] = {};
372
+ requests.push({
373
+ options: requestOptions,
374
+ authKeys: authDataKeys,
375
+ credentialType: nodeCredentialType,
376
+ });
377
+ if (pagination && pagination.paginationMode !== 'off') {
378
+ let continueExpression = '={{false}}';
379
+ if (pagination.paginationCompleteWhen === 'receiveSpecificStatusCodes') {
380
+ const statusCodesWhenCompleted = pagination.statusCodesWhenComplete
381
+ .split(',')
382
+ .map((item) => parseInt(item.trim()));
383
+ continueExpression = `={{ !${JSON.stringify(statusCodesWhenCompleted)}.includes($response.statusCode) }}`;
384
+ }
385
+ else if (pagination.paginationCompleteWhen === 'responseIsEmpty') {
386
+ continueExpression =
387
+ '={{ Array.isArray($response.body) ? $response.body.length : !!$response.body }}';
388
+ }
389
+ else {
390
+ if (!pagination.completeExpression.length || pagination.completeExpression[0] !== '=') {
391
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid or empty Complete Expression');
407
392
  }
408
- const parameterName = parameter.name;
409
- if (parameterName === '') {
410
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Parameter name must be set for parameter [${index + 1}] in pagination settings`);
393
+ continueExpression = `={{ !(${pagination.completeExpression.trim().slice(3, -2)}) }}`;
394
+ }
395
+ const paginationData = {
396
+ continue: continueExpression,
397
+ request: {},
398
+ requestInterval: pagination.requestInterval,
399
+ };
400
+ if (pagination.paginationMode === 'updateAParameterInEachRequest') {
401
+ paginationData.request = {};
402
+ const { parameters } = pagination.parameters;
403
+ if (parameters.length === 1 &&
404
+ parameters[0].name === '' &&
405
+ parameters[0].value === '') {
406
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), "At least one entry with 'Name' and 'Value' filled must be included in 'Parameters' to use 'Update a Parameter in Each Request' mode ");
411
407
  }
412
- const parameterValue = parameter.value;
413
- if (parameterValue === '') {
414
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Some value must be provided for parameter [${index + 1}] in pagination settings, omitting it will result in an infinite loop`);
408
+ pagination.parameters.parameters.forEach((parameter, index) => {
409
+ if (!paginationData.request[parameter.type]) {
410
+ paginationData.request[parameter.type] = {};
411
+ }
412
+ const parameterName = parameter.name;
413
+ if (parameterName === '') {
414
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Parameter name must be set for parameter [${index + 1}] in pagination settings`);
415
+ }
416
+ const parameterValue = parameter.value;
417
+ if (parameterValue === '') {
418
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Some value must be provided for parameter [${index + 1}] in pagination settings, omitting it will result in an infinite loop`);
419
+ }
420
+ paginationData.request[parameter.type][parameterName] = parameterValue;
421
+ });
422
+ }
423
+ else if (pagination.paginationMode === 'responseContainsNextURL') {
424
+ paginationData.request.url = pagination.nextURL;
425
+ }
426
+ if (pagination.limitPagesFetched) {
427
+ paginationData.maxRequests = pagination.maxRequests;
428
+ }
429
+ if (responseFormat === 'file') {
430
+ paginationData.binaryResult = true;
431
+ }
432
+ const requestPromise = this.helpers.requestWithAuthenticationPaginated
433
+ .call(this, requestOptions, itemIndex, paginationData, nodeCredentialType ?? genericCredentialType)
434
+ .catch((error) => {
435
+ if (error instanceof n8n_workflow_1.NodeOperationError && error.type === 'invalid_url') {
436
+ const urlParameterName = pagination.paginationMode === 'responseContainsNextURL' ? 'Next URL' : 'URL';
437
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, {
438
+ description: `Make sure the "${urlParameterName}" parameter evaluates to a valid URL.`,
439
+ });
415
440
  }
416
- paginationData.request[parameter.type][parameterName] = parameterValue;
441
+ throw error;
417
442
  });
443
+ requestPromises.push(requestPromise);
418
444
  }
419
- else if (pagination.paginationMode === 'responseContainsNextURL') {
420
- paginationData.request.url = pagination.nextURL;
421
- }
422
- if (pagination.limitPagesFetched) {
423
- paginationData.maxRequests = pagination.maxRequests;
424
- }
425
- if (responseFormat === 'file') {
426
- paginationData.binaryResult = true;
427
- }
428
- const requestPromise = this.helpers.requestWithAuthenticationPaginated
429
- .call(this, requestOptions, itemIndex, paginationData, nodeCredentialType ?? genericCredentialType)
430
- .catch((error) => {
431
- if (error instanceof n8n_workflow_1.NodeOperationError && error.type === 'invalid_url') {
432
- const urlParameterName = pagination.paginationMode === 'responseContainsNextURL' ? 'Next URL' : 'URL';
433
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, {
434
- description: `Make sure the "${urlParameterName}" parameter evaluates to a valid URL.`,
445
+ else if (authentication === 'genericCredentialType' || authentication === 'none') {
446
+ if (oAuth1Api) {
447
+ const requestOAuth1 = this.helpers.requestOAuth1.call(this, 'oAuth1Api', requestOptions);
448
+ requestOAuth1.catch(() => { });
449
+ requestPromises.push(requestOAuth1);
450
+ }
451
+ else if (oAuth2Api) {
452
+ const requestOAuth2 = this.helpers.requestOAuth2.call(this, 'oAuth2Api', requestOptions, {
453
+ tokenType: 'Bearer',
435
454
  });
455
+ requestOAuth2.catch(() => { });
456
+ requestPromises.push(requestOAuth2);
457
+ }
458
+ else {
459
+ const request = this.helpers.request(requestOptions);
460
+ request.catch(() => { });
461
+ requestPromises.push(request);
436
462
  }
437
- throw error;
438
- });
439
- requestPromises.push(requestPromise);
440
- }
441
- else if (authentication === 'genericCredentialType' || authentication === 'none') {
442
- if (oAuth1Api) {
443
- const requestOAuth1 = this.helpers.requestOAuth1.call(this, 'oAuth1Api', requestOptions);
444
- requestOAuth1.catch(() => { });
445
- requestPromises.push(requestOAuth1);
446
- }
447
- else if (oAuth2Api) {
448
- const requestOAuth2 = this.helpers.requestOAuth2.call(this, 'oAuth2Api', requestOptions, {
449
- tokenType: 'Bearer',
450
- });
451
- requestOAuth2.catch(() => { });
452
- requestPromises.push(requestOAuth2);
453
463
  }
454
- else {
455
- const request = this.helpers.request(requestOptions);
456
- request.catch(() => { });
457
- requestPromises.push(request);
464
+ else if (authentication === 'predefinedCredentialType' && nodeCredentialType) {
465
+ const additionalOAuth2Options = (0, GenericFunctions_1.getOAuth2AdditionalParameters)(nodeCredentialType);
466
+ const requestWithAuthentication = this.helpers.requestWithAuthentication.call(this, nodeCredentialType, requestOptions, additionalOAuth2Options && { oauth2: additionalOAuth2Options }, itemIndex);
467
+ requestWithAuthentication.catch(() => { });
468
+ requestPromises.push(requestWithAuthentication);
458
469
  }
459
470
  }
460
- else if (authentication === 'predefinedCredentialType' && nodeCredentialType) {
461
- const additionalOAuth2Options = (0, GenericFunctions_1.getOAuth2AdditionalParameters)(nodeCredentialType);
462
- const requestWithAuthentication = this.helpers.requestWithAuthentication.call(this, nodeCredentialType, requestOptions, additionalOAuth2Options && { oauth2: additionalOAuth2Options }, itemIndex);
463
- requestWithAuthentication.catch(() => { });
464
- requestPromises.push(requestWithAuthentication);
471
+ catch (error) {
472
+ if (!this.continueOnFail())
473
+ throw error;
474
+ requestPromises.push(Promise.reject(error).catch(() => { }));
475
+ errorItems[itemIndex] = error.message;
476
+ continue;
465
477
  }
466
478
  }
467
479
  const sanitizedRequests = [];
468
- const promisesResponses = await Promise.allSettled(requestPromises.map(async (requestPromise, itemIndex) => await requestPromise.finally(async () => {
480
+ const promisesResponses = await Promise.allSettled(requestPromises.map(async (requestPromise, itemIndex) => await requestPromise
481
+ .then((response) => response)
482
+ .finally(async () => {
483
+ if (errorItems[itemIndex])
484
+ return;
469
485
  try {
470
486
  const { options, authKeys, credentialType } = requests[itemIndex];
471
487
  let secrets = [];
@@ -483,6 +499,13 @@ class HttpRequestV3 {
483
499
  let responseData;
484
500
  for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
485
501
  responseData = promisesResponses.shift();
502
+ if (errorItems[itemIndex]) {
503
+ returnItems.push({
504
+ json: { error: errorItems[itemIndex] },
505
+ pairedItem: { item: itemIndex },
506
+ });
507
+ continue;
508
+ }
486
509
  if (responseData.status !== 'fulfilled') {
487
510
  if (responseData.reason.statusCode === 429) {
488
511
  responseData.reason.message =