From d66fa729ad157fcb2cd406233ad5e946ddcebc94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20J=C3=A4ckle?= Date: Tue, 21 Nov 2023 20:51:14 +0100 Subject: [PATCH 1/2] fix that non-successful message responses were not displayed in ACE editor * only successful responses were displayed * however, messages might e.g. be answered with a 400 (bad request) and useful information as response --- ui/modules/api.ts | 22 ++++++++++++++++++---- ui/modules/things/featureMessages.ts | 14 +++++++++----- ui/modules/things/thingMessages.ts | 12 ++++++++---- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/ui/modules/api.ts b/ui/modules/api.ts index bac8828c58..f28fef4104 100644 --- a/ui/modules/api.ts +++ b/ui/modules/api.ts @@ -315,10 +315,16 @@ export function setAuthHeader(forDevOps) { * @param {Object} additionalHeaders object with additional header fields * @param {boolean} returnHeaders request full response instead of json content * @param {boolean} devOps default: false. Set true to avoid /api/2 path + * @param {boolean} returnErrorJson default: false. Set true to return the response of a failed HTTP call as JSON * @return {Object} result as json object */ -export async function callDittoREST(method, path, body = null, - additionalHeaders = null, returnHeaders = false, devOps = false): Promise { +export async function callDittoREST(method, + path, + body = null, + additionalHeaders = null, + returnHeaders = false, + devOps = false, + returnErrorJson = false): Promise { let response; const contentType = method === 'PATCH' ? 'application/merge-patch+json' : 'application/json'; try { @@ -336,14 +342,22 @@ export async function callDittoREST(method, path, body = null, throw err; } if (!response.ok) { - response.json() + if (returnErrorJson) { + if (returnHeaders) { + return response; + } else { + return response.json(); + } + } else { + response.json() .then((dittoErr) => { Utils.showError(dittoErr.description + `\n(${dittoErr.error})`, dittoErr.message, dittoErr.status); }) .catch((err) => { Utils.showError('No error details from Ditto', response.statusText, response.status); }); - throw new Error('An error occurred: ' + response.status); + throw new Error('An error occurred: ' + response.status); + } } if (response.status !== 204) { if (returnHeaders) { diff --git a/ui/modules/things/featureMessages.ts b/ui/modules/things/featureMessages.ts index 5aec47f7f5..9e38d878e7 100644 --- a/ui/modules/things/featureMessages.ts +++ b/ui/modules/things/featureMessages.ts @@ -124,10 +124,14 @@ function messageFeature() { } aceResponse.setValue(''); API.callDittoREST('POST', '/things/' + Things.theThing.thingId + - '/features/' + theFeatureId + - '/inbox/messages/' + dom.inputMessageSubject.value + - '?timeout=' + dom.inputMessageTimeout.value, - payload, + '/features/' + theFeatureId + + '/inbox/messages/' + dom.inputMessageSubject.value + + '?timeout=' + dom.inputMessageTimeout.value, + payload, + null, + false, + false, + true ).then((data) => { dom.buttonMessageSend.classList.remove('busy'); dom.buttonMessageSend.disabled = false; @@ -137,7 +141,7 @@ function messageFeature() { }).catch((err) => { dom.buttonMessageSend.classList.remove('busy'); dom.buttonMessageSend.disabled = false; - aceResponse.setValue(''); + aceResponse.setValue(`Error: ${err}`); }); } diff --git a/ui/modules/things/thingMessages.ts b/ui/modules/things/thingMessages.ts index 1de988d521..bb04418405 100644 --- a/ui/modules/things/thingMessages.ts +++ b/ui/modules/things/thingMessages.ts @@ -117,9 +117,13 @@ function messageThing() { } aceResponse.setValue(''); API.callDittoREST('POST', '/things/' + Things.theThing.thingId + - '/inbox/messages/' + dom.inputThingMessageSubject.value + - '?timeout=' + dom.inputThingMessageTimeout.value, - payload, + '/inbox/messages/' + dom.inputThingMessageSubject.value + + '?timeout=' + dom.inputThingMessageTimeout.value, + payload, + null, + false, + false, + true ).then((data) => { dom.buttonThingMessageSend.classList.remove('busy'); dom.buttonThingMessageSend.disabled = false; @@ -129,7 +133,7 @@ function messageThing() { }).catch((err) => { dom.buttonThingMessageSend.classList.remove('busy'); dom.buttonThingMessageSend.disabled = false; - aceResponse.setValue(''); + aceResponse.setValue(`Error: ${err}`); }); } From 3ce5b5506e0377a8e2a6129807b0b044d87ed87c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20J=C3=A4ckle?= Date: Fri, 24 Nov 2023 10:03:48 +0100 Subject: [PATCH 2/2] improved error toast and showing errors from Ditto MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * display error toast also for message responses with "failed" response code * but still display the response as well in the messages response ace editor * still show JSON errors which are not formatted as "ditto error" (containing at least status and message) Signed-off-by: Thomas Jäckle --- ui/modules/api.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/ui/modules/api.ts b/ui/modules/api.ts index f28fef4104..cd1939c5a9 100644 --- a/ui/modules/api.ts +++ b/ui/modules/api.ts @@ -307,6 +307,14 @@ export function setAuthHeader(forDevOps) { } } +function showDittoError(dittoErr, response) { + if (dittoErr.status && dittoErr.message) { + Utils.showError(dittoErr.description + `\n(${dittoErr.error})`, dittoErr.message, dittoErr.status); + } else { + Utils.showError(JSON.stringify(dittoErr), 'Error', response.status); + } +} + /** * Calls the Ditto api * @param {String} method 'POST', 'GET', 'DELETE', etc. @@ -346,12 +354,15 @@ export async function callDittoREST(method, if (returnHeaders) { return response; } else { - return response.json(); + return response.json().then((dittoErr) => { + showDittoError(dittoErr, response); + return dittoErr; + }); } } else { response.json() .then((dittoErr) => { - Utils.showError(dittoErr.description + `\n(${dittoErr.error})`, dittoErr.message, dittoErr.status); + showDittoError(dittoErr, response); }) .catch((err) => { Utils.showError('No error details from Ditto', response.statusText, response.status); @@ -423,7 +434,7 @@ export async function callConnectionsAPI(operation, successCallback, connectionI if (!response.ok) { response.json() .then((dittoErr) => { - Utils.showError(dittoErr.description, dittoErr.message, dittoErr.status); + showDittoError(dittoErr, response); }) .catch((err) => { Utils.showError('No error details from Ditto', response.statusText, response.status); @@ -436,7 +447,7 @@ export async function callConnectionsAPI(operation, successCallback, connectionI .then((data) => { if (data && data['?'] && data['?']['?'].status >= 400) { const dittoErr = data['?']['?'].payload; - Utils.showError(dittoErr.description, dittoErr.message, dittoErr.status); + showDittoError(dittoErr, response); } else { if (params.unwrapJsonPath) { params.unwrapJsonPath.split('.').forEach(function(node) {