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.
- package/dist/build.tsbuildinfo +1 -1
- package/dist/nodes/ExecuteWorkflow/ExecuteWorkflow.node.js +53 -6
- package/dist/nodes/ExecuteWorkflow/ExecuteWorkflow.node.js.map +1 -1
- package/dist/nodes/Files/ReadWriteFile/actions/read.operation.js +1 -0
- package/dist/nodes/Files/ReadWriteFile/actions/read.operation.js.map +1 -1
- package/dist/nodes/Files/ReadWriteFile/helpers/utils.d.ts +1 -0
- package/dist/nodes/Files/ReadWriteFile/helpers/utils.js +5 -0
- package/dist/nodes/Files/ReadWriteFile/helpers/utils.js.map +1 -1
- package/dist/nodes/Form/Form.node.js +26 -16
- package/dist/nodes/Form/Form.node.js.map +1 -1
- package/dist/nodes/Form/interfaces.d.ts +6 -0
- package/dist/nodes/Form/interfaces.js.map +1 -1
- package/dist/nodes/Google/GenericFunctions.d.ts +2 -1
- package/dist/nodes/Google/GenericFunctions.js +12 -0
- package/dist/nodes/Google/GenericFunctions.js.map +1 -1
- package/dist/nodes/Google/Sheet/GoogleSheetsTrigger.node.js +2 -2
- package/dist/nodes/Google/Sheet/GoogleSheetsTrigger.node.js.map +1 -1
- package/dist/nodes/Google/Sheet/v2/actions/sheet/Sheet.resource.js +2 -2
- package/dist/nodes/Google/Sheet/v2/actions/sheet/Sheet.resource.js.map +1 -1
- package/dist/nodes/Google/YouTube/YouTube.node.js +3 -15
- package/dist/nodes/Google/YouTube/YouTube.node.js.map +1 -1
- package/dist/nodes/Google/constants.d.ts +1 -0
- package/dist/nodes/Google/constants.js +2 -1
- package/dist/nodes/Google/constants.js.map +1 -1
- package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.js +366 -343
- package/dist/nodes/HttpRequest/V3/HttpRequestV3.node.js.map +1 -1
- package/dist/nodes/HttpRequest/test/node/workflow.use_error_output.json +97 -0
- package/dist/nodes/Merge/v2/utils.d.ts +6 -0
- package/dist/nodes/Merge/v3/helpers/utils.d.ts +6 -0
- package/dist/types/nodes.json +4 -4
- 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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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 (
|
|
81
|
-
|
|
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
|
-
|
|
84
|
-
|
|
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
|
-
|
|
87
|
-
|
|
147
|
+
const defaultRedirect = nodeVersion >= 4 && redirect === undefined;
|
|
148
|
+
if (redirect?.redirect?.followRedirects || defaultRedirect) {
|
|
149
|
+
requestOptions.followRedirect = true;
|
|
150
|
+
requestOptions.followAllRedirects = true;
|
|
88
151
|
}
|
|
89
|
-
|
|
90
|
-
|
|
152
|
+
if (redirect?.redirect?.maxRedirects || defaultRedirect) {
|
|
153
|
+
requestOptions.maxRedirects = redirect?.redirect?.maxRedirects;
|
|
91
154
|
}
|
|
92
|
-
|
|
93
|
-
|
|
155
|
+
if (response?.response?.neverError) {
|
|
156
|
+
requestOptions.simple = false;
|
|
94
157
|
}
|
|
95
|
-
|
|
96
|
-
|
|
158
|
+
if (proxy) {
|
|
159
|
+
requestOptions.proxy = proxy;
|
|
97
160
|
}
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
|
|
200
|
-
if (
|
|
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(
|
|
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.
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
requestOptions.body = jsonBodyParameter;
|
|
268
|
+
requestOptions.qs = (0, n8n_workflow_1.jsonParse)(jsonQueryParameter);
|
|
213
269
|
}
|
|
214
270
|
}
|
|
215
|
-
|
|
216
|
-
|
|
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
|
-
|
|
240
|
-
|
|
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
|
-
|
|
246
|
-
|
|
289
|
+
...(lowercaseHeaders === undefined || lowercaseHeaders
|
|
290
|
+
? (0, utilities_1.keysToLowercase)(additionalHeaders)
|
|
291
|
+
: additionalHeaders),
|
|
247
292
|
};
|
|
248
293
|
}
|
|
249
|
-
|
|
250
|
-
requestOptions.
|
|
294
|
+
if (autoDetectResponseFormat || responseFormat === 'file') {
|
|
295
|
+
requestOptions.encoding = null;
|
|
296
|
+
requestOptions.json = false;
|
|
297
|
+
requestOptions.useStream = true;
|
|
251
298
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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
|
|
258
|
-
|
|
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
|
-
|
|
270
|
-
|
|
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
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
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
|
-
|
|
358
|
-
|
|
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
|
-
|
|
362
|
-
requestOptions.
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
.
|
|
381
|
-
|
|
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
|
-
|
|
388
|
-
if (
|
|
389
|
-
|
|
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
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
};
|
|
398
|
-
if (pagination.paginationMode
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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
|
-
|
|
441
|
+
throw error;
|
|
417
442
|
});
|
|
443
|
+
requestPromises.push(requestPromise);
|
|
418
444
|
}
|
|
419
|
-
else if (
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
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
|
|
456
|
-
|
|
457
|
-
|
|
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
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
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
|
|
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 =
|