From 74db5158023406ca78e0d33b17b29c57ead2f122 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Tue, 14 Feb 2017 04:10:50 +0100 Subject: [PATCH] refs #882, support for 30x redirect and some more utility functions * CNetworkUtils::setSwiftClientSslCertificate for shared URLs * redirect functions --- src/blackmisc/network/networkutils.cpp | 67 +++++++++++++++++++++++--- src/blackmisc/network/networkutils.h | 30 ++++++++++-- 2 files changed, 85 insertions(+), 12 deletions(-) diff --git a/src/blackmisc/network/networkutils.cpp b/src/blackmisc/network/networkutils.cpp index b01316a2b..a3d07bb1b 100644 --- a/src/blackmisc/network/networkutils.cpp +++ b/src/blackmisc/network/networkutils.cpp @@ -257,6 +257,19 @@ namespace BlackMisc request.setSslConfiguration(sslConfiguration); } + void CNetworkUtils::setSwiftClientSslCertificate(QNetworkRequest &request, const CUrlList &swiftSharedUrls) + { + for (const CUrl &sharedUrl : swiftSharedUrls) + { + const QString urlString = request.url().toString(); + if (urlString.startsWith(sharedUrl.toQString())) + { + CNetworkUtils::setSwiftClientSslCertificate(request); + break; + } + } + } + QHttpPart CNetworkUtils::getMultipartWithDebugFlag() { QHttpPart textPartDebug; @@ -309,15 +322,55 @@ namespace BlackMisc qint64 CNetworkUtils::lastModifiedMsSinceEpoch(QNetworkReply *nwReply) { - if (nwReply) + Q_ASSERT(nwReply); + const QDateTime lm = CNetworkUtils::lastModifiedDateTime(nwReply); + return lm.isValid() ? lm.toMSecsSinceEpoch() : -1; + } + + QDateTime CNetworkUtils::lastModifiedDateTime(QNetworkReply *nwReply) + { + Q_ASSERT(nwReply); + const QVariant lastModifiedQv = nwReply->header(QNetworkRequest::LastModifiedHeader); + if (lastModifiedQv.isValid() && lastModifiedQv.canConvert()) { - QVariant lastModifiedQv = nwReply->header(QNetworkRequest::LastModifiedHeader); - if (lastModifiedQv.isValid() && lastModifiedQv.canConvert()) - { - return lastModifiedQv.value().toMSecsSinceEpoch(); - } + return lastModifiedQv.value(); } - return -1; + return QDateTime(); + } + + qint64 CNetworkUtils::lastModifiedSinceNow(QNetworkReply *nwReply) + { + const qint64 sinceEpoch = CNetworkUtils::lastModifiedMsSinceEpoch(nwReply); + return sinceEpoch > 0 ? std::max(0LL, QDateTime::currentMSecsSinceEpoch() - sinceEpoch) : QDateTime::currentMSecsSinceEpoch(); + } + + int CNetworkUtils::getHttpStatusCode(QNetworkReply *nwReply) + { + if (!nwReply) { return -1; } + const QVariant statusCode = nwReply->attribute(QNetworkRequest::HttpStatusCodeAttribute); + if (!statusCode.isValid()) { return -1; } + const int status = statusCode.toInt(); + return status; + } + + bool CNetworkUtils::isHttpStatusRedirect(QNetworkReply *nwReply) + { + if (!nwReply) { return false; } + const int code = CNetworkUtils::getHttpStatusCode(nwReply); + return code == 301 || code == 302 || code == 303 || code == 307; + } + + QUrl CNetworkUtils::getHttpRedirectUrl(QNetworkReply *nwReply) + { + if (!nwReply) { return QUrl(); } + const QVariant possibleRedirectUrl = nwReply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (!possibleRedirectUrl.isValid()) { return QUrl(); } + QUrl redirectUrl = possibleRedirectUrl.toUrl(); + if (redirectUrl.isRelative()) + { + redirectUrl = nwReply->url().resolved(redirectUrl); + } + return redirectUrl; } QString CNetworkUtils::removeHtmlPartsFromPhpErrorMessage(const QString &errorMessage) diff --git a/src/blackmisc/network/networkutils.h b/src/blackmisc/network/networkutils.h index 454f7aec9..47b6bbdaf 100644 --- a/src/blackmisc/network/networkutils.h +++ b/src/blackmisc/network/networkutils.h @@ -13,7 +13,7 @@ #define BLACKMISC_NETWORKUTILS_H #include "blackmisc/blackmiscexport.h" -#include "blackmisc/network/url.h" +#include "blackmisc/network/urllist.h" #include #include @@ -52,7 +52,6 @@ namespace BlackMisc //! Is a connected interface available? //! \param withDebugOutput enables some debugging output - //! \return static bool hasConnectedInterface(bool withDebugOutput = false); //! Can connect? @@ -60,14 +59,12 @@ namespace BlackMisc //! \param port 80, 1234 //! \param timeoutMs //! \param message human readable message - //! \return static bool canConnect(const QString &hostAddress, int port, QString &message, int timeoutMs = getTimeoutMs()); //! Can connect to server? //! \param server //! \param message human readable message //! \param timeoutMs - //! \return static bool canConnect(const BlackMisc::Network::CServer &server, QString &message, int timeoutMs = getTimeoutMs()); //! Can connect to URL? @@ -106,9 +103,12 @@ namespace BlackMisc //! Set user agent for request static void setSwiftUserAgent(QNetworkRequest &request); - //! Set swift client ssl certificate + //! Set swift client SSL certificate static void setSwiftClientSslCertificate(QNetworkRequest &request); + //! Set swift client SSL certificate + static void setSwiftClientSslCertificate(QNetworkRequest &request, const BlackMisc::Network::CUrlList &swiftSharedUrls); + //! Multipart with DEBUG FLAG for server static QHttpPart getMultipartWithDebugFlag(); @@ -130,6 +130,26 @@ namespace BlackMisc //! Last modified from reply static qint64 lastModifiedMsSinceEpoch(QNetworkReply *nwReply); + //! Last modified from reply + static QDateTime lastModifiedDateTime(QNetworkReply *nwReply); + + //! Last modified from reply compared with now (in ms) + static qint64 lastModifiedSinceNow(QNetworkReply *nwReply); + + //! Get the http status code + static int getHttpStatusCode(QNetworkReply *nwReply); + + //! Is the reply an HTTP redirect? + //! \details Status codes: + //! - 301: Permanent redirect. Clients making subsequent requests for this resource should use the new URI. Clients should not follow the redirect automatically for POST/PUT/DELETE requests. + //! - 302: Redirect for undefined reason. Clients making subsequent requests for this resource should not use the new URI. Clients should not follow the redirect automatically for POST/PUT/DELETE requests. + //! - 303: Redirect for undefined reason. Typically, 'Operation has completed, continue elsewhere.' Clients making subsequent requests for this resource should not use the new URI. Clients should follow the redirect for POST/PUT/DELETE requests. + //! - 307: Temporary redirect. Resource may return to this location at a later point. Clients making subsequent requests for this resource should use the old URI. Clients should not follow the redirect automatically for POST/PUT/DELETE requests. + static bool isHttpStatusRedirect(QNetworkReply *nwReply); + + //! Get the redirect URL if any + static QUrl getHttpRedirectUrl(QNetworkReply *nwReply); + //! Remove the HTML formatting from a PHP error message static QString removeHtmlPartsFromPhpErrorMessage(const QString &errorMessage);