Skip to content
Snippets Groups Projects
qtlib_networkresource.cpp 6.62 KiB
Newer Older
akiraohgaki's avatar
akiraohgaki committed
/**
akiraohgaki's avatar
akiraohgaki committed
 * qtlib
akiraohgaki's avatar
akiraohgaki committed
 *
 * @author      Akira Ohgaki <akiraohgaki@gmail.com>
 * @copyright   Akira Ohgaki
akiraohgaki's avatar
akiraohgaki committed
 * @license     https://opensource.org/licenses/LGPL-3.0
akiraohgaki's avatar
akiraohgaki committed
 * @link        https://github.com/akiraohgaki/qtlib
akiraohgaki's avatar
akiraohgaki committed
 */

akiraohgaki's avatar
akiraohgaki committed
#include "qtlib_networkresource.h"
akiraohgaki's avatar
akiraohgaki committed

#include <QEventLoop>

akiraohgaki's avatar
akiraohgaki committed
#include "qtlib_file.h"
akiraohgaki's avatar
akiraohgaki committed

akiraohgaki's avatar
akiraohgaki committed
namespace qtlib {
akiraohgaki's avatar
akiraohgaki committed

akiraohgaki's avatar
akiraohgaki committed
NetworkResource::NetworkResource(const QString &id, const QUrl &url, bool async, QObject *parent)
    : QObject(parent), id_(id), url_(url), async_(async)
akiraohgaki's avatar
akiraohgaki committed
{
    setManager(new QNetworkAccessManager(this));
}

NetworkResource::~NetworkResource()
{
    manager()->deleteLater();
}

akiraohgaki's avatar
akiraohgaki committed
NetworkResource::NetworkResource(const NetworkResource &other, QObject *parent)
    : QObject(parent)
akiraohgaki's avatar
akiraohgaki committed
{
akiraohgaki's avatar
akiraohgaki committed
    setId(other.id());
akiraohgaki's avatar
akiraohgaki committed
    setUrl(other.url());
    setAsync(other.async());
    setRequest(other.request());
akiraohgaki's avatar
akiraohgaki committed
    setManager(new QNetworkAccessManager(this));
akiraohgaki's avatar
akiraohgaki committed
}

NetworkResource &NetworkResource::operator =(const NetworkResource &other)
{
akiraohgaki's avatar
akiraohgaki committed
    setId(other.id());
akiraohgaki's avatar
akiraohgaki committed
    setUrl(other.url());
    setAsync(other.async());
    setRequest(other.request());
    return *this;
}

akiraohgaki's avatar
akiraohgaki committed
QString NetworkResource::id() const
akiraohgaki's avatar
akiraohgaki committed
{
akiraohgaki's avatar
akiraohgaki committed
    return id_;
akiraohgaki's avatar
akiraohgaki committed
}

akiraohgaki's avatar
akiraohgaki committed
void NetworkResource::setId(const QString &id)
akiraohgaki's avatar
akiraohgaki committed
{
akiraohgaki's avatar
akiraohgaki committed
    id_ = id;
akiraohgaki's avatar
akiraohgaki committed
}

QUrl NetworkResource::url() const
{
    return url_;
}

void NetworkResource::setUrl(const QUrl &url)
{
    url_ = url;
}

bool NetworkResource::async() const
{
    return async_;
}

akiraohgaki's avatar
akiraohgaki committed
void NetworkResource::setAsync(bool async)
akiraohgaki's avatar
akiraohgaki committed
{
    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_;
}

akiraohgaki's avatar
akiraohgaki committed
QString NetworkResource::contentType() const
{
    return contentType_;
}

QByteArray NetworkResource::contentData() const
{
    return contentData_;
}

akiraohgaki's avatar
akiraohgaki committed
NetworkResource *NetworkResource::head()
{
    setMethod("HEAD");
akiraohgaki's avatar
akiraohgaki committed
    return send(url(), async());
akiraohgaki's avatar
akiraohgaki committed
}

NetworkResource *NetworkResource::get()
{
    setMethod("GET");
akiraohgaki's avatar
akiraohgaki committed
    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());
akiraohgaki's avatar
akiraohgaki committed
}

akiraohgaki's avatar
akiraohgaki committed
bool NetworkResource::isFinishedWithNoError()
{
    if (reply()->isFinished() && reply()->error() == QNetworkReply::NoError) {
        return true;
    }
    return false;
}

akiraohgaki's avatar
akiraohgaki committed
QByteArray NetworkResource::readData()
{
    QByteArray data;
akiraohgaki's avatar
akiraohgaki committed
    if (isFinishedWithNoError()) {
akiraohgaki's avatar
akiraohgaki committed
        data = reply()->readAll();
    }
    return data;
}

bool NetworkResource::saveData(const QString &path)
{
akiraohgaki's avatar
akiraohgaki committed
    if (isFinishedWithNoError()) {
akiraohgaki's avatar
akiraohgaki committed
        return qtlib::File(path).writeData(reply()->readAll());
akiraohgaki's avatar
akiraohgaki committed
    }
    return false;
}

void NetworkResource::abort()
{
    if (reply()->isRunning()) {
        reply()->abort();
    }
}

void NetworkResource::replyFinished()
{
akiraohgaki's avatar
akiraohgaki committed
    if (isFinishedWithNoError()) {
akiraohgaki's avatar
akiraohgaki committed
        // Check if redirection
        // Note: An auto redirection option is available since Qt 5.6
akiraohgaki's avatar
akiraohgaki committed
        QUrl redirectUrl;
akiraohgaki's avatar
akiraohgaki committed
        if (reply()->hasRawHeader("Location")) {
akiraohgaki's avatar
akiraohgaki committed
            redirectUrl.setUrl(QString(reply()->rawHeader("Location")));
akiraohgaki's avatar
akiraohgaki committed
        }
        else if (reply()->hasRawHeader("Refresh")) {
akiraohgaki's avatar
akiraohgaki committed
            redirectUrl.setUrl(QString(reply()->rawHeader("Refresh")).split("url=").last());
akiraohgaki's avatar
akiraohgaki committed
        }
akiraohgaki's avatar
akiraohgaki committed
        if (!redirectUrl.isEmpty()) {
            if (redirectUrl.isRelative()) {
                redirectUrl = reply()->url().resolved(redirectUrl);
akiraohgaki's avatar
akiraohgaki committed
            }
akiraohgaki's avatar
akiraohgaki committed
            reply()->deleteLater();
akiraohgaki's avatar
akiraohgaki committed
            send(redirectUrl, true);
akiraohgaki's avatar
akiraohgaki committed
            return;
        }
    }
    emit finished(this);
}

akiraohgaki's avatar
akiraohgaki committed
void NetworkResource::replyDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
    emit downloadProgress(id(), bytesReceived, bytesTotal);
}

void NetworkResource::replyUploadProgress(qint64 bytesSent, qint64 bytesTotal)
{
    emit uploadProgress(id(), bytesSent, bytesTotal);
}

akiraohgaki's avatar
akiraohgaki committed
void NetworkResource::setManager(QNetworkAccessManager *manager)
{
    manager_ = manager;
}

void NetworkResource::setReply(QNetworkReply *reply)
{
    reply_ = reply;
}

void NetworkResource::setMethod(const QString &method)
{
    method_ = method;
}

akiraohgaki's avatar
akiraohgaki committed
void NetworkResource::setContentType(const QString &contentType)
{
    contentType_ = contentType;
}

void NetworkResource::setContentData(const QByteArray &contentData)
akiraohgaki's avatar
akiraohgaki committed
{
akiraohgaki's avatar
akiraohgaki committed
    contentData_ = contentData;
}

NetworkResource *NetworkResource::send(const QUrl &url, bool async)
{
    QNetworkRequest networkRequest = request();
    networkRequest.setUrl(url);
akiraohgaki's avatar
akiraohgaki committed
    if (method() == "HEAD") {
akiraohgaki's avatar
akiraohgaki committed
        setReply(manager()->head(networkRequest));
akiraohgaki's avatar
akiraohgaki committed
    }
    else if (method() == "GET") {
akiraohgaki's avatar
akiraohgaki committed
        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);
akiraohgaki's avatar
akiraohgaki committed
    }
    connect(reply(), &QNetworkReply::finished, this, &NetworkResource::replyFinished);
akiraohgaki's avatar
akiraohgaki committed
    connect(reply(), &QNetworkReply::downloadProgress, this, &NetworkResource::replyDownloadProgress);
    connect(reply(), &QNetworkReply::uploadProgress, this, &NetworkResource::replyUploadProgress);
akiraohgaki's avatar
akiraohgaki committed
    if (!async) {
        QEventLoop eventLoop;
        connect(this, &NetworkResource::finished, &eventLoop, &QEventLoop::quit);
        eventLoop.exec();
    }
    return this;
}

akiraohgaki's avatar
akiraohgaki committed
} // namespace qtlib