summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuha Vuolle <[email protected]>2023-11-20 12:56:10 +0200
committerJuha Vuolle <[email protected]>2023-12-08 15:53:36 +0200
commit8da4156da7ed2eff7b44bdda51eb92870bdfbc57 (patch)
treee98d8d196f8b9b5003794b1de33ed24f35a6b0bb
parenta80ed49b1049478957edca1cfbcd90f9f4b83cb3 (diff)
Add PATCH support for QRestAccessManager
It is somewhat common HTTP method with RESTful use cases (partial updates on resources) Task-number: QTBUG-114637 Change-Id: Id252d3f4b54c3ebb8df5c93259e64a4af2d0ca2f Reviewed-by: Marc Mutz <[email protected]> Reviewed-by: Ivan Solovev <[email protected]> Reviewed-by: MÃ¥rten Nordheim <[email protected]>
-rw-r--r--src/network/access/qrestaccessmanager.cpp125
-rw-r--r--src/network/access/qrestaccessmanager.h5
-rw-r--r--src/network/doc/snippets/code/src_network_access_qrestaccessmanager.cpp8
-rw-r--r--tests/auto/network/access/qrestaccessmanager/httptestserver.cpp2
-rw-r--r--tests/auto/network/access/qrestaccessmanager/httptestserver_p.h1
-rw-r--r--tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp25
6 files changed, 166 insertions, 0 deletions
diff --git a/src/network/access/qrestaccessmanager.cpp b/src/network/access/qrestaccessmanager.cpp
index 2a2c1247d88..146d8b24b93 100644
--- a/src/network/access/qrestaccessmanager.cpp
+++ b/src/network/access/qrestaccessmanager.cpp
@@ -108,6 +108,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
\li \c post()
\li \c put()
\li \c head()
+ \li \c patch()
\li \c deleteResource()
\li \c sendCustomRequest()
\row
@@ -116,6 +117,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
\li -
\li -
\li X
+ \li -
\li X
\li -
\row
@@ -124,6 +126,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
\li X
\li X
\li -
+ \li X
\li -
\li X
\row
@@ -132,6 +135,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
\li X
\li X
\li -
+ \li X
\li -
\li -
\row
@@ -140,6 +144,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
\li X
\li X
\li -
+ \li X
\li -
\li -
\row
@@ -148,6 +153,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
\li X
\li X
\li -
+ \li X
\li -
\li -
\row
@@ -157,6 +163,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
\li X
\li -
\li -
+ \li -
\li X
\row
\li QIODevice
@@ -164,6 +171,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
\li X
\li X
\li -
+ \li X
\li -
\li X
\endtable
@@ -439,6 +447,77 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
*/
/*!
+ \fn template<typename Functor, if_compatible_callback<Functor>> QRestReply *QRestAccessManager::patch(
+ const QNetworkRequest &request, const QJsonObject &data,
+ const ContextTypeForFunctor<Functor> *context,
+ Functor &&callback)
+
+ Issues an \c {HTTP PATCH} based on \a request.
+
+ The optional \a callback and \a context object can be provided for
+ handling the request completion as illustrated below:
+
+ \snippet code/src_network_access_qrestaccessmanager.cpp 10
+
+ Alternatively the signals of the returned QRestReply* object can be
+ used. For further information see
+ \l {Issuing Network Requests and Handling Replies}.
+
+ The \c patch() method always requires \a data parameter. The following
+ data types are supported:
+ \list
+ \li QByteArray
+ \li QJsonObject *)
+ \li QJsonArray *)
+ \li QVariantMap **)
+ \li QIODevice*
+ \endlist
+
+ *) Sent in \l QJsonDocument::Compact format, and the
+ \c Content-Type header is set to \c {application/json} if the
+ \c Content-Type header was not set
+ **) QVariantMap is converted to and treated as a QJsonObject
+
+ \sa QRestReply, QRestReply::finished(), QRestAccessManager::requestFinished()
+*/
+
+/*!
+ \fn template<typename Functor, if_compatible_callback<Functor>> QRestReply *QRestAccessManager::patch(
+ const QNetworkRequest &request, const QJsonArray &data,
+ const ContextTypeForFunctor<Functor> *context,
+ Functor &&callback)
+
+ \overload
+*/
+
+/*!
+ \fn template<typename Functor, if_compatible_callback<Functor>> QRestReply *QRestAccessManager::patch(
+ const QNetworkRequest &request, const QVariantMap &data,
+ const ContextTypeForFunctor<Functor> *context,
+ Functor &&callback)
+
+ \overload
+*/
+
+/*!
+ \fn template<typename Functor, if_compatible_callback<Functor>> QRestReply *QRestAccessManager::patch(
+ const QNetworkRequest &request, const QByteArray &data,
+ const ContextTypeForFunctor<Functor> *context,
+ Functor &&callback)
+
+ \overload
+*/
+
+/*!
+ \fn template<typename Functor, if_compatible_callback<Functor>> QRestReply *QRestAccessManager::patch(
+ const QNetworkRequest &request, QIODevice *data,
+ const ContextTypeForFunctor<Functor> *context,
+ Functor &&callback)
+
+ \overload
+*/
+
+/*!
\fn template<typename Functor, if_compatible_callback<Functor>> QRestReply *QRestAccessManager::head(
const QNetworkRequest &request,
const ContextTypeForFunctor<Functor> *context,
@@ -800,6 +879,52 @@ QRestReply *QRestAccessManager::putWithDataImpl(const QNetworkRequest &request,
return d->executeRequest([&]() { return d->qnam->put(request, data); }, context, slot);
}
+static const auto PATCH = "PATCH"_ba;
+
+QRestReply *QRestAccessManager::patchWithDataImpl(const QNetworkRequest &request,
+ const QJsonObject &data, const QObject *context,
+ QtPrivate::QSlotObjectBase *slot)
+{
+ Q_D(QRestAccessManager);
+ return d->executeRequest(
+ [&](auto req, auto json){ return d->qnam->sendCustomRequest(req, PATCH, json); },
+ data, request, context, slot);
+}
+
+QRestReply *QRestAccessManager::patchWithDataImpl(const QNetworkRequest &request,
+ const QJsonArray &data, const QObject *context,
+ QtPrivate::QSlotObjectBase *slot)
+{
+ Q_D(QRestAccessManager);
+ return d->executeRequest(
+ [&](auto req, auto json){ return d->qnam->sendCustomRequest(req, PATCH, json); },
+ data, request, context, slot);
+}
+
+QRestReply *QRestAccessManager::patchWithDataImpl(const QNetworkRequest &request,
+ const QVariantMap &data, const QObject *context,
+ QtPrivate::QSlotObjectBase *slot)
+{
+ return patchWithDataImpl(request, QJsonObject::fromVariantMap(data), context, slot);
+}
+
+QRestReply *QRestAccessManager::patchWithDataImpl(const QNetworkRequest &request,
+ const QByteArray &data, const QObject *context,
+ QtPrivate::QSlotObjectBase *slot)
+{
+ Q_D(QRestAccessManager);
+ return d->executeRequest([&]() { return d->qnam->sendCustomRequest(request, PATCH, data); },
+ context, slot);
+}
+
+QRestReply *QRestAccessManager::patchWithDataImpl(const QNetworkRequest &request, QIODevice *data,
+ const QObject *context, QtPrivate::QSlotObjectBase *slot)
+{
+ Q_D(QRestAccessManager);
+ return d->executeRequest([&]() { return d->qnam->sendCustomRequest(request, PATCH, data); },
+ context, slot);
+}
+
QRestReply *QRestAccessManager::customWithDataImpl(const QNetworkRequest &request,
const QByteArray& method, const QByteArray &data,
const QObject *context,
diff --git a/src/network/access/qrestaccessmanager.h b/src/network/access/qrestaccessmanager.h
index 3ff23bee905..9656853f43d 100644
--- a/src/network/access/qrestaccessmanager.h
+++ b/src/network/access/qrestaccessmanager.h
@@ -114,6 +114,11 @@ public:
QREST_METHOD_WITH_DATA(put, const QByteArray &)
QREST_METHOD_WITH_DATA(put, QHttpMultiPart *)
QREST_METHOD_WITH_DATA(put, QIODevice *)
+ QREST_METHOD_WITH_DATA(patch, const QJsonObject &)
+ QREST_METHOD_WITH_DATA(patch, const QJsonArray &)
+ QREST_METHOD_WITH_DATA(patch, const QVariantMap &)
+ QREST_METHOD_WITH_DATA(patch, const QByteArray &)
+ QREST_METHOD_WITH_DATA(patch, QIODevice *)
QREST_METHOD_CUSTOM_WITH_DATA(const QByteArray &)
QREST_METHOD_CUSTOM_WITH_DATA(QIODevice *)
QREST_METHOD_CUSTOM_WITH_DATA(QHttpMultiPart *)
diff --git a/src/network/doc/snippets/code/src_network_access_qrestaccessmanager.cpp b/src/network/doc/snippets/code/src_network_access_qrestaccessmanager.cpp
index 20bb5d521d0..fcc8dbaef52 100644
--- a/src/network/doc/snippets/code/src_network_access_qrestaccessmanager.cpp
+++ b/src/network/doc/snippets/code/src_network_access_qrestaccessmanager.cpp
@@ -89,3 +89,11 @@ manager->sendCustomRequest(request, "MYMETHOD", myData, this, [this](QRestRepl
// ...
});
//! [9]
+
+
+//! [10]
+manager->patch(request, myData, this, [this](QRestReply *reply) {
+ if (reply->isSuccess())
+ // ...
+});
+//! [10]
diff --git a/tests/auto/network/access/qrestaccessmanager/httptestserver.cpp b/tests/auto/network/access/qrestaccessmanager/httptestserver.cpp
index dfa2b45063d..089342ff8bf 100644
--- a/tests/auto/network/access/qrestaccessmanager/httptestserver.cpp
+++ b/tests/auto/network/access/qrestaccessmanager/httptestserver.cpp
@@ -147,6 +147,8 @@ bool HttpTestServer::readMethod(QTcpSocket *socket)
method = Method::Get;
else if (fragment == "PUT")
method = Method::Put;
+ else if (fragment == "PATCH")
+ method = Method::Patch;
else if (fragment == "POST")
method = Method::Post;
else if (fragment == "DELETE")
diff --git a/tests/auto/network/access/qrestaccessmanager/httptestserver_p.h b/tests/auto/network/access/qrestaccessmanager/httptestserver_p.h
index d1819fcc21a..1498c4bdb7e 100644
--- a/tests/auto/network/access/qrestaccessmanager/httptestserver_p.h
+++ b/tests/auto/network/access/qrestaccessmanager/httptestserver_p.h
@@ -54,6 +54,7 @@ public:
Head,
Get,
Put,
+ Patch,
Post,
Delete,
Custom,
diff --git a/tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp b/tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp
index f66968bf1cf..b2cfcf4a754 100644
--- a/tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp
+++ b/tests/auto/network/access/qrestaccessmanager/tst_qrestaccessmanager.cpp
@@ -108,6 +108,7 @@ void tst_QRestAccessManager::networkRequestReply()
const QByteArray methodPOST{"POST"_ba};
const QByteArray methodGET{"GET"_ba};
const QByteArray methodPUT{"PUT"_ba};
+ const QByteArray methodPATCH{"PATCH"_ba};
const QByteArray methodCUSTOM{"FOOBAR"_ba};
// DELETE
@@ -209,6 +210,27 @@ void tst_QRestAccessManager::networkRequestReply()
VERIFY_REPLY_OK(methodPUT);
QCOMPARE(serverSideRequest.body, ioDeviceData);
+ // PATCH
+ manager.patch(request, byteArrayData, this, callback);
+ VERIFY_REPLY_OK(methodPATCH);
+ QCOMPARE(serverSideRequest.body, byteArrayData);
+
+ manager.patch(request, jsonObjectData, this, callback);
+ VERIFY_REPLY_OK(methodPATCH);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).object(), jsonObjectData);
+
+ manager.patch(request, jsonArrayData, this, callback);
+ VERIFY_REPLY_OK(methodPATCH);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).array(), jsonArrayData);
+
+ manager.patch(request, variantMapData, this, callback);
+ VERIFY_REPLY_OK(methodPATCH);
+ QCOMPARE(QJsonDocument::fromJson(serverSideRequest.body).object(), jsonObjectData);
+
+ manager.patch(request, &bufferIoDevice, this, callback);
+ VERIFY_REPLY_OK(methodPATCH);
+ QCOMPARE(serverSideRequest.body, ioDeviceData);
+
//These must NOT compile
//manager.get(request, [](){}); // callback without context object
//manager.get(request, ""_ba, [](){}); // callback without context object
@@ -219,6 +241,9 @@ void tst_QRestAccessManager::networkRequestReply()
//manager.post(request); // data is required
//manager.put(request, QString()); // wrong datatype
//manager.put(request); // data is required
+ //manager.patch(request, 123); // wrong datatype
+ //manager.patch(request, QString()); // wrong datatype
+ //manager.patch(request); // data is required
//manager.deleteResource(request, "f"_ba); // data not allowed
//manager.head(request, "f"_ba); // data not allowed
//manager.post(request, ""_ba, this, [](int param){}); // Wrong callback signature