#include "networkmanager.h" #include #include #include 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(pingTimer->timer.elapsed()); pingTimer->deleteLater(); int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (statusCode > 0) { emit pingResult(elapsed); } else { emit pingFailed(); } }); }