server-sdk/src/serversdk/requestmanager.cpp

149 lines
4.4 KiB
C++

#include "requestmanager.h"
#include "request.h"
#ifdef CORESDK_ZLIB
#include "compression.h"
#endif
#include <memory>
namespace serversdk {
/**
* @brief Wrapper around QNetworkAccessManger to handle soap protocol
* @param parent
*/
RequestManager::RequestManager(QObject *parent)
: QObject(parent)
{
connect(&mNetworkAccessManager, &QNetworkAccessManager::authenticationRequired, [](){
qCWarning(sdknetwork) << "server need authentication";
});
connect(&mNetworkAccessManager, &QNetworkAccessManager::sslErrors, this, &RequestManager::sslErrors);
}
/**
* @brief Process request using QNetworkAccessManger
*
* @param Request
*/
bool RequestManager::processRequest(const std::shared_ptr<Request>& request)
{
QNetworkReply *reply = nullptr;
request->logStartTime();
if (request->type() == "POST") {
if ( request->requestData().isEmpty()) {
qCWarning(sdknetwork) << "Request data is empty -> nothing to send";
}
reply = mNetworkAccessManager.post(request->networkRequest(), request->requestData());
} else if (request->type() == "GET") {
if ( ! request->requestData().isEmpty()) {
qCWarning(sdknetwork) << "Request data is not empty, and you are trying to use get ( not sending any data)";
}
reply = mNetworkAccessManager.get(request->networkRequest());
} else if (request->type() == "PUT") {
reply = mNetworkAccessManager.put(request->networkRequest(), request->requestData());
} else {
qCritical(sdknetwork) << "Using request type:" << request->type() << "is not implemented";
return false;
}
Q_ASSERT(reply);
// Adding reply to final request
reply->setParent(nullptr); // ensure QNetworkreply wont be deleted by QNetworkAccessManager ( it is parent of reply )
request->setNetworkReply(reply);
// Add to map to get correct request when reply is used in signal
mRequestMap.insert(reply, request);
connect(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error),
this, &RequestManager::replyError);
connect(reply, &QNetworkReply::downloadProgress, this, &RequestManager::downloadProgress);
connect(reply, &QNetworkReply::finished, this, [=]() {
std::shared_ptr<Request> request = mRequestMap.value(reply);
request->logFinishTime();
mRequestMap.remove(reply);
emit request->finished(request);
emit downloadFinished(request);
});
return true;
}
/**
* @brief Handle sslErrors -> only debug output
* @param sslErrors ( from QNetworkReply::sslErrors )
*/
void RequestManager::sslErrors(QNetworkReply *reply, const QList<QSslError> &sslErrors)
{
for (const QSslError &error : sslErrors) {
qCDebug(sdknetwork) << QStringLiteral("SSL error:") << error.errorString();
}
if (ignoreSsl()) {
reply->ignoreSslErrors(sslErrors);
}
}
/**
* @brief called upon download progess -> adding data into QByteArray
* @param bytesReceived ( can be different from actual data -> compression )
* @param bytesTotal ( can be different from actual data -> compression )
*/
void RequestManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
// Get Reply ( now only one )
//Q_ASSERT(mCurrentReply);
auto *reply = qobject_cast<QNetworkReply*>(sender());
Q_ASSERT(mRequestMap.contains(reply));
std::shared_ptr<Request> request = mRequestMap.value(reply);
//Q_ASSERT(reply == mCurrentReply);
QString encoding;
// Check encoding
for (const auto & pair : reply->rawHeaderPairs()) {
if (pair.first == QStringLiteral("Content-Encoding")) {
encoding = pair.second;
}
}
QByteArray data = reply->readAll();
// Decompress gzip data
#ifdef CORESDK_ZLIB
if (encoding.toLower() == "gzip" && !data.isEmpty() ) {
data = Compression::decompress(data);
}
#endif
// Append data to request
request->appendResponseData(data);
emit progresss(bytesReceived, bytesTotal);
}
void RequestManager::replyError(QNetworkReply::NetworkError code)
{
auto *reply = qobject_cast<QNetworkReply*>(sender());
Q_ASSERT(mRequestMap.contains(reply));
std::shared_ptr<Request> request = mRequestMap.value(reply);
qCWarning(sdknetwork) << request.get() << "reply error: " << code;
}
bool RequestManager::ignoreSsl() const
{
return mIgnoreSsl;
}
void RequestManager::setIgnoreSsl(bool ignoreSsl)
{
mIgnoreSsl = ignoreSsl;
}
} // core