Skip to content
Snippets Groups Projects
networkresource.cpp 4.42 KiB
Newer Older
akiraohgaki's avatar
akiraohgaki committed
/**
 * 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 {

akiraohgaki's avatar
akiraohgaki committed
NetworkResource::NetworkResource(const QString &name, const QUrl &url, bool async, QObject *parent)
akiraohgaki's avatar
akiraohgaki committed
    : QObject(parent), name_(name), 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
{
    setName(other.name());
    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)
{
    setName(other.name());
    setUrl(other.url());
    setAsync(other.async());
    setRequest(other.request());
    return *this;
}

akiraohgaki's avatar
akiraohgaki committed
QString NetworkResource::name() const
{
    return name_;
}

void NetworkResource::setName(const QString &name)
{
    name_ = name;
}

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_;
}

NetworkResource *NetworkResource::head()
{
    setMethod("HEAD");
    QNetworkRequest networkRequest = request();
    networkRequest.setUrl(url());
    return send(async(), networkRequest);
}

NetworkResource *NetworkResource::get()
{
    setMethod("GET");
    QNetworkRequest networkRequest = request();
    networkRequest.setUrl(url());
    return send(async(), networkRequest);
}

QByteArray NetworkResource::readData()
{
    QByteArray data;
    if (reply()->isFinished()) {
        data = reply()->readAll();
    }
    return data;
}

bool NetworkResource::saveData(const QString &path)
{
    if (reply()->isFinished()) {
        return qtlibs::File(path).writeData(readData());
    }
    return false;
}

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

void NetworkResource::replyFinished()
{
    if (reply()->error() == QNetworkReply::NoError) {
        // Check if redirection
        // Note: An auto redirection option is available since Qt 5.6
        QString newUrl;
        if (reply()->hasRawHeader("Location")) {
            newUrl = QString(reply()->rawHeader("Location"));
        }
        else if (reply()->hasRawHeader("Refresh")) {
            newUrl = QString(reply()->rawHeader("Refresh")).split("url=").last();
        }
        if (!newUrl.isEmpty()) {
            if (newUrl.startsWith("/")) {
                newUrl = reply()->url().authority() + newUrl;
            }
            QNetworkRequest networkRequest = request();
            networkRequest.setUrl(QUrl(newUrl));
            send(true, networkRequest);
            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;
}

akiraohgaki's avatar
akiraohgaki committed
NetworkResource *NetworkResource::send(bool async, const QNetworkRequest &request)
akiraohgaki's avatar
akiraohgaki committed
{
    if (method() == "HEAD") {
        setReply(manager()->head(request));
    }
    else if (method() == "GET") {
        setReply(manager()->get(request));
        connect(reply(), &QNetworkReply::downloadProgress, this, &NetworkResource::downloadProgress);
    }
    connect(reply(), &QNetworkReply::finished, this, &NetworkResource::replyFinished);
    if (!async) {
        QEventLoop eventLoop;
        connect(this, &NetworkResource::finished, &eventLoop, &QEventLoop::quit);
        eventLoop.exec();
    }
    return this;
}

} // namespace qtlibs