| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726 |
- #include "networkaccessmanager.h"
- #include "appevent.h"
- #include <QBuffer>
- #include <QCoreApplication>
- #include <QEventLoop>
- #include <QFile>
- #include <QJsonDocument>
- #include <QJsonObject>
- #include <QUrlQuery>
- // 基础URL配置
- static QString base_url("http://127.0.0.1:8200");
- static const QString messageVal = "msg";
- // static QString base_url("http://127.0.0.1:8888/api");
- static NetworkAccessManager* namInstance = nullptr;
- void cleanupNetworkAccessManager()
- {
- delete namInstance;
- namInstance = nullptr;
- }
- NetworkAccessManager* NetworkAccessManager::instance()
- {
- if (!namInstance) {
- namInstance = new NetworkAccessManager;
- qAddPostRoutine(cleanupNetworkAccessManager);
- }
- return namInstance;
- }
- NetworkAccessManager::NetworkAccessManager(QObject* parent)
- : QNetworkAccessManager(parent)
- {
- // #ifdef QT_DEBUG
- // connect(this, &QNetworkAccessManager::finished, this, [](QNetworkReply* reply) {
- // const auto data = reply->readAll();
- // reply->seek(0);
- // const auto startTimeValue = reply->property("startTime");
- // const QDateTime startTime = startTimeValue.value<QDateTime>();
- // const QDateTime endTime = QDateTime::currentDateTime();
- // qDebug() << QString("[%1] time:[%2]ms --> %3")
- // .arg(endTime.toString("yyyy-MM-dd hh:mm:ss.zzz"))
- // .arg((endTime.msecsTo(startTime)))
- // .arg(QString::fromUtf8(data));
- // });
- // #endif
- }
- QNetworkReply* NetworkAccessManager::createRequest(Operation op,
- const QNetworkRequest& request,
- QIODevice* outgoingData)
- {
- QNetworkRequest req(request);
- // 记录请求开始时间
- QDateTime startTime = QDateTime::currentDateTime();
- // 获取操作类型字符串
- QString opStr;
- switch (op) {
- case QNetworkAccessManager::GetOperation:
- opStr = "GET";
- break;
- case QNetworkAccessManager::PostOperation:
- opStr = "POST";
- break;
- case QNetworkAccessManager::PutOperation:
- opStr = "PUT";
- break;
- case QNetworkAccessManager::DeleteOperation:
- opStr = "DELETE";
- break;
- case QNetworkAccessManager::HeadOperation:
- opStr = "HEAD";
- break;
- default:
- opStr = "UNKNOWN";
- break;
- }
- qDebug() << QString("[%1] --> %2 %3")
- .arg(startTime.toString("yyyy-MM-dd hh:mm:ss.zzz"))
- .arg(opStr)
- .arg(request.url().toString());
- // 默认的请求处理
- QString agentStr = QString::fromLatin1("%1/%2 (QNetworkAccessManager %3; %4; %5; %6 bit)")
- .arg(QCoreApplication::applicationName(),
- QCoreApplication::applicationVersion(),
- QLatin1String(qVersion()),
- QSysInfo::prettyProductName(),
- QLocale::system().name())
- .arg(QSysInfo::WordSize);
- req.setRawHeader("User-Agent", agentStr.toLatin1());
- const QString token = AppEvent::instance()->jwtToken();
- if (!token.isEmpty()) {
- req.setRawHeader("Authorization", "Bearer " + token.toUtf8());
- }
- req.setRawHeader("Machine-Code", AppEvent::instance()->machineCode().toUtf8());
- req.setRawHeader("Accept-Language", AppEvent::instance()->locale().toUtf8());
- const QUrl& url = request.url();
- const QString urlPath = url.path();
- if (!urlPath.contains("/api/auth/refresh-token") && !urlPath.contains("/api/auth/login")) {
- if (AppEvent::instance()->isRefreshToken()) {
- emit AppEvent::instance()->refreshTokenNeeded();
- }
- }
- QNetworkReply* reply
- = QNetworkAccessManager::createRequest(op,
- req,
- outgoingData); // 存储开始时间,用于计算请求耗时
- reply->setProperty("startTime", startTime);
- return reply;
- }
- namespace TC {
- // 认证请求拦截器
- class AuthRequestInterceptor : public Interceptor
- {
- public:
- void interceptRequest(QNetworkRequest& request) override;
- };
- // 认证响应拦截器
- class AuthResponseInterceptor : public Interceptor
- {
- public:
- void interceptResponse(QNetworkReply* reply) override;
- private:
- void doRefreshToken();
- void doReAuthenticate();
- };
- // 错误响应拦截器
- class ErrorResponseInterceptor : public Interceptor
- {
- public:
- void interceptResponse(QNetworkReply* reply) override;
- };
- // 请求客户端实现
- RequestClient::RequestClient(const RequestClientOptions& options)
- : m_baseUrl(options.baseURL)
- {
- // 初始化默认拦截器
- if (options.enableDefaultInterceptors) {
- setupDefaultInterceptors();
- }
- }
- RequestClient* RequestClient::createClient(const QString& baseURL,
- const RequestClientOptions& options)
- {
- RequestClientOptions opts = options;
- opts.baseURL = baseURL;
- return new RequestClient(opts);
- }
- void RequestClient::setupDefaultInterceptors()
- {
- // 添加认证拦截器
- auto authRequestInterceptor = new AuthRequestInterceptor();
- addInterceptor(authRequestInterceptor);
- // 添加响应拦截器
- auto authResponseInterceptor = new AuthResponseInterceptor();
- addInterceptor(authResponseInterceptor);
- // 添加错误处理拦截器
- auto errorInterceptor = new ErrorResponseInterceptor();
- addInterceptor(errorInterceptor);
- }
- void RequestClient::addInterceptor(Interceptor* interceptor)
- {
- if (!interceptors.contains(interceptor)) {
- interceptors.append(interceptor);
- }
- }
- void RequestClient::removeInterceptor(Interceptor* interceptor)
- {
- interceptors.removeOne(interceptor);
- }
- void RequestClient::setBaseUrl(const QString& url)
- {
- m_baseUrl = url;
- }
- QString RequestClient::baseUrl() const
- {
- if (m_baseUrl.isEmpty()) {
- return base_url;
- }
- return m_baseUrl;
- }
- void RequestClient::setTimeout(int timeout)
- {
- m_timeout = timeout;
- }
- int RequestClient::timeout() const
- {
- return m_timeout;
- }
- QNetworkReply* RequestClient::getSync(const QString& url, const QVariantMap& params)
- {
- QNetworkReply* reply = get(url, params);
- // 同步等待
- QEventLoop loop;
- QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
- loop.exec();
- // 处理响应拦截器
- processResponse(reply);
- return reply;
- }
- QNetworkReply* RequestClient::postSync(const QString& url, const QJsonDocument& data)
- {
- QNetworkReply* reply = post(url, data);
- // 同步等待
- QEventLoop loop;
- QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
- loop.exec();
- // 处理响应拦截器
- processResponse(reply);
- return reply;
- }
- QNetworkReply* RequestClient::putSync(const QString& url, const QJsonDocument& data)
- {
- QNetworkReply* reply = put(url, data);
- // 同步等待
- QEventLoop loop;
- QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
- loop.exec();
- // 处理响应拦截器
- processResponse(reply);
- return reply;
- }
- QNetworkReply* RequestClient::deleteSync(const QString& url)
- {
- QNetworkReply* reply = deleteResource(url);
- // 同步等待
- QEventLoop loop;
- QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
- loop.exec();
- // 处理响应拦截器
- processResponse(reply);
- return reply;
- }
- QNetworkReply* RequestClient::uploadSync(const QString& url, QHttpMultiPart* multiPart)
- {
- QNetworkReply* reply = upload(url, multiPart);
- // 同步等待
- QEventLoop loop;
- QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
- loop.exec();
- // 处理响应拦截器
- processResponse(reply);
- return reply;
- }
- QFuture<HttpResponse> RequestClient::getAsync(const QString& url, const QVariantMap& params)
- {
- QFutureInterface<HttpResponse> interface;
- interface.reportStarted();
- QNetworkReply* reply = get(url, params);
- setupAsyncConnections(reply, interface);
- return interface.future();
- }
- QFuture<HttpResponse> RequestClient::postAsync(const QString& url, const QJsonDocument& data)
- {
- QFutureInterface<HttpResponse> interface;
- interface.reportStarted();
- QNetworkReply* reply = post(url, data);
- setupAsyncConnections(reply, interface);
- return interface.future();
- }
- QFuture<HttpResponse> RequestClient::putAsync(const QString& url, const QJsonDocument& data)
- {
- QFutureInterface<HttpResponse> interface;
- interface.reportStarted();
- QNetworkReply* reply = put(url, data);
- setupAsyncConnections(reply, interface);
- return interface.future();
- }
- QFuture<HttpResponse> RequestClient::deleteAsync(const QString& url)
- {
- QFutureInterface<HttpResponse> interface;
- interface.reportStarted();
- QNetworkReply* reply = deleteResource(url);
- setupAsyncConnections(reply, interface);
- return interface.future();
- }
- QFuture<HttpResponse> RequestClient::uploadAsync(const QString& url, QHttpMultiPart* multiPart)
- {
- QFutureInterface<HttpResponse> interface;
- interface.reportStarted();
- QNetworkReply* reply = upload(url, multiPart);
- setupAsyncConnections(reply, interface);
- return interface.future();
- }
- HttpResponse RequestClient::parseReplyData(QNetworkReply* reply)
- {
- HttpResponse response;
- if (reply->error() != QNetworkReply::NoError) {
- response.code = reply->error();
- response.message = reply->errorString();
- return response;
- }
- const QByteArray responseData = reply->readAll();
- QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData);
- qDebug() << responseData << jsonDoc;
- if (jsonDoc.isObject()) {
- const QJsonObject jsonObj = jsonDoc.object();
- qDebug() << jsonObj;
- if (jsonObj.contains("code")) {
- response.code = jsonObj["code"].toInt();
- }
- if (jsonObj.contains(messageVal)) {
- response.message = jsonObj[messageVal].toString();
- }
- if (jsonObj.contains("data")) {
- QJsonValue dataValue = jsonObj["data"];
- response.data = dataValue;
- }
- }
- return response;
- }
- void RequestClient::processRequest(QNetworkRequest& request)
- {
- for (auto interceptor : interceptors) {
- interceptor->interceptRequest(request);
- }
- }
- void RequestClient::processResponse(QNetworkReply* reply)
- {
- for (auto interceptor : interceptors) {
- interceptor->interceptResponse(reply);
- }
- }
- QNetworkReply* RequestClient::get(const QString& url, const QVariantMap& params)
- {
- QNetworkAccessManager* manager = NetworkAccessManager::instance();
- manager->setTransferTimeout(m_timeout);
- QUrl fullUrl(m_baseUrl.isEmpty() ? QString(base_url).append(url) : m_baseUrl.append(url));
- QUrlQuery query;
- for (auto it = params.constBegin(); it != params.constEnd(); ++it) {
- query.addQueryItem(it.key(), it.value().toString());
- }
- if (!params.isEmpty()) {
- fullUrl.setQuery(query);
- }
- QNetworkRequest modifiedRequest(fullUrl);
- modifiedRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
- processRequest(modifiedRequest);
- QNetworkReply* reply = manager->get(modifiedRequest);
- return reply;
- }
- QNetworkReply* RequestClient::post(const QString& url, const QJsonDocument& data)
- {
- QNetworkAccessManager* manager = NetworkAccessManager::instance();
- manager->setTransferTimeout(m_timeout);
- QUrl fullUrl(m_baseUrl.isEmpty() ? QString(base_url).append(url) : m_baseUrl.append(url));
- QBuffer* buffer = new QBuffer;
- buffer->setData(data.toJson());
- buffer->open(QIODevice::ReadOnly);
- QNetworkRequest modifiedRequest(fullUrl);
- modifiedRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
- processRequest(modifiedRequest);
- QNetworkReply* reply = manager->post(modifiedRequest, buffer);
- buffer->setParent(reply);
- return reply;
- }
- QNetworkReply* RequestClient::put(const QString& url, const QJsonDocument& data)
- {
- QNetworkAccessManager* manager = NetworkAccessManager::instance();
- manager->setTransferTimeout(m_timeout);
- QUrl fullUrl(m_baseUrl.isEmpty() ? QString(base_url).append(url) : m_baseUrl.append(url));
- QBuffer* buffer = new QBuffer;
- buffer->setData(data.toJson());
- buffer->open(QIODevice::ReadOnly);
- QNetworkRequest modifiedRequest(fullUrl);
- processRequest(modifiedRequest);
- QNetworkReply* reply = manager->put(modifiedRequest, buffer);
- buffer->setParent(reply);
- return reply;
- }
- QNetworkReply* RequestClient::deleteResource(const QString& url)
- {
- QNetworkAccessManager* manager = NetworkAccessManager::instance();
- manager->setTransferTimeout(m_timeout);
- QUrl fullUrl(m_baseUrl.isEmpty() ? QString(base_url).append(url) : m_baseUrl.append(url));
- QNetworkRequest modifiedRequest(fullUrl);
- processRequest(modifiedRequest);
- QNetworkReply* reply = manager->deleteResource(modifiedRequest);
- return reply;
- }
- QNetworkReply* RequestClient::upload(const QString& url, QHttpMultiPart* multiPart)
- {
- QNetworkAccessManager* manager = NetworkAccessManager::instance();
- manager->setTransferTimeout(m_timeout);
- QUrl fullUrl(m_baseUrl.isEmpty() ? QString(base_url).append(url) : m_baseUrl.append(url));
- QNetworkRequest modifiedRequest(fullUrl);
- QNetworkReply* reply = manager->post(modifiedRequest, multiPart);
- return reply;
- }
- bool RequestClient::download(const QString& url, const QString& saveFilePath)
- {
- QNetworkReply* reply = get(url);
- QEventLoop loop;
- QFile file(saveFilePath);
- if (!file.open(QIODevice::WriteOnly)) {
- return false;
- }
- QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
- QObject::connect(reply, &QNetworkReply::readyRead, [&]() { file.write(reply->readAll()); });
- loop.exec();
- file.close();
- return reply->error() == QNetworkReply::NoError;
- }
- void RequestClient::setupAsyncConnections(QNetworkReply* reply,
- QFutureInterface<HttpResponse>& _interface)
- { // 处理网络错误信号
- QObject::connect(reply,
- &QNetworkReply::errorOccurred,
- [this, reply, _interface](QNetworkReply::NetworkError error) mutable {
- // 避免重复处理
- if (reply->property("handled").toBool()) {
- return;
- }
- reply->setProperty("handled", true);
- this->processResponse(reply);
- HttpResponse errorResponse;
- errorResponse.code = error;
- errorResponse.message = reply->errorString();
- // 特殊处理网络错误类型
- if (error == QNetworkReply::OperationCanceledError) {
- errorResponse.message = "请求被取消";
- } else if (error == QNetworkReply::TimeoutError) {
- errorResponse.message = "请求超时";
- } else if (error == QNetworkReply::ConnectionRefusedError) {
- errorResponse.message = "连接被拒绝";
- } else if (error == QNetworkReply::HostNotFoundError) {
- errorResponse.message = "找不到主机";
- }
- _interface.reportResult(errorResponse);
- _interface.reportFinished();
- });
- // 处理完成信号
- QObject::connect(reply, &QNetworkReply::finished, [this, reply, _interface]() mutable {
- // 避免重复处理
- if (reply->property("handled").toBool()) {
- reply->deleteLater();
- return;
- }
- reply->setProperty("handled", true);
- processResponse(reply);
- try {
- // 即使在 finished 信号中,也需要检查是否有错误
- if (reply->error() != QNetworkReply::NoError) {
- HttpResponse errorResponse;
- errorResponse.code = reply->error();
- errorResponse.message = reply->errorString();
- _interface.reportResult(errorResponse);
- } else {
- HttpResponse response = parseReplyData(reply);
- _interface.reportResult(response);
- }
- _interface.reportFinished();
- } catch (const std::exception& e) {
- HttpResponse errorResponse;
- errorResponse.code = -1;
- errorResponse.message = QString::fromUtf8(e.what());
- _interface.reportResult(errorResponse);
- _interface.reportFinished();
- }
- reply->deleteLater();
- });
- }
- // 拦截器实现
- void AuthRequestInterceptor::interceptRequest(QNetworkRequest& request)
- {
- const QString token = AppEvent::instance()->jwtToken();
- if (!token.isEmpty()) {
- request.setRawHeader("Authorization", "Bearer " + token.toUtf8());
- }
- request.setRawHeader("Machine-Code", AppEvent::instance()->machineCode().toUtf8());
- request.setRawHeader("Accept-Language", AppEvent::instance()->locale().toUtf8());
- }
- void AuthResponseInterceptor::interceptResponse(QNetworkReply* reply)
- {
- // 检查是否需要刷新token
- if (reply->error() == QNetworkReply::AuthenticationRequiredError) {
- // 触发token刷新
- emit AppEvent::instance()->refreshTokenNeeded();
- // 如果启用了自动刷新token,可以在这里实现
- if (AppEvent::instance()->isEnableRefreshToken()) {
- doRefreshToken();
- } else {
- doReAuthenticate();
- }
- }
- }
- void AuthResponseInterceptor::doRefreshToken()
- {
- // 实现刷新token的逻辑
- RequestClient refreshClient;
- QJsonObject emptyData;
- QJsonDocument jsonDoc(emptyData);
- QNetworkReply* reply = refreshClient.postSync("/api/auth/refresh-token", jsonDoc);
- if (reply->error() == QNetworkReply::NoError) {
- QByteArray responseData = reply->readAll();
- QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData);
- QJsonObject jsonObject = jsonResponse.object();
- if (jsonObject.contains("data")) {
- QString newToken = jsonObject["data"].toString();
- AppEvent::instance()->setJwtToken(newToken);
- }
- } else {
- // 刷新失败,需要重新登录
- doReAuthenticate();
- }
- reply->deleteLater();
- }
- void AuthResponseInterceptor::doReAuthenticate()
- {
- // 实现重新认证的逻辑
- AppEvent::instance()->setJwtToken("");
- emit AppEvent::instance()->loginExpired(true);
- }
- void ErrorResponseInterceptor::interceptResponse(QNetworkReply* reply)
- {
- if (reply->error() != QNetworkReply::NoError) {
- // 解析错误信息
- QByteArray responseData = reply->readAll();
- QString errorMessage;
- try {
- QJsonDocument jsonResponse = QJsonDocument::fromJson(responseData);
- QJsonObject jsonObject = jsonResponse.object();
- if (jsonObject.contains("error")) {
- errorMessage = jsonObject["error"].toString();
- } else if (jsonObject.contains(messageVal)) {
- errorMessage = jsonObject[messageVal].toString();
- }
- } catch (...) {
- // 解析失败,使用默认错误信息
- }
- if (errorMessage.isEmpty()) {
- errorMessage = reply->errorString();
- }
- // 发送错误信息
- emit AppEvent::instance()->errorMessage(errorMessage);
- // 可以根据不同的错误类型进行不同的处理
- switch (reply->error()) {
- case QNetworkReply::ConnectionRefusedError:
- qDebug() << "连接被拒绝" << errorMessage;
- break;
- case QNetworkReply::RemoteHostClosedError:
- qDebug() << "远程主机关闭连接" << errorMessage;
- break;
- case QNetworkReply::HostNotFoundError:
- qDebug() << "主机未找到" << errorMessage;
- break;
- case QNetworkReply::TimeoutError:
- qDebug() << "连接超时" << errorMessage;
- break;
- case QNetworkReply::OperationCanceledError:
- qDebug() << "操作被取消" << errorMessage;
- break;
- case QNetworkReply::SslHandshakeFailedError:
- qDebug() << "SSL握手失败" << errorMessage;
- break;
- case QNetworkReply::TemporaryNetworkFailureError:
- qDebug() << "临时网络故障" << errorMessage;
- break;
- case QNetworkReply::NetworkSessionFailedError:
- qDebug() << "网络会话失败" << errorMessage;
- break;
- case QNetworkReply::BackgroundRequestNotAllowedError:
- qDebug() << "不允许后台请求" << errorMessage;
- break;
- case QNetworkReply::ContentReSendError:
- qDebug() << "内容重发错误" << errorMessage;
- break;
- default:
- qDebug() << "其他网络错误" << errorMessage;
- break;
- }
- }
- }
- // 创建全局客户端实例
- static RequestClient* requestClientInstance = nullptr;
- static RequestClient* baseRequestClientInstance = nullptr;
- RequestClient* RequestClient::requestClient(const RequestClientOptions& defaultOptions)
- {
- if (!requestClientInstance) {
- RequestClientOptions options = defaultOptions;
- options.enableDefaultInterceptors = true;
- options.responseReturn = "data";
- requestClientInstance = createClient(options.baseURL, options);
- }
- return requestClientInstance;
- }
- RequestClient* RequestClient::baseRequestClient(const RequestClientOptions& defaultOptions)
- {
- if (!baseRequestClientInstance) {
- RequestClientOptions options = defaultOptions;
- options.enableDefaultInterceptors = false;
- options.responseReturn = "data";
- baseRequestClientInstance = createClient(options.baseURL, options);
- }
- return baseRequestClientInstance;
- }
- } // namespace TC
|