/** * A library for Qt app * * LICENSE: The GNU Lesser General Public License, version 3.0 * * @author Akira Ohgaki <akiraohgaki@gmail.com> * @copyright Akira Ohgaki * @license https://opensource.org/licenses/LGPL-3.0 The GNU Lesser General Public License, version 3.0 * @link https://github.com/akiraohgaki/qtlibs */ #include "networkresource.h" #include <QEventLoop> #include "file.h" namespace qtlibs { NetworkResource::NetworkResource(const QString &id, const QUrl &url, bool async, QObject *parent) : QObject(parent), id_(id), url_(url), async_(async) { setManager(new QNetworkAccessManager(this)); } NetworkResource::~NetworkResource() { manager()->deleteLater(); } NetworkResource::NetworkResource(const NetworkResource &other, QObject *parent) : QObject(parent) { setId(other.id()); setUrl(other.url()); setAsync(other.async()); setRequest(other.request()); setManager(new QNetworkAccessManager(this)); } NetworkResource &NetworkResource::operator =(const NetworkResource &other) { setId(other.id()); setUrl(other.url()); setAsync(other.async()); setRequest(other.request()); return *this; } QString NetworkResource::id() const { return id_; } void NetworkResource::setId(const QString &id) { id_ = id; } QUrl NetworkResource::url() const { return url_; } void NetworkResource::setUrl(const QUrl &url) { url_ = url; } bool NetworkResource::async() const { return async_; } void NetworkResource::setAsync(bool async) { async_ = async; } QNetworkRequest NetworkResource::request() const { return request_; } void NetworkResource::setRequest(const QNetworkRequest &request) { request_ = request; } QNetworkAccessManager *NetworkResource::manager() const { return manager_; } QNetworkReply *NetworkResource::reply() const { return reply_; } QString NetworkResource::method() const { return method_; } QString NetworkResource::contentType() const { return contentType_; } QByteArray NetworkResource::contentData() const { return contentData_; } NetworkResource *NetworkResource::head() { setMethod("HEAD"); return send(url(), async()); } NetworkResource *NetworkResource::get() { setMethod("GET"); return send(url(), async()); } NetworkResource *NetworkResource::post(const QByteArray &contentData, const QString &contentType) { setMethod("POST"); setContentType(contentType); setContentData(contentData); return send(url(), async()); } NetworkResource *NetworkResource::post(const QUrlQuery &contentData) { setMethod("POST"); setContentType("application/x-www-form-urlencoded"); setContentData(contentData.toString(QUrl::FullyEncoded).toUtf8()); return send(url(), async()); } NetworkResource *NetworkResource::put(const QByteArray &contentData, const QString &contentType) { setMethod("PUT"); setContentType(contentType); setContentData(contentData); return send(url(), async()); } NetworkResource *NetworkResource::put(const QUrlQuery &contentData) { setMethod("PUT"); setContentType("application/x-www-form-urlencoded"); setContentData(contentData.toString(QUrl::FullyEncoded).toUtf8()); return send(url(), async()); } NetworkResource *NetworkResource::deleteResource() { setMethod("DELETE"); return send(url(), async()); } bool NetworkResource::isFinishedWithNoError() { if (reply()->isFinished() && reply()->error() == QNetworkReply::NoError) { return true; } return false; } QByteArray NetworkResource::readData() { QByteArray data; if (isFinishedWithNoError()) { data = reply()->readAll(); } return data; } bool NetworkResource::saveData(const QString &path) { if (isFinishedWithNoError()) { return qtlibs::File(path).writeData(reply()->readAll()); } return false; } void NetworkResource::abort() { if (reply()->isRunning()) { reply()->abort(); } } void NetworkResource::replyFinished() { if (isFinishedWithNoError()) { // Check if redirection // Note: An auto redirection option is available since Qt 5.6 QUrl redirectUrl; if (reply()->hasRawHeader("Location")) { redirectUrl.setUrl(QString(reply()->rawHeader("Location"))); } else if (reply()->hasRawHeader("Refresh")) { redirectUrl.setUrl(QString(reply()->rawHeader("Refresh")).split("url=").last()); } if (!redirectUrl.isEmpty()) { if (redirectUrl.isRelative()) { redirectUrl = reply()->url().resolved(redirectUrl); } reply()->deleteLater(); send(redirectUrl, true); return; } } emit finished(this); } void NetworkResource::setManager(QNetworkAccessManager *manager) { manager_ = manager; } void NetworkResource::setReply(QNetworkReply *reply) { reply_ = reply; } void NetworkResource::setMethod(const QString &method) { method_ = method; } void NetworkResource::setContentType(const QString &contentType) { contentType_ = contentType; } void NetworkResource::setContentData(const QByteArray &contentData) { contentData_ = contentData; } NetworkResource *NetworkResource::send(const QUrl &url, bool async) { QNetworkRequest networkRequest = request(); networkRequest.setUrl(url); if (method() == "HEAD") { setReply(manager()->head(networkRequest)); } else if (method() == "GET") { setReply(manager()->get(networkRequest)); } else if (method() == "POST") { networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType())); setReply(manager()->post(networkRequest, contentData())); } else if (method() == "PUT") { networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType())); setReply(manager()->put(networkRequest, contentData())); } else if (method() == "DELETE") { setReply(manager()->deleteResource(networkRequest)); } else { Q_ASSERT(false); } connect(reply(), &QNetworkReply::finished, this, &NetworkResource::replyFinished); connect(reply(), &QNetworkReply::downloadProgress, this, &NetworkResource::downloadProgress); connect(reply(), &QNetworkReply::uploadProgress, this, &NetworkResource::uploadProgress); if (!async) { QEventLoop eventLoop; connect(this, &NetworkResource::finished, &eventLoop, &QEventLoop::quit); eventLoop.exec(); } return this; } } // namespace qtlibs