From 0119f0a43bf2356f9f1f7ed83ed7abe5777b2dcf Mon Sep 17 00:00:00 2001 From: Juha Vuolle Date: Mon, 26 Feb 2024 11:59:37 +0200 Subject: [PATCH] Add QNetworkRequest attribute support to QNetworkRequestFactory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ChangeLog][QtNetwork][QNetworkRequestFactory] Add QNetworkRequest attribute support to QNetworkRequestFactory Fixes: QTBUG-122397 Change-Id: Ie73f104cdad9f8f0721d8ee28f79095bfb04fb3c Reviewed-by: MÃ¥rten Nordheim Reviewed-by: Ivan Solovev --- src/network/access/qnetworkrequestfactory.cpp | 94 +++++++++++++++++++ src/network/access/qnetworkrequestfactory.h | 8 ++ src/network/access/qnetworkrequestfactory_p.h | 3 + .../tst_qnetworkrequestfactory.cpp | 51 ++++++++++ 4 files changed, 156 insertions(+) diff --git a/src/network/access/qnetworkrequestfactory.cpp b/src/network/access/qnetworkrequestfactory.cpp index 081ff8ac8f3..c9b94f77077 100644 --- a/src/network/access/qnetworkrequestfactory.cpp +++ b/src/network/access/qnetworkrequestfactory.cpp @@ -506,6 +506,96 @@ QNetworkRequest::Priority QNetworkRequestFactory::priority() const return d->priority; } +/*! + \since 6.8 + + Sets the value associated with \a attribute to \a value. + If the attribute is already set, the previous value is + replaced. The attributes are set to any future requests + created by this factory. + + \sa attribute(), clearAttribute(), clearAttributes(), + QNetworkRequest::Attribute +*/ +void QNetworkRequestFactory::setAttribute(QNetworkRequest::Attribute attribute, + const QVariant &value) +{ + if (attribute == QNetworkRequest::HttpStatusCodeAttribute + || attribute == QNetworkRequest::HttpReasonPhraseAttribute + || attribute == QNetworkRequest::RedirectionTargetAttribute + || attribute == QNetworkRequest::ConnectionEncryptedAttribute + || attribute == QNetworkRequest::SourceIsFromCacheAttribute + || attribute == QNetworkRequest::HttpPipeliningWasUsedAttribute + || attribute == QNetworkRequest::Http2WasUsedAttribute + || attribute == QNetworkRequest::OriginalContentLengthAttribute) + { + qCWarning(lcQrequestfactory, "%i is a reply-only attribute, ignoring.", attribute); + return; + } + d.detach(); + d->attributes.insert(attribute, value); +} + +/*! + \since 6.8 + + Returns the value associated with \a attribute. If the + attribute has not been set, returns a default-constructed \l QVariant. + + \sa attribute(QNetworkRequest::Attribute, const QVariant &), + setAttribute(), clearAttributes(), QNetworkRequest::Attribute + +*/ +QVariant QNetworkRequestFactory::attribute(QNetworkRequest::Attribute attribute) const +{ + return d->attributes.value(attribute); +} + +/*! + \since 6.8 + + Returns the value associated with \a attribute. If the + attribute has not been set, returns \a defaultValue. + + \sa attribute(), setAttribute(), clearAttributes(), + QNetworkRequest::Attribute +*/ +QVariant QNetworkRequestFactory::attribute(QNetworkRequest::Attribute attribute, + const QVariant &defaultValue) const +{ + return d->attributes.value(attribute, defaultValue); +} + +/*! + \since 6.8 + + Clears \a attribute set to this factory. + + \sa attribute(), setAttribute() +*/ +void QNetworkRequestFactory::clearAttribute(QNetworkRequest::Attribute attribute) +{ + if (!d->attributes.contains(attribute)) + return; + d.detach(); + d->attributes.remove(attribute); +} + +/*! + \since 6.8 + + Clears any attributes set to this factory. + + \sa attribute(), setAttribute() +*/ +void QNetworkRequestFactory::clearAttributes() +{ + if (d->attributes.isEmpty()) + return; + d.detach(); + d->attributes.clear(); +} + QNetworkRequestFactoryPrivate::QNetworkRequestFactoryPrivate() = default; @@ -539,6 +629,10 @@ QNetworkRequest QNetworkRequestFactoryPrivate::newRequest(const QUrl &url) const request.setTransferTimeout(transferTimeout); request.setPriority(priority); + + for (const auto &[attribute, value] : attributes.asKeyValueRange()) + request.setAttribute(attribute, value); + return request; } diff --git a/src/network/access/qnetworkrequestfactory.h b/src/network/access/qnetworkrequestfactory.h index ea887ea05b9..c170b75c8e9 100644 --- a/src/network/access/qnetworkrequestfactory.h +++ b/src/network/access/qnetworkrequestfactory.h @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -77,6 +78,13 @@ public: Q_NETWORK_EXPORT void setPriority(QNetworkRequest::Priority priority); Q_NETWORK_EXPORT QNetworkRequest::Priority priority() const; + Q_NETWORK_EXPORT QVariant attribute(QNetworkRequest::Attribute attribute) const; + Q_NETWORK_EXPORT QVariant attribute(QNetworkRequest::Attribute attribute, + const QVariant &defaultValue) const; + Q_NETWORK_EXPORT void setAttribute(QNetworkRequest::Attribute attribute, const QVariant &value); + Q_NETWORK_EXPORT void clearAttribute(QNetworkRequest::Attribute attribute); + Q_NETWORK_EXPORT void clearAttributes(); + private: #ifndef QT_NO_DEBUG_STREAM friend Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QNetworkRequestFactory &reply); diff --git a/src/network/access/qnetworkrequestfactory_p.h b/src/network/access/qnetworkrequestfactory_p.h index e98a1f7bb9d..4116669f215 100644 --- a/src/network/access/qnetworkrequestfactory_p.h +++ b/src/network/access/qnetworkrequestfactory_p.h @@ -20,9 +20,11 @@ #if QT_CONFIG(ssl) #include #endif +#include #include #include #include +#include QT_BEGIN_NAMESPACE @@ -46,6 +48,7 @@ public: QUrlQuery queryParameters; QNetworkRequest::Priority priority = QNetworkRequest::NormalPriority; std::chrono::milliseconds transferTimeout{0}; + QHash attributes; }; QT_END_NAMESPACE diff --git a/tests/auto/network/access/qnetworkrequestfactory/tst_qnetworkrequestfactory.cpp b/tests/auto/network/access/qnetworkrequestfactory/tst_qnetworkrequestfactory.cpp index fee137309e8..d04a7ff3eca 100644 --- a/tests/auto/network/access/qnetworkrequestfactory/tst_qnetworkrequestfactory.cpp +++ b/tests/auto/network/access/qnetworkrequestfactory/tst_qnetworkrequestfactory.cpp @@ -27,6 +27,7 @@ private Q_SLOTS: void timeout(); void userInfo(); void priority(); + void attributes(); private: const QUrl url1{u"http://foo.io"_s}; @@ -368,5 +369,55 @@ void tst_QNetworkRequestFactory::priority() QCOMPARE(request.priority(), QNetworkRequest::HighPriority); } +void tst_QNetworkRequestFactory::attributes() +{ + const auto attribute1 = QNetworkRequest::Attribute::BackgroundRequestAttribute; + const auto attribute2 = QNetworkRequest::User; + QNetworkRequestFactory factory; + QNetworkRequest request; + + // Empty factory + QVERIFY(!factory.attribute(attribute1).isValid()); + request = factory.createRequest(); + QVERIFY(!request.attribute(attribute1).isValid()); + + // (Re-)set and clear individual attribute + factory.setAttribute(attribute1, true); + QVERIFY(factory.attribute(attribute1).isValid()); + QCOMPARE(factory.attribute(attribute1).toBool(), true); + request = factory.createRequest(); + QVERIFY(request.attribute(attribute1).isValid()); + QCOMPARE(request.attribute(attribute1).toBool(), true); + // Replace previous value + factory.setAttribute(attribute1, false); + QVERIFY(factory.attribute(attribute1).isValid()); + QCOMPARE(factory.attribute(attribute1).toBool(), false); + request = factory.createRequest(); + QVERIFY(request.attribute(attribute1).isValid()); + QCOMPARE(request.attribute(attribute1).toBool(), false); + // Clear individual attribute + factory.clearAttribute(attribute1); + QVERIFY(!factory.attribute(attribute1).isValid()); + + // Getter default value + QCOMPARE(factory.attribute(attribute2, 111).toInt(), 111); // default value returned + factory.setAttribute(attribute2, 222); + QCOMPARE(factory.attribute(attribute2, 111).toInt(), 222); // actual value returned + factory.clearAttribute(attribute2); + QCOMPARE(factory.attribute(attribute2, 111).toInt(), 111); // default value returned + + // Clear attributes + factory.setAttribute(attribute1, true); + factory.setAttribute(attribute2, 333); + QVERIFY(factory.attribute(attribute1).isValid()); + QVERIFY(factory.attribute(attribute2).isValid()); + factory.clearAttributes(); + QVERIFY(!factory.attribute(attribute1).isValid()); + QVERIFY(!factory.attribute(attribute2).isValid()); + request = factory.createRequest(); + QVERIFY(!request.attribute(attribute1).isValid()); + QVERIFY(!request.attribute(attribute2).isValid()); +} + QTEST_MAIN(tst_QNetworkRequestFactory) #include "tst_qnetworkrequestfactory.moc"