|
|
@@ -125,6 +125,14 @@ const configSchema = {
|
|
|
title: 'Follow Redirects',
|
|
|
default: true
|
|
|
},
|
|
|
+ failOnErrorStatus: {
|
|
|
+ type: 'boolean',
|
|
|
+ title: 'Fail on error status',
|
|
|
+ description: 'Stop the node when the server answers 4xx or 5xx, with what it said as the error. ' +
|
|
|
+ 'Turn this off only to branch on the status yourself - the output still carries ' +
|
|
|
+ 'ok, statusCode and body.',
|
|
|
+ default: true
|
|
|
+ },
|
|
|
responseMode: {
|
|
|
type: 'string',
|
|
|
title: 'Response Mode',
|
|
|
@@ -525,8 +533,43 @@ async function execute(config, input, context) {
|
|
|
result.body = response.data;
|
|
|
}
|
|
|
|
|
|
+ // An error status fails the node.
|
|
|
+ //
|
|
|
+ // It used to return normally with ok:false and a warning in the log, so a
|
|
|
+ // workflow that posted to an API and was refused reported success. A run
|
|
|
+ // that created nothing looked exactly like a run that created everything -
|
|
|
+ // the tag flow here silently did nothing through several rounds of "it
|
|
|
+ // works", because every 422 was a completed node.
|
|
|
+ //
|
|
|
+ // The message carries what the server actually said. "HTTP 422" sends
|
|
|
+ // somebody to the logs; "slug is required" is the answer itself.
|
|
|
+ if (!result.ok && config.failOnErrorStatus !== false) {
|
|
|
+ let detail = '';
|
|
|
+ const body = result.body;
|
|
|
+ if (body && typeof body === 'object') {
|
|
|
+ const parts = [];
|
|
|
+ if (body.error) parts.push(String(body.error));
|
|
|
+ if (body.message && body.message !== body.error) parts.push(String(body.message));
|
|
|
+ if (body.details) parts.push(String(body.details));
|
|
|
+ if (body.validation_errors && typeof body.validation_errors === 'object') {
|
|
|
+ for (const field of Object.keys(body.validation_errors)) {
|
|
|
+ const msgs = body.validation_errors[field];
|
|
|
+ parts.push(field + ': ' + (Array.isArray(msgs) ? msgs.join(' ') : String(msgs)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ detail = parts.join(' - ') || JSON.stringify(body).slice(0, 300);
|
|
|
+ } else if (typeof body === 'string' && body) {
|
|
|
+ detail = body.slice(0, 300);
|
|
|
+ }
|
|
|
+ throw new Error(
|
|
|
+ `${config.method || 'GET'} ${url} returned ${response.status}` +
|
|
|
+ (detail ? ` - ${detail}` : '')
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
if (!result.ok) {
|
|
|
- smartbotic.log.warn(`HTTP request returned ${response.status}`);
|
|
|
+ smartbotic.log.warn(`HTTP request returned ${response.status}, continuing because ` +
|
|
|
+ `"Fail on error status" is off`);
|
|
|
}
|
|
|
|
|
|
return result;
|