Added ability to synchronous/asynchronous HTTP POST to be used by TT-RSS plugin.

This commit is contained in:
Martin Rotter 2015-12-01 07:30:26 +01:00
parent 3271c56827
commit f634857f6e
6 changed files with 108 additions and 4 deletions

View File

@ -100,7 +100,7 @@ int main(int argc, char *argv[]) {
main_window.setWindowTitle(APP_LONG_NAME);
// Now is a good time to initialize dynamic keyboard shortcuts.
DynamicShortcuts::load(qApp->userActions());
DynamicShortcuts::load(qApp->userActions());
// Display main window.
if (qApp->settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool() && SystemTrayIcon::isSystemTrayActivated()) {

View File

@ -24,8 +24,8 @@
Downloader::Downloader(QObject *parent)
: QObject(parent), m_activeReply(NULL), m_downloadManager(new SilentNetworkAccessManager(this)),
m_timer(new QTimer(this)), m_customHeaders(QHash<QByteArray, QByteArray>()), m_lastOutputData(QByteArray()),
m_lastOutputError(QNetworkReply::NoError), m_lastContentType(QVariant()) {
m_timer(new QTimer(this)), m_customHeaders(QHash<QByteArray, QByteArray>()), m_inputData(QByteArray()),
m_lastOutputData(QByteArray()), m_lastOutputError(QNetworkReply::NoError), m_lastContentType(QVariant()) {
m_timer->setInterval(DOWNLOAD_TIMEOUT);
m_timer->setSingleShot(true);
@ -66,8 +66,33 @@ void Downloader::downloadFile(const QString &url, int timeout, bool protected_co
runGetRequest(request);
}
void Downloader::uploadData(const QString &url, const QByteArray &data, int timeout) {
QNetworkRequest request;
QString non_const_url = url;
foreach (const QByteArray &header_name, m_customHeaders.keys()) {
request.setRawHeader(header_name, m_customHeaders.value(header_name));
}
m_inputData = data;
// Set url for this request and fire it up.
m_timer->setInterval(timeout);
if (non_const_url.startsWith(URI_SCHEME_FEED)) {
qDebug("Replacing URI schemes for '%s'.", qPrintable(non_const_url));
request.setUrl(non_const_url.replace(QRegExp(QString('^') + URI_SCHEME_FEED), QString(URI_SCHEME_HTTP)));
}
else {
request.setUrl(non_const_url);
}
runPostRequest(request, m_inputData);
}
void Downloader::finished() {
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
QNetworkAccessManager::Operation reply_operation = reply->operation();
m_timer->stop();
@ -89,7 +114,12 @@ void Downloader::finished() {
m_activeReply->deleteLater();
m_activeReply = NULL;
runGetRequest(request);
if (reply_operation == QNetworkAccessManager::GetOperation) {
runGetRequest(request);
}
else if (reply_operation == QNetworkAccessManager::PostOperation) {
runPostRequest(request, m_inputData);
}
}
else {
// No redirection is indicated. Final file is obtained in our "reply" object.
@ -120,6 +150,14 @@ void Downloader::timeout() {
}
}
void Downloader::runPostRequest(const QNetworkRequest &request, const QByteArray &data) {
m_timer->start();
m_activeReply = m_downloadManager->post(request, data);
connect(m_activeReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(progressInternal(qint64,qint64)));
connect(m_activeReply, SIGNAL(finished()), this, SLOT(finished()));
}
void Downloader::runGetRequest(const QNetworkRequest &request) {
m_timer->start();
m_activeReply = m_downloadManager->get(request);

View File

@ -49,6 +49,11 @@ class Downloader : public QObject {
void downloadFile(const QString &url, int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false,
const QString &username = QString(), const QString &password = QString());
// Performs asynchronous upload of given data as HTTP POST.
// User needs to setup "Content-Encoding" header which
// matches encoding of the data.
void uploadData(const QString &url, const QByteArray &data, int timeout = DOWNLOAD_TIMEOUT);
signals:
// Emitted when new progress is known.
void progress(qint64 bytes_received, qint64 bytes_total);
@ -65,6 +70,7 @@ class Downloader : public QObject {
void timeout();
private:
void runPostRequest(const QNetworkRequest &request, const QByteArray &data);
void runGetRequest(const QNetworkRequest &request);
private:
@ -72,6 +78,7 @@ class Downloader : public QObject {
SilentNetworkAccessManager *m_downloadManager;
QTimer *m_timer;
QHash<QByteArray, QByteArray> m_customHeaders;
QByteArray m_inputData;
// Response data.
QByteArray m_lastOutputData;

View File

@ -148,6 +148,26 @@ QNetworkReply::NetworkError NetworkFactory::downloadIcon(const QList<QString> &u
return network_result;
}
NetworkResult NetworkFactory::uploadData(const QString &url, int timeout, const QByteArray &input_data,
const QString &input_content_type, QByteArray &output) {
Downloader downloader;
QEventLoop loop;
NetworkResult result;
downloader.appendRawHeader("Content-Type", input_content_type.toLocal8Bit());
// We need to quit event loop when the download finishes.
QObject::connect(&downloader, SIGNAL(completed(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
downloader.uploadData(url, input_data, timeout);
loop.exec();
output = downloader.lastOutputData();
result.first = downloader.lastOutputError();
result.second = downloader.lastContentType();
return result;
}
NetworkResult NetworkFactory::downloadFeedFile(const QString &url, int timeout,
QByteArray &output, bool protected_contents,
const QString &username, const QString &password) {

3
src/network-web/networkfactory.h Normal file → Executable file
View File

@ -43,6 +43,9 @@ class NetworkFactory {
// given URL belongs to.
static QNetworkReply::NetworkError downloadIcon(const QList<QString> &urls, int timeout, QIcon &output);
static NetworkResult uploadData(const QString &url, int timeout, const QByteArray &input_data,
const QString &input_content_type, QByteArray &output);
static NetworkResult downloadFeedFile(const QString &url, int timeout, QByteArray &output,
bool protected_contents = false, const QString &username = QString(),
const QString &password = QString());

View File

@ -0,0 +1,36 @@
#ifndef DEFINITIONS_H
#define DEFINITIONS_H
// Error when user needs to login before making an operation.
#define NOT_LOGGED_IN "NOT_LOGGED_IN"
// General return status codes.
#define API_STATUS_OK 0
#define API_STATUS_ERR 1
#define STATUS_OK "OK"
// Login.
#define API_DISABLED "API_DISABLED" // API is not enabled.
#define LOGIN_ERROR "LOGIN_ERROR" // Incorrect password/username.
// Logout.
#define LOGOUT_OK "OK"
/* //login
* QtJson::JsonObject obj;
obj["op"] = "login";
obj["user"] = "admin";
obj["password"] = "Zy69tKWF";
QByteArray arr;
NetworkResult res = NetworkFactory::uploadData("http://rss.rotterovi.eu/api/",
15000,
QtJson::serialize(obj),
"application/json; charset=utf-8",
arr);
obj = QtJson::parse(QString::fromUtf8(arr)).toMap();*/
#endif // DEFINITIONS_H