#include "httpRequestManager.h" #include #include #include HttpRequestManager::HttpRequestManager(QObject* parent) : QObject(parent) { } HttpRequestManager::~HttpRequestManager() { for(auto& config : m_endpoints) { if(config.activeReply) { config.activeReply->abort(); config.activeReply->deleteLater(); config.activeReply = nullptr; } if(config.timeoutTimer) { config.timeoutTimer->stop(); config.timeoutTimer->deleteLater(); config.timeoutTimer = nullptr; } } } void HttpRequestManager::sendRequest(EndpointConfig& config) { QNetworkRequest request(config.url); for(auto it = config.headers.constBegin(); it != config.headers.constEnd(); ++it) request.setRawHeader(it.key(), it.value()); QNetworkReply* reply = nullptr; if(config.method == "GET") reply = m_networkManager.get(request); else if(config.method == "POST") reply = m_networkManager.post(request, config.body); else if(config.method == "PUT") reply = m_networkManager.put(request, config.body); else if(config.method == "DELETE") reply = m_networkManager.deleteResource(request); else { qWarning() << "Unsupported HTTP method:" << config.method; emit requestFailed(config.dataKey, "Unsupported HTTP method"); return; } connect(reply, &QNetworkReply::finished, this, &HttpRequestManager::onReplyFinished); connect(reply, &QNetworkReply::errorOccurred, this, &HttpRequestManager::onReplyError); config.timeoutTimer = new QTimer(this); config.timeoutTimer->setSingleShot(true); config.timeoutTimer->setInterval(m_defaultTimeout); connect(config.timeoutTimer, &QTimer::timeout, this, [this, &config](){ handleRequestTimeout(config.dataKey); }); } void HttpRequestManager::handleResponse(const QString& dataKey, QNetworkReply* reply) { if(!m_endpoints.contains(dataKey)) { qWarning() << "Recived response for unregistered dataKey:" << dataKey; reply->deleteLater(); return; } EndpointConfig& config = m_endpoints[dataKey]; //关闭超时重连定时器 if(config.timeoutTimer) { config.timeoutTimer->stop(); config.timeoutTimer->deleteLater(); config.timeoutTimer = nullptr; } if(reply->error() != QNetworkReply::NoError) return; //具体错误信息在onReplyError中进行处理 QByteArray responseData = reply->readAll(); QString contentType = reply->header(QNetworkRequest::ContentTypeHeader).toString(); if(contentType.contains("application/json")) parseJsonResponse(dataKey, responseData); else if(contentType.contains("text/")) parseTextResponse(dataKey, responseData); else parseBinaryResponse(dataKey, responseData); //数据重置 reply->deleteLater(); config.retryCount = 0; config.activeReply = nullptr; } void HttpRequestManager::handleRequestTimeout(const QString& dataKey) { if(!m_endpoints.contains(dataKey)) return; EndpointConfig& config = m_endpoints[dataKey]; qWarning() << "Request timeout for dataKey: " << dataKey; if(config.activeReply) config.activeReply->abort(); //重试 if(config.retryCount < config.maxRetries) scheduleRetry(config.dataKey); else { emit requestFailed(config.dataKey, "Request timed out"); config.retryCount = 0; } } void HttpRequestManager::scheduleRetry(const QString& dataKey) { if(!m_endpoints.contains(dataKey)) return; EndpointConfig& config = m_endpoints[dataKey]; config.retryCount++; QTimer::singleShot(config.retryInterval, this, [this, dataKey](){ requestData(dataKey); }); } void HttpRequestManager::parseJsonResponse(const QString& dataKey, const QByteArray& data) { QJsonParseError parseError; QJsonDocument document = QJsonDocument::fromJson(data, &parseError); if(document.isNull()) { emit requestFailed(dataKey, "get JSonDocument failed"); return; } if(parseError.error != QJsonParseError::NoError) { emit requestFailed(dataKey, "JSON parse error: " + parseError.errorString()); return; } if(document.isObject()) emit dataReceived(dataKey, document.object().toVariantMap()); else if(document.isArray()) emit dataReceived(dataKey, document.array().toVariantList()); else emit dataReceived(dataKey, QVariant()); } void HttpRequestManager::parseTextResponse(const QString& dataKey, const QByteArray& data) { emit dataReceived(dataKey, QString::fromUtf8(data)); } void HttpRequestManager::parseBinaryResponse(const QString& dataKey, const QByteArray& data) { emit dataReceived(dataKey, data); } void HttpRequestManager::registerEndpoint(const QString& dataKey, const QUrl& url, const QByteArray& method, const QByteArray& body, const QMap& headers) { EndpointConfig config; config.dataKey = dataKey; config.url = url; config.method = method.toUpper(); config.body = body; config.headers = headers; config.maxRetries = m_maxRetries; config.retryInterval = m_retryIntrval; m_endpoints[dataKey] = config; } void HttpRequestManager::requestData(const QString& dataKey) { if(!m_endpoints.contains(dataKey)) { qWarning() << "This dataKey is not present in endpoints: " << dataKey; emit requestFailed(dataKey, "dataKey is not present in endpoints"); return; } EndpointConfig& config = m_endpoints[dataKey]; if(config.activeReply) { config.activeReply->abort(); config.activeReply->deleteLater(); config.activeReply = nullptr; } if(config.timeoutTimer) { config.timeoutTimer->stop(); config.timeoutTimer->deleteLater(); config.timeoutTimer = nullptr; } sendRequest(config); } void HttpRequestManager::cancleRequest(const QString& dataKey) { if(!m_endpoints.contains(dataKey)) return; EndpointConfig& config = m_endpoints[dataKey]; if(config.activeReply) { config.activeReply->abort(); config.activeReply->deleteLater(); config.activeReply = nullptr; } if(config.timeoutTimer) { config.timeoutTimer->stop(); config.timeoutTimer->deleteLater(); config.timeoutTimer = nullptr; } config.retryCount = 0; } void HttpRequestManager::setDefaultTimeout(int ms) { m_defaultTimeout = qMax(1000, ms); } void HttpRequestManager::setRetryPolicy(int maxRetries, int retryInterval) { m_maxRetries = qMax(0, maxRetries); m_retryIntrval = qMax(500, retryInterval); //更新所以已注册端点的充实策略 for(auto& config : m_endpoints) { config.maxRetries = m_maxRetries; config.retryInterval = m_retryIntrval; } } bool HttpRequestManager::hasVaildEndpoint(const QString& dataKey) { return m_endpoints.contains(dataKey) && m_endpoints[dataKey].url.isEmpty(); } void HttpRequestManager::onReplyFinished() { QNetworkReply* reply = qobject_cast(sender()); if(!reply) return; QString dataKey; for(auto& config : m_endpoints) { if(config.activeReply == reply) { dataKey = config.dataKey; break; } } if(dataKey.isEmpty()) { reply->deleteLater(); return; } handleResponse(dataKey, reply); } void HttpRequestManager::onReplyError(QNetworkReply::NetworkError code) { Q_UNUSED(code); QNetworkReply* reply = qobject_cast(sender()); if(!reply) return; QString dataKey; for(auto& config : m_endpoints) { if(config.activeReply == reply) { dataKey = config.dataKey; break; } } if(dataKey.isEmpty()) return; EndpointConfig& config = m_endpoints[dataKey]; //关闭超时重连定时器 if(config.timeoutTimer) { config.timeoutTimer->stop(); config.timeoutTimer->deleteLater(); config.timeoutTimer = nullptr; } //打印错误 QString error = reply->errorString(); qWarning() << "HTTP request failed for " << dataKey << ":" << error; //重试 if(config.retryCount < config.maxRetries) scheduleRetry(dataKey); else { emit requestFailed(dataKey, error); config.retryCount = 0; } reply->deleteLater(); config.activeReply = nullptr; }