File indexing completed on 2025-01-19 03:55:40
0001 #include <cassert> 0002 0003 #include <QDebug> 0004 #include <QTimer> 0005 #include <QBuffer> 0006 #if QT_VERSION >= 0x050000 0007 #include <QUrlQuery> 0008 #endif 0009 0010 #include "o2requestor.h" 0011 #include "o2.h" 0012 #include "o0globals.h" 0013 0014 O2Requestor::O2Requestor(QNetworkAccessManager *manager, O2 *authenticator, QObject *parent): QObject(parent), reply_(NULL), status_(Idle), addAccessTokenInQuery_(true), rawData_(false) { 0015 manager_ = manager; 0016 authenticator_ = authenticator; 0017 if (authenticator) { 0018 timedReplies_.setIgnoreSslErrors(authenticator->ignoreSslErrors()); 0019 } 0020 qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError"); 0021 connect(authenticator, SIGNAL(refreshFinished(QNetworkReply::NetworkError)), this, SLOT(onRefreshFinished(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0022 } 0023 0024 O2Requestor::~O2Requestor() { 0025 } 0026 0027 void O2Requestor::setAddAccessTokenInQuery(bool value) { 0028 addAccessTokenInQuery_ = value; 0029 } 0030 0031 void O2Requestor::setAccessTokenInAuthenticationHTTPHeaderFormat(const QString &value) { 0032 accessTokenInAuthenticationHTTPHeaderFormat_ = value; 0033 } 0034 0035 int O2Requestor::get(const QNetworkRequest &req, int timeout/* = 60*1000*/) { 0036 if (-1 == setup(req, QNetworkAccessManager::GetOperation)) { 0037 return -1; 0038 } 0039 reply_ = manager_->get(request_); 0040 timedReplies_.add(new O2Reply(reply_, timeout)); 0041 0042 #if QT_VERSION < 0x051500 0043 connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0044 #else 0045 connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0046 #endif 0047 connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished()), Qt::QueuedConnection); 0048 return id_; 0049 } 0050 0051 int O2Requestor::post(const QNetworkRequest &req, const QByteArray &data, int timeout/* = 60*1000*/) { 0052 if (-1 == setup(req, QNetworkAccessManager::PostOperation)) { 0053 return -1; 0054 } 0055 rawData_ = true; 0056 data_ = data; 0057 reply_ = manager_->post(request_, data_); 0058 timedReplies_.add(new O2Reply(reply_, timeout)); 0059 #if QT_VERSION < 0x051500 0060 connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0061 #else 0062 connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0063 #endif 0064 connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished()), Qt::QueuedConnection); 0065 connect(reply_, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(onUploadProgress(qint64,qint64))); 0066 return id_; 0067 } 0068 0069 int O2Requestor::post(const QNetworkRequest & req, QHttpMultiPart* data, int timeout/* = 60*1000*/) 0070 { 0071 if (-1 == setup(req, QNetworkAccessManager::PostOperation)) { 0072 return -1; 0073 } 0074 rawData_ = false; 0075 multipartData_ = data; 0076 reply_ = manager_->post(request_, multipartData_); 0077 multipartData_->setParent(reply_); 0078 timedReplies_.add(new O2Reply(reply_, timeout)); 0079 #if QT_VERSION < 0x051500 0080 connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0081 #else 0082 connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0083 #endif 0084 connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished()), Qt::QueuedConnection); 0085 connect(reply_, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(onUploadProgress(qint64,qint64))); 0086 return id_; 0087 } 0088 0089 int O2Requestor::put(const QNetworkRequest &req, const QByteArray &data, int timeout/* = 60*1000*/) { 0090 if (-1 == setup(req, QNetworkAccessManager::PutOperation)) { 0091 return -1; 0092 } 0093 rawData_ = true; 0094 data_ = data; 0095 reply_ = manager_->put(request_, data_); 0096 timedReplies_.add(new O2Reply(reply_, timeout)); 0097 #if QT_VERSION < 0x051500 0098 connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0099 #else 0100 connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0101 #endif 0102 connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished()), Qt::QueuedConnection); 0103 connect(reply_, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(onUploadProgress(qint64,qint64))); 0104 return id_; 0105 } 0106 0107 int O2Requestor::put(const QNetworkRequest & req, QHttpMultiPart* data, int timeout/* = 60*1000*/) 0108 { 0109 if (-1 == setup(req, QNetworkAccessManager::PutOperation)) { 0110 return -1; 0111 } 0112 rawData_ = false; 0113 multipartData_ = data; 0114 reply_ = manager_->put(request_, multipartData_); 0115 multipartData_->setParent(reply_); 0116 timedReplies_.add(new O2Reply(reply_, timeout)); 0117 #if QT_VERSION < 0x051500 0118 connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0119 #else 0120 connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0121 #endif 0122 connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished()), Qt::QueuedConnection); 0123 connect(reply_, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(onUploadProgress(qint64,qint64))); 0124 return id_; 0125 } 0126 0127 int O2Requestor::deleteResource(const QNetworkRequest & req, int timeout/* = 60*1000*/) 0128 { 0129 if (-1 == setup(req, QNetworkAccessManager::DeleteOperation)) { 0130 return -1; 0131 } 0132 rawData_ = false; 0133 reply_ = manager_->deleteResource(request_); 0134 timedReplies_.add(new O2Reply(reply_, timeout)); 0135 #if QT_VERSION < 0x051500 0136 connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0137 #else 0138 connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0139 #endif 0140 connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished()), Qt::QueuedConnection); 0141 return id_; 0142 } 0143 0144 int O2Requestor::customRequest(const QNetworkRequest &req, const QByteArray &verb, const QByteArray &data, int timeout/* = 60*1000*/) 0145 { 0146 (void)timeout; 0147 0148 if (-1 == setup(req, QNetworkAccessManager::CustomOperation, verb)) { 0149 return -1; 0150 } 0151 data_ = data; 0152 QBuffer * buffer = new QBuffer; 0153 buffer->setData(data_); 0154 reply_ = manager_->sendCustomRequest(request_, verb, buffer); 0155 buffer->setParent(reply_); 0156 timedReplies_.add(new O2Reply(reply_)); 0157 #if QT_VERSION < 0x051500 0158 connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0159 #else 0160 connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0161 #endif 0162 connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished()), Qt::QueuedConnection); 0163 connect(reply_, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(onUploadProgress(qint64,qint64))); 0164 return id_; 0165 } 0166 0167 int O2Requestor::head(const QNetworkRequest &req, int timeout/* = 60*1000*/) 0168 { 0169 if (-1 == setup(req, QNetworkAccessManager::HeadOperation)) { 0170 return -1; 0171 } 0172 reply_ = manager_->head(request_); 0173 timedReplies_.add(new O2Reply(reply_, timeout)); 0174 #if QT_VERSION < 0x051500 0175 connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0176 #else 0177 connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0178 #endif 0179 connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished()), Qt::QueuedConnection); 0180 return id_; 0181 } 0182 0183 void O2Requestor::onRefreshFinished(QNetworkReply::NetworkError error) { 0184 if (status_ != Requesting) { 0185 qWarning() << "O2Requestor::onRefreshFinished: No pending request"; 0186 return; 0187 } 0188 if (QNetworkReply::NoError == error) { 0189 QTimer::singleShot(100, this, SLOT(retry())); 0190 } else { 0191 error_ = error; 0192 QTimer::singleShot(10, this, SLOT(finish())); 0193 } 0194 } 0195 0196 void O2Requestor::onRequestFinished() { 0197 if (status_ == Idle) { 0198 return; 0199 } 0200 if (reply_ != qobject_cast<QNetworkReply *>(sender())) { 0201 return; 0202 } 0203 if (reply_->error() == QNetworkReply::NoError) { 0204 QTimer::singleShot(10, this, SLOT(finish())); 0205 } 0206 } 0207 0208 void O2Requestor::onRequestError(QNetworkReply::NetworkError error) { 0209 qWarning() << "O2Requestor::onRequestError: Error" << (int)error; 0210 if (status_ == Idle) { 0211 return; 0212 } 0213 if (reply_ != qobject_cast<QNetworkReply *>(sender())) { 0214 return; 0215 } 0216 int httpStatus = reply_->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); 0217 qWarning() << "O2Requestor::onRequestError: HTTP status" << httpStatus << reply_->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); 0218 if ((status_ == Requesting) && (httpStatus == 401)) { 0219 // Call O2::refresh. Note the O2 instance might live in a different thread 0220 if (QMetaObject::invokeMethod(authenticator_, "refresh")) { 0221 return; 0222 } 0223 qCritical() << "O2Requestor::onRequestError: Invoking remote refresh failed"; 0224 } 0225 error_ = error; 0226 QTimer::singleShot(10, this, SLOT(finish())); 0227 } 0228 0229 void O2Requestor::onUploadProgress(qint64 uploaded, qint64 total) { 0230 if (status_ == Idle) { 0231 qWarning() << "O2Requestor::onUploadProgress: No pending request"; 0232 return; 0233 } 0234 if (reply_ != qobject_cast<QNetworkReply *>(sender())) { 0235 return; 0236 } 0237 // Restart timeout because request in progress 0238 O2Reply *o2Reply = timedReplies_.find(reply_); 0239 if(o2Reply) 0240 o2Reply->start(); 0241 Q_EMIT uploadProgress(id_, uploaded, total); 0242 } 0243 0244 int O2Requestor::setup(const QNetworkRequest &req, QNetworkAccessManager::Operation operation, const QByteArray &verb) { 0245 static int currentId; 0246 0247 if (status_ != Idle) { 0248 qWarning() << "O2Requestor::setup: Another request pending"; 0249 return -1; 0250 } 0251 0252 request_ = req; 0253 operation_ = operation; 0254 id_ = currentId++; 0255 url_ = req.url(); 0256 0257 QUrl url = url_; 0258 if (addAccessTokenInQuery_) { 0259 #if QT_VERSION < 0x050000 0260 url.addQueryItem(O2_OAUTH2_ACCESS_TOKEN, authenticator_->token()); 0261 #else 0262 QUrlQuery query(url); 0263 query.addQueryItem(O2_OAUTH2_ACCESS_TOKEN, authenticator_->token()); 0264 url.setQuery(query); 0265 #endif 0266 } 0267 0268 request_.setUrl(url); 0269 0270 // If the service require the access token to be sent as a Authentication HTTP header, we add the access token. 0271 if (!accessTokenInAuthenticationHTTPHeaderFormat_.isEmpty()) { 0272 request_.setRawHeader(O2_HTTP_AUTHORIZATION_HEADER, accessTokenInAuthenticationHTTPHeaderFormat_.arg(authenticator_->token()).toLatin1()); 0273 } 0274 0275 if (!verb.isEmpty()) { 0276 request_.setRawHeader(O2_HTTP_HTTP_HEADER, verb); 0277 } 0278 0279 status_ = Requesting; 0280 error_ = QNetworkReply::NoError; 0281 return id_; 0282 } 0283 0284 void O2Requestor::finish() { 0285 QByteArray data; 0286 if (status_ == Idle) { 0287 qWarning() << "O2Requestor::finish: No pending request"; 0288 return; 0289 } 0290 data = reply_->readAll(); 0291 status_ = Idle; 0292 timedReplies_.remove(reply_); 0293 reply_->disconnect(this); 0294 reply_->deleteLater(); 0295 QList<QNetworkReply::RawHeaderPair> headers = reply_->rawHeaderPairs(); 0296 Q_EMIT finished(id_, error_, data); 0297 Q_EMIT finished(id_, error_, reply_->errorString(), data); 0298 Q_EMIT finished(id_, error_, data, headers); 0299 Q_EMIT finished(id_, error_, reply_->errorString(), data, headers); 0300 } 0301 0302 void O2Requestor::retry() { 0303 if (status_ != Requesting) { 0304 qWarning() << "O2Requestor::retry: No pending request"; 0305 return; 0306 } 0307 timedReplies_.remove(reply_); 0308 reply_->disconnect(this); 0309 reply_->deleteLater(); 0310 QUrl url = url_; 0311 if (addAccessTokenInQuery_) { 0312 #if QT_VERSION < 0x050000 0313 url.addQueryItem(O2_OAUTH2_ACCESS_TOKEN, authenticator_->token()); 0314 #else 0315 QUrlQuery query(url); 0316 query.addQueryItem(O2_OAUTH2_ACCESS_TOKEN, authenticator_->token()); 0317 url.setQuery(query); 0318 #endif 0319 } 0320 request_.setUrl(url); 0321 0322 // If the service require the access token to be sent as a Authentication HTTP header, 0323 // we update the access token when retrying. 0324 if(!accessTokenInAuthenticationHTTPHeaderFormat_.isEmpty()) { 0325 request_.setRawHeader(O2_HTTP_AUTHORIZATION_HEADER, accessTokenInAuthenticationHTTPHeaderFormat_.arg(authenticator_->token()).toLatin1()); 0326 } 0327 0328 status_ = ReRequesting; 0329 switch (operation_) { 0330 case QNetworkAccessManager::GetOperation: 0331 reply_ = manager_->get(request_); 0332 break; 0333 case QNetworkAccessManager::PostOperation: 0334 reply_ = rawData_ ? manager_->post(request_, data_) : manager_->post(request_, multipartData_); 0335 break; 0336 case QNetworkAccessManager::CustomOperation: 0337 { 0338 QBuffer * buffer = new QBuffer; 0339 buffer->setData(data_); 0340 reply_ = manager_->sendCustomRequest(request_, request_.rawHeader(O2_HTTP_HTTP_HEADER), buffer); 0341 buffer->setParent(reply_); 0342 } 0343 break; 0344 case QNetworkAccessManager::PutOperation: 0345 reply_ = rawData_ ? manager_->post(request_, data_) : manager_->put(request_, multipartData_); 0346 break; 0347 case QNetworkAccessManager::HeadOperation: 0348 reply_ = manager_->head(request_); 0349 break; 0350 default: 0351 assert(!"Unspecified operation for request"); 0352 reply_ = manager_->get(request_); 0353 break; 0354 } 0355 timedReplies_.add(reply_); 0356 #if QT_VERSION < 0x051500 0357 connect(reply_, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0358 #else 0359 connect(reply_, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(onRequestError(QNetworkReply::NetworkError)), Qt::QueuedConnection); 0360 #endif 0361 connect(reply_, SIGNAL(finished()), this, SLOT(onRequestFinished()), Qt::QueuedConnection); 0362 connect(reply_, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(onUploadProgress(qint64,qint64))); 0363 } 0364 0365 #include "moc_o2requestor.cpp"