Better abstraction for http multipart responses.
This commit is contained in:
parent
e9c3c10f53
commit
134c25e86d
1466
rssguard.pro
1466
rssguard.pro
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@
|
||||
|
||||
#include "network-web/downloader.h"
|
||||
|
||||
#include "miscellaneous/iofactory.h"
|
||||
#include "network-web/silentnetworkaccessmanager.h"
|
||||
|
||||
#include <QHttpMultiPart>
|
||||
@ -12,7 +13,7 @@ Downloader::Downloader(QObject* parent)
|
||||
: QObject(parent), m_activeReply(nullptr), m_downloadManager(new SilentNetworkAccessManager(this)),
|
||||
m_timer(new QTimer(this)), m_customHeaders(QHash<QByteArray, QByteArray>()), m_inputData(QByteArray()),
|
||||
m_inputMultipartData(nullptr), m_targetProtected(false), m_targetUsername(QString()), m_targetPassword(QString()),
|
||||
m_lastOutputData(QByteArray()), m_lastOutputMultipartData(QList<QHttpPart*>()), m_lastOutputError(QNetworkReply::NoError),
|
||||
m_lastOutputData(QByteArray()), m_lastOutputMultipartData(QList<HttpResponse>()), m_lastOutputError(QNetworkReply::NoError),
|
||||
m_lastContentType(QVariant()) {
|
||||
m_timer->setInterval(DOWNLOAD_TIMEOUT);
|
||||
m_timer->setSingleShot(true);
|
||||
@ -172,11 +173,11 @@ void Downloader::progressInternal(qint64 bytes_received, qint64 bytes_total) {
|
||||
emit progress(bytes_received, bytes_total);
|
||||
}
|
||||
|
||||
QList<QHttpPart*> Downloader::decodeMultipartAnswer(QNetworkReply* reply) {
|
||||
QList<HttpResponse> Downloader::decodeMultipartAnswer(QNetworkReply* reply) {
|
||||
QByteArray data = reply->readAll();
|
||||
|
||||
if (data.isEmpty()) {
|
||||
return QList<QHttpPart*>();
|
||||
return QList<HttpResponse>();
|
||||
}
|
||||
|
||||
QString content_type = reply->header(QNetworkRequest::KnownHeaders::ContentTypeHeader).toString();
|
||||
@ -184,10 +185,34 @@ QList<QHttpPart*> Downloader::decodeMultipartAnswer(QNetworkReply* reply) {
|
||||
QRegularExpression regex(QL1S("--") + boundary + QL1S("(--)?(\\r\\n)?"));
|
||||
QStringList list = QString::fromUtf8(data).split(regex, QString::SplitBehavior::SkipEmptyParts);
|
||||
|
||||
QList<QHttpPart*> parts;
|
||||
QList<HttpResponse> parts;
|
||||
|
||||
parts.reserve(list.size());
|
||||
|
||||
foreach (const QString& http_response_str, list) {
|
||||
// We separate headers and body.
|
||||
HttpResponse new_part;
|
||||
int start_of_http = http_response_str.indexOf(QL1S("HTTP/1.1"));
|
||||
int start_of_headers = http_response_str.indexOf(QRegularExpression(QSL("\\r\\r?\\n")), start_of_http);
|
||||
int start_of_body = http_response_str.indexOf(QRegularExpression(QSL("(\\r\\r?\\n){2,}")), start_of_headers + 2);
|
||||
QString body = http_response_str.mid(start_of_body);
|
||||
QString headers = http_response_str.mid(start_of_headers,
|
||||
start_of_body - start_of_headers).replace(QRegularExpression(QSL("[\\n\\r]+")),
|
||||
QSL("\n"));
|
||||
|
||||
foreach (const QString& header_line, headers.split(QL1C('\n'), QString::SplitBehavior::SkipEmptyParts)) {
|
||||
int index_colon = header_line.indexOf(QL1C(':'));
|
||||
|
||||
if (index_colon > 0) {
|
||||
new_part.appendHeader(header_line.mid(0, index_colon),
|
||||
header_line.mid(index_colon + 2));
|
||||
}
|
||||
}
|
||||
|
||||
new_part.setBody(body);
|
||||
parts.append(new_part);
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
@ -262,7 +287,7 @@ QNetworkReply::NetworkError Downloader::lastOutputError() const {
|
||||
return m_lastOutputError;
|
||||
}
|
||||
|
||||
QList<QHttpPart*> Downloader::lastOutputMultipartData() const {
|
||||
QList<HttpResponse> Downloader::lastOutputMultipartData() const {
|
||||
return m_lastOutputMultipartData;
|
||||
}
|
||||
|
||||
|
@ -6,13 +6,14 @@
|
||||
#include <QObject>
|
||||
|
||||
#include "definitions/definitions.h"
|
||||
#include "network-web/httpresponse.h"
|
||||
|
||||
#include <QHttpMultiPart>
|
||||
#include <QNetworkReply>
|
||||
#include <QSslError>
|
||||
|
||||
class SilentNetworkAccessManager;
|
||||
class QTimer;
|
||||
class QHttpPart;
|
||||
|
||||
class Downloader : public QObject {
|
||||
Q_OBJECT
|
||||
@ -26,7 +27,7 @@ class Downloader : public QObject {
|
||||
// Access to last received full output data/error/content-type.
|
||||
QByteArray lastOutputData() const;
|
||||
QNetworkReply::NetworkError lastOutputError() const;
|
||||
QList<QHttpPart*> lastOutputMultipartData() const;
|
||||
QList<HttpResponse> lastOutputMultipartData() const;
|
||||
QVariant lastContentType() const;
|
||||
|
||||
public slots:
|
||||
@ -67,7 +68,7 @@ class Downloader : public QObject {
|
||||
void progressInternal(qint64 bytes_received, qint64 bytes_total);
|
||||
|
||||
private:
|
||||
QList<QHttpPart*> decodeMultipartAnswer(QNetworkReply* reply);
|
||||
QList<HttpResponse> decodeMultipartAnswer(QNetworkReply* reply);
|
||||
void manipulateData(const QString& url, QNetworkAccessManager::Operation operation,
|
||||
const QByteArray& data, QHttpMultiPart* multipart_data,
|
||||
int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false,
|
||||
@ -94,7 +95,7 @@ class Downloader : public QObject {
|
||||
// Response data.
|
||||
QByteArray m_lastOutputData;
|
||||
|
||||
QList<QHttpPart*> m_lastOutputMultipartData;
|
||||
QList<HttpResponse> m_lastOutputMultipartData;
|
||||
|
||||
QNetworkReply::NetworkError m_lastOutputError;
|
||||
QVariant m_lastContentType;
|
||||
|
26
src/network-web/httpresponse.cpp
Executable file
26
src/network-web/httpresponse.cpp
Executable file
@ -0,0 +1,26 @@
|
||||
// For license of this file, see <object-root-folder>/LICENSE.md.
|
||||
|
||||
#include "network-web/httpresponse.h"
|
||||
|
||||
HttpResponse::HttpResponse() : m_headers(QList<HttpHeader>()), m_body(QString()) {}
|
||||
|
||||
QString HttpResponse::body() const {
|
||||
return m_body;
|
||||
}
|
||||
|
||||
QList<HttpHeader> HttpResponse::headers() const {
|
||||
return m_headers;
|
||||
}
|
||||
|
||||
void HttpResponse::appendHeader(const QString& name, const QString& value) {
|
||||
HttpHeader head;
|
||||
|
||||
head.first = name;
|
||||
head.second = value;
|
||||
|
||||
m_headers.append(head);
|
||||
}
|
||||
|
||||
void HttpResponse::setBody(const QString& body) {
|
||||
m_body = body;
|
||||
}
|
26
src/network-web/httpresponse.h
Executable file
26
src/network-web/httpresponse.h
Executable file
@ -0,0 +1,26 @@
|
||||
// For license of this file, see <object-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef HTTPRESPONSE_H
|
||||
#define HTTPRESPONSE_H
|
||||
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
|
||||
typedef QPair<QString, QString> HttpHeader;
|
||||
|
||||
class HttpResponse {
|
||||
public:
|
||||
explicit HttpResponse();
|
||||
|
||||
QString body() const;
|
||||
void setBody(const QString& body);
|
||||
QList<HttpHeader> headers() const;
|
||||
|
||||
void appendHeader(const QString& name, const QString& value);
|
||||
|
||||
private:
|
||||
QList<HttpHeader> m_headers;
|
||||
QString m_body;
|
||||
};
|
||||
|
||||
#endif // HTTPRESPONSE_H
|
@ -208,7 +208,7 @@ NetworkResult NetworkFactory::performNetworkOperation(const QString& url, int ti
|
||||
NetworkResult NetworkFactory::performNetworkOperation(const QString& url,
|
||||
int timeout,
|
||||
QHttpMultiPart* input_data,
|
||||
QList<QHttpPart*>& output,
|
||||
QList<HttpResponse>& output,
|
||||
QNetworkAccessManager::Operation operation,
|
||||
QList<QPair<QByteArray, QByteArray>> additional_headers,
|
||||
bool protected_contents,
|
||||
|
@ -3,6 +3,8 @@
|
||||
#ifndef NETWORKFACTORY_H
|
||||
#define NETWORKFACTORY_H
|
||||
|
||||
#include "network-web/httpresponse.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QHttpPart>
|
||||
#include <QNetworkReply>
|
||||
@ -51,7 +53,7 @@ class NetworkFactory {
|
||||
const QString& password = QString());
|
||||
static NetworkResult performNetworkOperation(const QString& url, int timeout,
|
||||
QHttpMultiPart* input_data,
|
||||
QList<QHttpPart*>& output,
|
||||
QList<HttpResponse>& output,
|
||||
QNetworkAccessManager::Operation operation,
|
||||
QList<QPair<QByteArray,
|
||||
QByteArray>> additional_headers = QList<QPair<QByteArray, QByteArray>>(),
|
||||
|
@ -329,7 +329,7 @@ void GmailNetworkFactory::onAuthFailed() {
|
||||
});
|
||||
}
|
||||
|
||||
bool GmailNetworkFactory::obtainAndDecodeFullMessages(const QList<Message>& lite_messages) {
|
||||
bool GmailNetworkFactory::obtainAndDecodeFullMessages(QList<Message>& lite_messages) {
|
||||
QHttpMultiPart* multi = new QHttpMultiPart();
|
||||
|
||||
multi->setContentType(QHttpMultiPart::ContentType::MixedType);
|
||||
@ -354,7 +354,7 @@ bool GmailNetworkFactory::obtainAndDecodeFullMessages(const QList<Message>& lite
|
||||
}
|
||||
|
||||
QList<QPair<QByteArray, QByteArray>> headers;
|
||||
QList<QHttpPart*> output;
|
||||
QList<HttpResponse> output;
|
||||
int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
|
||||
|
||||
headers.append(QPair<QByteArray, QByteArray>(QString(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(),
|
||||
@ -367,7 +367,7 @@ bool GmailNetworkFactory::obtainAndDecodeFullMessages(const QList<Message>& lite
|
||||
QNetworkAccessManager::Operation::PostOperation,
|
||||
headers).first == QNetworkReply::NetworkError::NoError) {
|
||||
// We parse each part of HTTP response (it contains HTTP headers and payload with msg full data).
|
||||
|
||||
foreach (const HttpResponse& part, output) {}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
|
@ -47,7 +47,7 @@ class GmailNetworkFactory : public QObject {
|
||||
void onAuthFailed();
|
||||
|
||||
private:
|
||||
bool obtainAndDecodeFullMessages(const QList<Message>& lite_messages);
|
||||
bool obtainAndDecodeFullMessages(QList<Message>& lite_messages);
|
||||
QList<Message> decodeLiteMessages(const QString& messages_json_data, const QString& stream_id, QString& next_page_token);
|
||||
|
||||
//RootItem* decodeFeedCategoriesData(const QString& categories);
|
||||
|
Loading…
x
Reference in New Issue
Block a user