#include "FluHttp.h" #include #include #include #include #include #include #include "MainThread.h" #include "FluApp.h" FluHttp::FluHttp(QObject *parent) : QObject{parent} { retry(3); timeout(15000); } FluHttp::~FluHttp(){ cancel(); } void FluHttp::cancel(){ foreach (QPointer item, _cache) { if(item){ item->abort(); } } } void FluHttp::handleReply(QNetworkReply* reply){ _cache.append(reply); } void FluHttp::post(QString url,QJSValue callable,QMap params,QMap headers){ QMap data = invokeIntercept(params,headers,"post").toMap(); QThreadPool::globalInstance()->start([=](){ onStart(callable); for (int i = 0; i < retry(); ++i) { QNetworkAccessManager manager; manager.setTransferTimeout(timeout()); QUrl _url(url); QNetworkRequest request(_url); addHeaders(&request,data["headers"].toMap()); QHttpMultiPart multiPart(QHttpMultiPart::FormDataType); QString contentType = QString("multipart/form-data;boundary=%1").arg(multiPart.boundary()); request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); for (const auto& each : data["params"].toMap().toStdMap()) { const QString& key = each.first; const QString& value = each.second.toString(); QString dispositionHeader = QString("form-data; name=\"%1\"").arg(key); QHttpPart part; part.setHeader(QNetworkRequest::ContentDispositionHeader, dispositionHeader); part.setBody(value.toUtf8()); multiPart.append(part); } QEventLoop loop; QNetworkReply* reply = manager.post(request,&multiPart); _cache.append(reply); connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){ loop.quit(); }); loop.exec(); QString result = QString::fromUtf8(reply->readAll()); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); QString errorString = reply->errorString(); bool isSuccess = reply->error() == QNetworkReply::NoError; _cache.removeOne(reply); reply->deleteLater(); reply = nullptr; if (isSuccess) { onSuccess(callable,result); break; }else{ if(i == retry()-1){ onError(callable,status,errorString); } } } onFinish(callable); }); } void FluHttp::postString(QString url,QJSValue callable,QString params,QMap headers){ QMap data = invokeIntercept(params,headers,"postString").toMap(); QThreadPool::globalInstance()->start([=](){ onStart(callable); for (int i = 0; i < retry(); ++i) { QNetworkAccessManager manager; manager.setTransferTimeout(timeout()); QUrl _url(url); QNetworkRequest request(_url); addHeaders(&request,data["headers"].toMap()); QString contentType = QString("text/plain;charset=utf-8"); request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); QEventLoop loop; QNetworkReply* reply = manager.post(request,params.toUtf8()); _cache.append(reply); connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){ loop.quit(); }); loop.exec(); QString result = QString::fromUtf8(reply->readAll()); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); QString errorString = reply->errorString(); bool isSuccess = reply->error() == QNetworkReply::NoError; _cache.removeOne(reply); reply->deleteLater(); reply = nullptr; if (isSuccess) { onSuccess(callable,result); break; }else{ if(i == retry()-1){ onError(callable,status,errorString); } } } onFinish(callable); }); } void FluHttp::postJson(QString url,QJSValue callable,QMap params,QMap headers){ QMap data = invokeIntercept(params,headers,"postJson").toMap(); QThreadPool::globalInstance()->start([=](){ onStart(callable); for (int i = 0; i < retry(); ++i) { QNetworkAccessManager manager; manager.setTransferTimeout(timeout()); QUrl _url(url); QNetworkRequest request(_url); addHeaders(&request,data["headers"].toMap()); QString contentType = QString("application/json;charset=utf-8"); request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); QEventLoop loop; QNetworkReply* reply = manager.post(request,QJsonDocument::fromVariant(data["params"]).toJson()); _cache.append(reply); connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){ loop.quit(); }); loop.exec(); QString result = QString::fromUtf8(reply->readAll()); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); QString errorString = reply->errorString(); bool isSuccess = reply->error() == QNetworkReply::NoError; _cache.removeOne(reply); reply->deleteLater(); reply = nullptr; if (isSuccess) { onSuccess(callable,result); break; }else{ if(i == retry()-1){ onError(callable,status,errorString); } } } onFinish(callable); }); } void FluHttp::get(QString url,QJSValue callable,QMap params,QMap headers){ QMap data = invokeIntercept(params,headers,"get").toMap(); QThreadPool::globalInstance()->start([=](){ for (int i = 0; i < retry(); ++i) { onStart(callable); QNetworkAccessManager manager; manager.setTransferTimeout(timeout()); QUrl _url(url); addQueryParam(&_url,data["params"].toMap()); QNetworkRequest request(_url); addHeaders(&request,data["headers"].toMap()); QEventLoop loop; QNetworkReply* reply = manager.get(request); _cache.append(reply); connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){ loop.quit(); }); loop.exec(); QString result = QString::fromUtf8(reply->readAll()); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); QString errorString = reply->errorString(); bool isSuccess = reply->error() == QNetworkReply::NoError; _cache.removeOne(reply); reply->deleteLater(); reply = nullptr; if (isSuccess) { onSuccess(callable,result); break; }else{ if(i == retry()-1){ onError(callable,status,errorString); } } } onFinish(callable); }); } void FluHttp::download(QString url,QJSValue callable,QString filePath,QMap params,QMap headers){ QMap data = invokeIntercept(params,headers,"download").toMap(); QThreadPool::globalInstance()->start([=](){ onStart(callable); QNetworkAccessManager manager; QUrl _url(url); addQueryParam(&_url,data["params"].toMap()); QNetworkRequest request(_url); addHeaders(&request,data["headers"].toMap()); QSharedPointer file(new QFile(filePath)); QIODevice::OpenMode mode = QIODevice::WriteOnly|QIODevice::Truncate; if (!file->open(mode)) { onError(callable,-1,QString("Url: %1 %2 Non-Writable").arg(request.url().toString(),file->fileName())); onFinish(callable); return; } QEventLoop loop; connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){ loop.quit(); }); QPointer reply = manager.get(request); _cache.append(reply); connect(reply,&QNetworkReply::downloadProgress,this,[=](qint64 bytesReceived, qint64 bytesTotal){ onDownloadProgress(callable,bytesReceived,bytesTotal); }); loop.exec(); if (reply->error() == QNetworkReply::NoError) { file->write(reply->readAll()); onSuccess(callable,filePath); }else{ onError(callable,reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(),reply->errorString()); } _cache.removeOne(reply); reply->deleteLater(); reply = nullptr; onFinish(callable); }); } QVariant FluHttp::invokeIntercept(const QVariant& params,const QVariant& headers,const QString& method){ QMap requet = { {"params",params}, {"headers",headers}, {"method",method} }; if(!FluApp::getInstance()->httpInterceptor()){ return requet; } QVariant target; QMetaObject::invokeMethod(FluApp::getInstance()->httpInterceptor(), "onIntercept",Q_RETURN_ARG(QVariant,target),Q_ARG(QVariant, requet)); return target; } void FluHttp::addQueryParam(QUrl* url,const QMap& params){ QMapIterator iter(params); QUrlQuery urlQuery(*url); while (iter.hasNext()) { iter.next(); urlQuery.addQueryItem(iter.key(), iter.value().toString()); } url->setQuery(urlQuery); } void FluHttp::addHeaders(QNetworkRequest* request,const QMap& headers){ QMapIterator iter(headers); while (iter.hasNext()) { iter.next(); request->setRawHeader(iter.key().toUtf8(), iter.value().toString().toUtf8()); } } void FluHttp::onStart(const QJSValue& callable){ QJSValue onStart = callable.property("onStart"); MainThread::post([=](){onStart.call();}); } void FluHttp::onFinish(const QJSValue& callable){ QJSValue onFinish = callable.property("onFinish"); MainThread::post([=](){onFinish.call();}); } void FluHttp::onError(const QJSValue& callable,int status,QString errorString){ QJSValue onError = callable.property("onError"); QJSValueList args; args<(recv); args<(total); QJSValue onDownloadProgress = callable.property("onDownloadProgress"); MainThread::post([=](){onDownloadProgress.call(args);}); }