Tweak error handling a bit

Always get http headers of the response to be able
to handle issues more explicitly.
These headers also contain additional information
we will need later on.

Change-Id: I062e97726a473c16b29cd84be0aa37260bac4ed8
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Stenger
2022-12-16 08:55:20 +01:00
parent 82bd1de936
commit cc0b392e87
3 changed files with 69 additions and 21 deletions

View File

@@ -6,9 +6,69 @@
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QRegularExpression>
#include <utility>
namespace Axivion::Internal {
static std::pair<QByteArray, QByteArray> splitHeaderAndBody(const QByteArray &input)
{
QByteArray header;
QByteArray json;
int emptyLine = input.indexOf("\r\n\r\n"); // we always get \r\n as line separator
if (emptyLine != -1) {
header = input.left(emptyLine);
json = input.mid(emptyLine + 4);
} else {
json = input;
}
return {header, json};
}
static int httpStatus(const QByteArray &header)
{
int firstHeaderEnd = header.indexOf("\r\n");
if (firstHeaderEnd == -1)
return 600; // unexpected header
const QString firstLine = QString::fromUtf8(header.first(firstHeaderEnd));
static const QRegularExpression regex(R"(^HTTP/\d\.\d (\d{3}) .*$)");
const QRegularExpressionMatch match = regex.match(firstLine);
return match.hasMatch() ? match.captured(1).toInt() : 601;
}
static std::pair<BaseResult, QJsonDocument> prehandleHeaderAndBody(const QByteArray &header,
const QByteArray &body)
{
BaseResult result;
if (header.isEmpty()) {
result.error = QString::fromUtf8(body); // we likely had a curl problem
return {result, {}};
}
int status = httpStatus(header);
if ((status > 399) || (status > 299 && body.isEmpty())) { // FIXME handle some explicitly?
const QString statusStr = QString::number(status);
if (body.isEmpty() || body.startsWith('<')) // likely an html response or redirect
result.error = QLatin1String("(%1)").arg(statusStr);
else
result.error = QLatin1String("%1 (%2)").arg(QString::fromUtf8(body)).arg(statusStr);
return {result, {}};
}
QJsonParseError error;
const QJsonDocument doc = QJsonDocument::fromJson(body, &error);
if (error.error != QJsonParseError::NoError) {
result.error = error.errorString();
return {result, doc};
}
if (!doc.isObject()) {
result.error = "Not an object.";
return {result, {}};
}
return {result, doc};
}
namespace ResultParser {
@@ -16,18 +76,10 @@ DashboardInfo parseDashboardInfo(const QByteArray &input)
{
DashboardInfo result;
QJsonParseError error;
const QJsonDocument doc = QJsonDocument::fromJson(input, &error);
if (error.error != QJsonParseError::NoError) {
if (input.startsWith("Authentication failed:"))
result.error = QString::fromUtf8(input);
else
result.error = error.errorString();
return result;
}
if (!doc.isObject()) {
result.error = "Not an object.";
auto [header, body] = splitHeaderAndBody(input);
auto [error, doc] = prehandleHeaderAndBody(header, body);
if (!error.error.isEmpty()) {
result.error = error.error;
return result;
}
const QJsonObject object = doc.object();