#include "hpptclient.h" //HpptClient* HpptClient::gInstance = nullptr; HpptClient::HpptClient(QObject *p): QObject(p) { connect(&mNetAccessManager, &QNetworkAccessManager::finished, this, [this](QNetworkReply *reply) { if(reply->property("data").isValid()) onHttpPostRspFinished(reply); else onHttpGetRspFinished(reply); }); } void HpptClient::clearRp(QNetworkReply *rp) { if(rp) { QString url = rp->request().url().toString(); QString postMD5 = rp->property("postMD5").toString(); QString postData = rp->property("data").toByteArray(); if(postMD5.isEmpty()) { //清理对应缓存 mDownloadDataCache.remove(url); //解除正在处理状态 mProcessingRq.remove(url); } else { //清理对应缓存 mDownloadDataCache.remove(postMD5); //解除正在处理状态 mProcessingRq.remove(postMD5); } mRedirectMap.remove(url); mRedirectMap.remove(postMD5); //qDebug() << "delete cache, url:" << url << " postMOD5:" << postMD5; rp->deleteLater(); } } void HpptClient::onHttpGetRspProgress(qint64 bytesReceived, qint64 bytesTotal) { Q_UNUSED(bytesReceived) if(sender() == NULL) { return ; } QNetworkReply* rp = qobject_cast(sender()); if(rp == NULL) { return; } //qDebug() << "http get rsp progress:" << rp->url().toString() << bytesReceived << "/" << bytesTotal; if(bytesTotal <= 0) { return; } QString url = rp->url().toString(); mDownloadDataCache[url].append(rp->readAll()); } void HpptClient::onHttpGetRspFinished(QNetworkReply *reply) { QByteArray rpData; QString url = reply->url().toString(); int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); QString strUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString(); switch(statusCode) { case 200: { rpData = mDownloadDataCache[reply->url().toString()]; QString redirectUrl = mRedirectMap[url];//重定向的url地址 if(redirectUrl.isEmpty()) emit httpGetRspReady(url, rpData); else emit httpGetRspReady(redirectUrl, rpData); } break; case 301: case 302: { if(!strUrl.isEmpty()) { QString turl = mRedirectMap[url]; if(turl.isEmpty()) mRedirectMap[strUrl] = url; else mRedirectMap[strUrl] = turl; httpGet(strUrl); } } break; default: // error { qDebug() << url << "[get error:" << statusCode << "]"; QString redirectUrl = mRedirectMap[url]; if(redirectUrl.isEmpty()) emit httpGetRspReady(url, QByteArray()); else emit httpGetRspReady(redirectUrl, QByteArray()); } break; } clearRp(reply); } void HpptClient::onHttpPostRspProgress(qint64 bytesReceived, qint64 bytesTotal){ if(sender() == NULL) return; QNetworkReply* rp = qobject_cast(sender()); if(rp == NULL) return; if(bytesTotal <= 0) return; mDownloadDataCache[rp->property("postMD5").toString()].append(rp->readAll()); } void HpptClient::onHttpPostRspFinished(QNetworkReply *reply) { QString url = reply->url().toString(); QString postMD5 = reply->property("postMD5").toString(); int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); switch(statusCode) { case 200: { auto rpData = mDownloadDataCache[postMD5]; QString redirectMD5 = mRedirectMap[postMD5]; QString redirectUrl = mRedirectMap[url]; if(redirectMD5.isEmpty() || redirectUrl.isEmpty()) emit httpPostRspReady(url, postMD5, rpData); else emit httpPostRspReady(redirectUrl, redirectMD5, rpData); } break; case 301: case 302: { auto redireUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString(); if(!redireUrl.isEmpty()) { QString turl = mRedirectMap[url];//direct by if(turl.isEmpty()) mRedirectMap[redireUrl] = url; else mRedirectMap[redireUrl] = turl; QByteArray postData = reply->property("data").toByteArray(); QByteArray d = redireUrl.toUtf8() + postData; QString md5 = QCryptographicHash::hash(d, QCryptographicHash::Md5); QString tPostMD5 = mRedirectMap[md5];//direct by if(tPostMD5.isEmpty()) mRedirectMap[md5] = postMD5; else mRedirectMap[md5] = tPostMD5; httpPost(redireUrl, postData); } } break; default: QString redirectMD5 = mRedirectMap[postMD5]; QString redirectUrl = mRedirectMap[url]; if(redirectMD5.isEmpty() || redirectUrl.isEmpty()) { emit httpPostRspReady(url, postMD5, QByteArray()); } else { emit httpPostRspReady(redirectUrl, redirectMD5, QByteArray()); } break; } clearRp(reply); } void HpptClient::httpGet(const QString &url) { if(mProcessingRq.value(url, false)) return;//ignore when rq processing auto values = mRedirectMap.values(); for(int i = 0; i < values.count(); i++) if(values[i] == url) return;//ignore when redirect processing mProcessingRq.insert(url, true); QNetworkRequest request{url}; QSslConfiguration config = request.sslConfiguration(); config.setPeerVerifyMode(QSslSocket::VerifyNone); config.setProtocol(QSsl::TlsV1SslV3); request.setSslConfiguration(config); QNetworkReply* rp = mNetAccessManager.get(request); connect(rp, &QNetworkReply::downloadProgress, this, &HpptClient::onHttpGetRspProgress); } QByteArray HpptClient::httpPost(const QString &url, const QByteArray &data) { QByteArray md5 = QCryptographicHash::hash(url.toUtf8() + data, QCryptographicHash::Md5); if(mProcessingRq.value(md5, false)) return md5;//ignore when rq processing auto values = mRedirectMap.values(); for(int i=0; i < values.count(); i++) if(values[i] == md5) return md5; //ignore when redirect processing mProcessingRq.insert(md5, true); QNetworkRequest request{url}; request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");//add by alahover 20200304 QNetworkReply* reply = mNetAccessManager.post(request, data); reply->setProperty("postMD5", md5); reply->setProperty("url", url); reply->setProperty("data", data); connect(reply, &QNetworkReply::downloadProgress, this, &HpptClient::onHttpPostRspProgress); return md5; }