Files
llink/cpp/src/networkmanager.cpp
T

147 lines
4.1 KiB
C++

#include "networkmanager.h"
#include <QElapsedTimer>
#include <QJsonDocument>
#include <QNetworkReply>
namespace
{
constexpr char API_URL[] = "https://orion.dev.flowy.live";
}
NetworkManager::NetworkManager()
{
m_qnam = new QNetworkAccessManager(this);
connect(m_qnam, &QNetworkAccessManager::finished, this, [this](QNetworkReply *reply) {
// In case particular instances of QNetworkReply are not cleaned up.
// It's safe to be redundant with deleteLater
// Calling deleteLater here also doesn't disrupt QNetworkReply::finished slots, as this both here
// and in those slots are fired in tandem and deleteLater waits for return to event loop to perform deleteLater
reply->deleteLater();
int statusCode = reply->attribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute).toInt();
qDebug() << "Network request status code: " << statusCode;
if (statusCode == 401)
{
qWarning() << "Unauthorized request: " << reply->errorString();
emit unauthorizedDetected();
}
});
}
NetworkManager::~NetworkManager()
{
}
NetworkManager &NetworkManager::instance()
{
static NetworkManager instance;
return instance;
}
void NetworkManager::setAuthHeader(QNetworkRequest &request)
{
if (m_sessionToken.isEmpty())
{
return;
}
QString headerValue = QString("Bearer %1").arg(m_sessionToken);
request.setRawHeader("Authorization", headerValue.toUtf8());
}
QString NetworkManager::getFullUrl(const QString &url)
{
return QString("%1%2").arg(API_URL, url);
}
QNetworkReply *NetworkManager::get(const QString &path)
{
QNetworkRequest req = QNetworkRequest(getFullUrl(path));
setAuthHeader(req);
return m_qnam->get(req);
}
QNetworkReply *NetworkManager::post(const QString &path, const QJsonDocument &doc)
{
QNetworkRequest request = QNetworkRequest(getFullUrl(path));
setAuthHeader(request);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
return m_qnam->post(request, doc.toJson());
}
QNetworkReply *NetworkManager::put(const QString &path, const QJsonDocument &doc)
{
QNetworkRequest request = QNetworkRequest(getFullUrl(path));
setAuthHeader(request);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
return m_qnam->put(request, doc.toJson());
}
QNetworkReply *NetworkManager::patch(const QString &path, const QJsonDocument &doc)
{
QNetworkRequest request = QNetworkRequest(getFullUrl(path));
setAuthHeader(request);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
return m_qnam->sendCustomRequest(request, "PATCH", doc.toJson());
}
QNetworkReply *NetworkManager::del(const QString &path)
{
QNetworkRequest request = QNetworkRequest(getFullUrl(path));
setAuthHeader(request);
return m_qnam->deleteResource(request);
}
QNetworkReply *NetworkManager::del(const QString &path, const QJsonDocument &doc)
{
QNetworkRequest request = QNetworkRequest(getFullUrl(path));
setAuthHeader(request);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
return m_qnam->sendCustomRequest(request, "DELETE", doc.toJson());
}
QNetworkRequest NetworkManager::buildRequest(const QString &path)
{
QNetworkRequest request(getFullUrl(path));
setAuthHeader(request);
return request;
}
QString NetworkManager::sessionToken() const
{
return m_sessionToken;
}
void NetworkManager::setSessionToken(const QString &newToken)
{
m_sessionToken = newToken;
}
class PingTimer : public QObject
{
public:
QElapsedTimer timer;
explicit PingTimer(QObject *parent = nullptr) : QObject(parent) { timer.start(); }
};
void NetworkManager::ping()
{
auto *pingTimer = new PingTimer(this);
QNetworkRequest request(getFullUrl(""));
QNetworkReply *reply = m_qnam->get(request);
connect(reply, &QNetworkReply::finished, pingTimer, [this, pingTimer, reply]() {
int elapsed = static_cast<int>(pingTimer->timer.elapsed());
pingTimer->deleteLater();
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (statusCode > 0)
{
emit pingResult(elapsed);
}
else
{
emit pingFailed();
}
});
}