mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-20 20:40:29 +08:00
Ref T570, prepared ApiServerConnection for "threaded AFV client"
* use get/post/deleteFromNetwork function in sApp (calling QAM in coorect thread) * removed timer, use QDateTime::currentMSecsSinceEpoch - one member less causing issues in threaded environment * using CLogMessage instead of qDebug/qWarning * unified log messages
This commit is contained in:
committed by
Mat Sutcliffe
parent
ea8e27cc9b
commit
61d82ab780
@@ -7,13 +7,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "apiserverconnection.h"
|
#include "apiserverconnection.h"
|
||||||
|
|
||||||
|
#include "blackmisc/network/networkutils.h"
|
||||||
#include "blackmisc/network/external/qjsonwebtoken.h"
|
#include "blackmisc/network/external/qjsonwebtoken.h"
|
||||||
|
#include "blackmisc/logmessage.h"
|
||||||
|
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
|
#include <QMetaEnum>
|
||||||
|
|
||||||
|
using namespace BlackMisc;
|
||||||
|
using namespace BlackMisc::Network;
|
||||||
|
|
||||||
namespace BlackCore
|
namespace BlackCore
|
||||||
{
|
{
|
||||||
@@ -23,19 +30,19 @@ namespace BlackCore
|
|||||||
{
|
{
|
||||||
ApiServerConnection::ApiServerConnection(const QString &address, QObject *parent) :
|
ApiServerConnection::ApiServerConnection(const QString &address, QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
m_address(address),
|
m_address(address)
|
||||||
m_watch(new QElapsedTimer)
|
|
||||||
{
|
{
|
||||||
qDebug() << "ApiServerConnection instantiated";
|
CLogMessage(this).debug(u"ApiServerConnection instantiated");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ApiServerConnection::connectTo(const QString &username, const QString &password, const QUuid &networkVersion)
|
bool ApiServerConnection::connectTo(const QString &username, const QString &password, const QUuid &networkVersion)
|
||||||
{
|
{
|
||||||
|
if (isShuttingDown()) { return false; }
|
||||||
|
|
||||||
m_username = username;
|
m_username = username;
|
||||||
m_password = password;
|
m_password = password;
|
||||||
m_networkVersion = networkVersion;
|
m_networkVersion = networkVersion;
|
||||||
m_isAuthenticated = false;
|
m_isAuthenticated = false;
|
||||||
m_watch->start();
|
|
||||||
|
|
||||||
QUrl url(m_address);
|
QUrl url(m_address);
|
||||||
url.setPath("/api/v1/auth");
|
url.setPath("/api/v1/auth");
|
||||||
@@ -47,66 +54,76 @@ namespace BlackCore
|
|||||||
{"networkversion", networkVersion.toString()},
|
{"networkversion", networkVersion.toString()},
|
||||||
};
|
};
|
||||||
|
|
||||||
QNetworkAccessManager *nam = sApp->getNetworkAccessManager();
|
|
||||||
QEventLoop loop;
|
|
||||||
connect(nam, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
|
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(nam->post(request, QJsonDocument(obj).toJson()));
|
QEventLoop loop(sApp);
|
||||||
while (! reply->isFinished()) { loop.exec(); }
|
|
||||||
|
|
||||||
qDebug() << "POST api/v1/auth (" << m_watch->elapsed() << "ms)";
|
// posted in QAM thread
|
||||||
if (reply->error() != QNetworkReply::NoError)
|
QNetworkReply *reply = sApp->postToNetwork(request, CApplication::NoLogRequestId, QJsonDocument(obj).toJson(),
|
||||||
{
|
{
|
||||||
qWarning() << reply->errorString();
|
this, [ & ](QNetworkReply * nwReply)
|
||||||
return false;
|
{
|
||||||
}
|
// called in "this" thread
|
||||||
|
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(nwReply);
|
||||||
|
if (isShuttingDown()) { return; }
|
||||||
|
this->logRequestDuration(reply.data(), "authentication");
|
||||||
|
if (reply->error() != QNetworkReply::NoError)
|
||||||
|
{
|
||||||
|
this->logReplyErrorMessage(reply.data(), "authentication error");
|
||||||
|
loop.exit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// JWT authentication token
|
// JWT authentication token
|
||||||
m_serverToUserOffsetMs = 0;
|
m_serverToUserOffsetMs = 0;
|
||||||
m_expiryLocalUtc = QDateTime(); // clean up
|
m_expiryLocalUtc = QDateTime(); // clean up
|
||||||
|
|
||||||
m_jwt = reply->readAll().trimmed();
|
m_jwt = reply->readAll().trimmed();
|
||||||
qint64 lifeTimeSecs = -1;
|
qint64 lifeTimeSecs = -1;
|
||||||
qint64 serverToUserOffsetSecs = -1;
|
qint64 serverToUserOffsetSecs = -1;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
const QString jwtToken(m_jwt);
|
const QString jwtToken(m_jwt);
|
||||||
QJsonWebToken token = QJsonWebToken::fromTokenAndSecret(jwtToken, "");
|
QJsonWebToken token = QJsonWebToken::fromTokenAndSecret(jwtToken, "");
|
||||||
|
|
||||||
// get decoded header and payload
|
// get decoded header and payload
|
||||||
// QString strHeader = token.getHeaderQStr();
|
// QString strHeader = token.getHeaderQStr();
|
||||||
// QString strPayload = token.getPayloadQStr();
|
// QString strPayload = token.getPayloadQStr();
|
||||||
const QJsonDocument doc = token.getPayloadJDoc();
|
const QJsonDocument doc = token.getPayloadJDoc();
|
||||||
if (doc.isEmpty() || !doc.isObject()) { break; }
|
if (doc.isEmpty() || !doc.isObject()) { break; }
|
||||||
const qint64 validFromSecs = doc.object().value("nbf").toInt(-1);
|
const qint64 validFromSecs = doc.object().value("nbf").toInt(-1);
|
||||||
if (validFromSecs < 0) { break; }
|
if (validFromSecs < 0) { break; }
|
||||||
const qint64 localSecsSinceEpoch = QDateTime::currentSecsSinceEpoch();
|
const qint64 localSecsSinceEpoch = QDateTime::currentSecsSinceEpoch();
|
||||||
serverToUserOffsetSecs = validFromSecs - localSecsSinceEpoch;
|
serverToUserOffsetSecs = validFromSecs - localSecsSinceEpoch;
|
||||||
const qint64 serverExpirySecs = doc.object().value("exp").toInt();
|
const qint64 serverExpirySecs = doc.object().value("exp").toInt();
|
||||||
const qint64 expiryLocalUtc = serverExpirySecs - serverToUserOffsetSecs;
|
const qint64 expiryLocalUtc = serverExpirySecs - serverToUserOffsetSecs;
|
||||||
lifeTimeSecs = expiryLocalUtc - localSecsSinceEpoch;
|
lifeTimeSecs = expiryLocalUtc - localSecsSinceEpoch;
|
||||||
}
|
}
|
||||||
while (false);
|
while (false);
|
||||||
|
|
||||||
if (lifeTimeSecs > 0)
|
if (lifeTimeSecs > 0)
|
||||||
{
|
{
|
||||||
m_serverToUserOffsetMs = serverToUserOffsetSecs * 1000;
|
m_serverToUserOffsetMs = serverToUserOffsetSecs * 1000;
|
||||||
m_expiryLocalUtc = QDateTime::currentDateTimeUtc().addSecs(lifeTimeSecs);
|
m_expiryLocalUtc = QDateTime::currentDateTimeUtc().addSecs(lifeTimeSecs);
|
||||||
m_isAuthenticated = true;
|
m_isAuthenticated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loop.exit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (reply) { loop.exec(); }
|
||||||
return m_isAuthenticated;
|
return m_isAuthenticated;
|
||||||
}
|
}
|
||||||
|
|
||||||
PostCallsignResponseDto ApiServerConnection::addCallsign(const QString &callsign)
|
PostCallsignResponseDto ApiServerConnection::addCallsign(const QString &callsign)
|
||||||
{
|
{
|
||||||
return postNoRequest<PostCallsignResponseDto>("/api/v1/users/" + m_username + "/callsigns/" + callsign);
|
return this->postNoRequest<PostCallsignResponseDto>("/api/v1/users/" + m_username + "/callsigns/" + callsign);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiServerConnection::removeCallsign(const QString &callsign)
|
void ApiServerConnection::removeCallsign(const QString &callsign)
|
||||||
{
|
{
|
||||||
deleteResource("/api/v1/users/" + m_username + "/callsigns/" + callsign);
|
this->deleteResource("/api/v1/users/" + m_username + "/callsigns/" + callsign);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiServerConnection::updateTransceivers(const QString &callsign, const QVector<TransceiverDto> &transceivers)
|
void ApiServerConnection::updateTransceivers(const QString &callsign, const QVector<TransceiverDto> &transceivers)
|
||||||
@@ -116,8 +133,7 @@ namespace BlackCore
|
|||||||
{
|
{
|
||||||
array.append(tx.toJson());
|
array.append(tx.toJson());
|
||||||
}
|
}
|
||||||
|
this->postNoResponse("/api/v1/users/" + m_username + "/callsigns/" + callsign + "/transceivers", QJsonDocument(array));
|
||||||
postNoResponse("/api/v1/users/" + m_username + "/callsigns/" + callsign + "/transceivers", QJsonDocument(array));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiServerConnection::forceDisconnect()
|
void ApiServerConnection::forceDisconnect()
|
||||||
@@ -128,64 +144,142 @@ namespace BlackCore
|
|||||||
|
|
||||||
QVector<StationDto> ApiServerConnection::getAllAliasedStations()
|
QVector<StationDto> ApiServerConnection::getAllAliasedStations()
|
||||||
{
|
{
|
||||||
getAsVector<StationDto>("/api/v1/stations/aliased");
|
this->getAsVector<StationDto>("/api/v1/stations/aliased");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray ApiServerConnection::getWithResponse(const QNetworkRequest &request)
|
||||||
|
{
|
||||||
|
if (isShuttingDown()) { return {}; }
|
||||||
|
|
||||||
|
QEventLoop loop(sApp);
|
||||||
|
QByteArray receivedData;
|
||||||
|
|
||||||
|
// posted in QAM thread
|
||||||
|
QNetworkReply *reply = sApp->getFromNetwork(request,
|
||||||
|
{
|
||||||
|
this, [ & ](QNetworkReply * nwReply)
|
||||||
|
{
|
||||||
|
// called in "this" thread
|
||||||
|
if (!isShuttingDown())
|
||||||
|
{
|
||||||
|
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(nwReply);
|
||||||
|
if (isShuttingDown()) { return; }
|
||||||
|
this->logRequestDuration(reply.data());
|
||||||
|
if (reply->error() == QNetworkReply::NoError)
|
||||||
|
{
|
||||||
|
receivedData = reply->readAll();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->logReplyErrorMessage(reply.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loop.exit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!reply) { return {}; }
|
||||||
|
loop.exec();
|
||||||
|
return receivedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray ApiServerConnection::postWithResponse(const QNetworkRequest &request, const QByteArray &data)
|
||||||
|
{
|
||||||
|
if (isShuttingDown()) { return {}; }
|
||||||
|
|
||||||
|
QEventLoop loop(sApp);
|
||||||
|
QByteArray receivedData;
|
||||||
|
|
||||||
|
// posted in QAM thread
|
||||||
|
QNetworkReply *reply = sApp->postToNetwork(request, CApplication::NoLogRequestId, data,
|
||||||
|
{
|
||||||
|
this, [ & ](QNetworkReply * nwReply)
|
||||||
|
{
|
||||||
|
// called in "this" thread
|
||||||
|
if (!isShuttingDown())
|
||||||
|
{
|
||||||
|
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(nwReply);
|
||||||
|
if (isShuttingDown()) { return; }
|
||||||
|
this->logRequestDuration(reply.data());
|
||||||
|
if (reply->error() == QNetworkReply::NoError)
|
||||||
|
{
|
||||||
|
receivedData = reply->readAll();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->logReplyErrorMessage(reply.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loop.exit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!reply) { return {}; }
|
||||||
|
loop.exec();
|
||||||
|
return receivedData;
|
||||||
|
}
|
||||||
|
|
||||||
void ApiServerConnection::postNoResponse(const QString &resource, const QJsonDocument &json)
|
void ApiServerConnection::postNoResponse(const QString &resource, const QJsonDocument &json)
|
||||||
{
|
{
|
||||||
if (isShuttingDown()) { return; } // avoid crash
|
if (isShuttingDown()) { return; } // avoid crash
|
||||||
if (! m_isAuthenticated)
|
if (!m_isAuthenticated)
|
||||||
{
|
{
|
||||||
qDebug() << "Not authenticated";
|
CLogMessage(this).debug(u"AFV not authenticated");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkExpiry();
|
this->checkExpiry();
|
||||||
|
|
||||||
m_watch->start();
|
|
||||||
QUrl url(m_address);
|
QUrl url(m_address);
|
||||||
url.setPath(resource);
|
url.setPath(resource);
|
||||||
QNetworkAccessManager *nam = sApp->getNetworkAccessManager();
|
|
||||||
QEventLoop loop;
|
|
||||||
connect(nam, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
|
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
request.setRawHeader("Authorization", "Bearer " + m_jwt);
|
request.setRawHeader("Authorization", "Bearer " + m_jwt);
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(nam->post(request, json.toJson()));
|
|
||||||
while (! reply->isFinished()) { loop.exec(); }
|
|
||||||
qDebug() << "POST" << resource << "(" << m_watch->elapsed() << "ms)";
|
|
||||||
|
|
||||||
if (reply->error() != QNetworkReply::NoError)
|
// posted in QAM thread
|
||||||
|
sApp->postToNetwork(request, CApplication::NoLogRequestId, json.toJson(),
|
||||||
{
|
{
|
||||||
qWarning() << "POST" << resource << "failed:" << reply->errorString();
|
this, [ & ](QNetworkReply * nwReply)
|
||||||
return;
|
{
|
||||||
}
|
// called in "this" thread
|
||||||
|
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(nwReply);
|
||||||
|
if (isShuttingDown()) { return; }
|
||||||
|
this->logRequestDuration(reply.data());
|
||||||
|
if (reply->error() != QNetworkReply::NoError)
|
||||||
|
{
|
||||||
|
this->logReplyErrorMessage(reply.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiServerConnection::deleteResource(const QString &resource)
|
void ApiServerConnection::deleteResource(const QString &resource)
|
||||||
{
|
{
|
||||||
if (! m_isAuthenticated) { return; }
|
if (isShuttingDown()) { return; }
|
||||||
|
if (!m_isAuthenticated) { return; }
|
||||||
|
|
||||||
m_watch->start();
|
|
||||||
QUrl url(m_address);
|
QUrl url(m_address);
|
||||||
url.setPath(resource);
|
url.setPath(resource);
|
||||||
|
|
||||||
QNetworkAccessManager *nam = sApp->getNetworkAccessManager();
|
|
||||||
QEventLoop loop;
|
|
||||||
connect(nam, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
|
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
request.setRawHeader("Authorization", "Bearer " + m_jwt);
|
request.setRawHeader("Authorization", "Bearer " + m_jwt);
|
||||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(nam->deleteResource(request));
|
|
||||||
while (! reply->isFinished()) { loop.exec(); }
|
|
||||||
qDebug() << "DELETE" << resource << "(" << m_watch->elapsed() << "ms)";
|
|
||||||
|
|
||||||
if (reply->error() != QNetworkReply::NoError)
|
// posted in QAM thread
|
||||||
|
sApp->deleteResourceFromNetwork(request, CApplication::NoLogRequestId,
|
||||||
{
|
{
|
||||||
qWarning() << "DELETE" << resource << "failed:" << reply->errorString();
|
this, [ & ](QNetworkReply * nwReply)
|
||||||
}
|
{
|
||||||
|
// called in "this" thread
|
||||||
|
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(nwReply);
|
||||||
|
if (isShuttingDown()) { return; }
|
||||||
|
this->logRequestDuration(reply.data());
|
||||||
|
if (reply->error() != QNetworkReply::NoError)
|
||||||
|
{
|
||||||
|
this->logReplyErrorMessage(reply.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiServerConnection::checkExpiry()
|
void ApiServerConnection::checkExpiry()
|
||||||
@@ -196,6 +290,34 @@ namespace BlackCore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApiServerConnection::logReplyErrorMessage(const QNetworkReply *reply, const QString &addMsg)
|
||||||
|
{
|
||||||
|
if (!reply) { return; }
|
||||||
|
if (addMsg.isEmpty())
|
||||||
|
{
|
||||||
|
CLogMessage(this).warning(u"AFV network error for '%1' '%2': '%3'") << reply->url().toString() << CNetworkUtils::networkOperationToString(reply->operation()) << reply->errorString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CLogMessage(this).warning(u"AFV network error (%1) for '%2' '%3': '%4'") << addMsg << reply->url().toString() << CNetworkUtils::networkOperationToString(reply->operation()) << reply->errorString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApiServerConnection::logRequestDuration(const QNetworkReply *reply, const QString &addMsg)
|
||||||
|
{
|
||||||
|
if (!reply) { return; }
|
||||||
|
const qint64 d = CNetworkUtils::requestDuration(reply);
|
||||||
|
if (d < 0) { return; }
|
||||||
|
if (addMsg.isEmpty())
|
||||||
|
{
|
||||||
|
CLogMessage(this).info(u"AFV network request for '%1': %2ms") << reply->url().toString() << d;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CLogMessage(this).info(u"AFV network request (%1) for '%2': '%3'") << addMsg << reply->url().toString() << d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool ApiServerConnection::isShuttingDown()
|
bool ApiServerConnection::isShuttingDown()
|
||||||
{
|
{
|
||||||
return !sApp || sApp->isShuttingDown();
|
return !sApp || sApp->isShuttingDown();
|
||||||
|
|||||||
@@ -68,91 +68,84 @@ namespace BlackCore
|
|||||||
QVector<StationDto> getAllAliasedStations();
|
QVector<StationDto> getAllAliasedStations();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
//! Post to resource
|
||||||
template<typename TResponse>
|
template<typename TResponse>
|
||||||
TResponse postNoRequest(const QString &resource)
|
TResponse postNoRequest(const QString &resource)
|
||||||
{
|
{
|
||||||
if (!m_isAuthenticated)
|
if (!m_isAuthenticated)
|
||||||
{
|
{
|
||||||
qDebug() << "Not authenticated";
|
CLogMessage(this).debug(u"AFV not authenticated");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
checkExpiry();
|
this->checkExpiry();
|
||||||
|
|
||||||
QNetworkAccessManager *nam = sApp->getNetworkAccessManager();
|
|
||||||
|
|
||||||
m_watch->start();
|
|
||||||
QUrl url(m_address);
|
QUrl url(m_address);
|
||||||
url.setPath(resource);
|
url.setPath(resource);
|
||||||
QEventLoop loop;
|
|
||||||
connect(nam, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
|
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
request.setRawHeader("Authorization", "Bearer " + m_jwt);
|
request.setRawHeader("Authorization", "Bearer " + m_jwt);
|
||||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(nam->post(request, QByteArray()));
|
|
||||||
while (! reply->isFinished()) { loop.exec(); }
|
|
||||||
qDebug() << "POST" << resource << "(" << m_watch->elapsed() << "ms)";
|
|
||||||
|
|
||||||
if (reply->error() != QNetworkReply::NoError)
|
const QByteArray receivedData = this->postWithResponse(request);
|
||||||
{
|
const QJsonDocument doc = QJsonDocument::fromJson(receivedData);
|
||||||
qWarning() << "POST" << resource << "failed:" << reply->errorString();
|
const TResponse response = TResponse::fromJson(doc.object());
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
|
|
||||||
TResponse response = TResponse::fromJson(doc.object());
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Get resource and return as vector
|
||||||
template<typename TResponse>
|
template<typename TResponse>
|
||||||
QVector<TResponse> getAsVector(const QString &resource)
|
QVector<TResponse> getAsVector(const QString &resource)
|
||||||
{
|
{
|
||||||
if (! m_isAuthenticated)
|
if (! m_isAuthenticated)
|
||||||
{
|
{
|
||||||
qDebug() << "Not authenticated";
|
CLogMessage(this).debug(u"AFV not authenticated");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
checkExpiry();
|
this->checkExpiry();
|
||||||
|
|
||||||
QNetworkAccessManager *nam = sApp->getNetworkAccessManager();
|
|
||||||
|
|
||||||
m_watch->start();
|
|
||||||
QUrl url(m_address);
|
QUrl url(m_address);
|
||||||
url.setPath(resource);
|
url.setPath(resource);
|
||||||
QEventLoop loop;
|
|
||||||
connect(nam, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
|
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
request.setRawHeader("Authorization", "Bearer " + m_jwt);
|
request.setRawHeader("Authorization", "Bearer " + m_jwt);
|
||||||
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(nam->get(request));
|
|
||||||
while (! reply->isFinished()) { loop.exec(); }
|
|
||||||
qDebug() << "GET" << resource << "(" << m_watch->elapsed() << "ms)";
|
|
||||||
|
|
||||||
if (reply->error() != QNetworkReply::NoError)
|
const QByteArray receivedData = this->getWithResponse(request);
|
||||||
{
|
const QJsonDocument jsonDoc = QJsonDocument::fromJson(receivedData);
|
||||||
qWarning() << "GET" << resource << "failed:" << reply->errorString();
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll());
|
|
||||||
QVector<TResponse> dtos;
|
QVector<TResponse> dtos;
|
||||||
if (jsonDoc.isArray())
|
if (jsonDoc.isArray())
|
||||||
{
|
{
|
||||||
QJsonArray rootArray = jsonDoc.array();
|
QJsonArray rootArray = jsonDoc.array();
|
||||||
for (auto o : rootArray)
|
for (auto o : rootArray)
|
||||||
{
|
{
|
||||||
QJsonObject d = o.toObject();
|
const QJsonObject d = o.toObject();
|
||||||
TResponse dto = TResponse::fromJson(d);
|
const TResponse dto = TResponse::fromJson(d);
|
||||||
dtos.push_back(dto);
|
dtos.push_back(dto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Pseudo synchronous post request returning data
|
||||||
|
QByteArray getWithResponse(const QNetworkRequest &request);
|
||||||
|
|
||||||
|
//! Pseudo synchronous post request returning data
|
||||||
|
QByteArray postWithResponse(const QNetworkRequest &request, const QByteArray &data = {});
|
||||||
|
|
||||||
|
//! Post but do NOT wait for response
|
||||||
void postNoResponse(const QString &resource, const QJsonDocument &json);
|
void postNoResponse(const QString &resource, const QJsonDocument &json);
|
||||||
|
|
||||||
|
//! Delete and do NOT wait for response
|
||||||
void deleteResource(const QString &resource);
|
void deleteResource(const QString &resource);
|
||||||
|
|
||||||
|
//! Session expired, then re-login
|
||||||
void checkExpiry();
|
void checkExpiry();
|
||||||
|
|
||||||
|
//! Message if reply has error
|
||||||
|
void logReplyErrorMessage(const QNetworkReply *reply, const QString &addMsg = {});
|
||||||
|
|
||||||
|
//! Message if reply has error
|
||||||
|
void logRequestDuration(const QNetworkReply *reply, const QString &addMsg = {});
|
||||||
|
|
||||||
|
//! Application shutting down
|
||||||
static bool isShuttingDown();
|
static bool isShuttingDown();
|
||||||
|
|
||||||
const QString m_address;
|
const QString m_address;
|
||||||
@@ -163,7 +156,6 @@ namespace BlackCore
|
|||||||
QDateTime m_expiryLocalUtc;
|
QDateTime m_expiryLocalUtc;
|
||||||
qint64 m_serverToUserOffsetMs;
|
qint64 m_serverToUserOffsetMs;
|
||||||
bool m_isAuthenticated = false;
|
bool m_isAuthenticated = false;
|
||||||
QElapsedTimer *m_watch = nullptr;
|
|
||||||
};
|
};
|
||||||
} // ns
|
} // ns
|
||||||
} // ns
|
} // ns
|
||||||
|
|||||||
Reference in New Issue
Block a user