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 <marc.mutz@qt.io> Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
a80ed49b10
commit
8da4156da7
@ -108,6 +108,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
|
|||||||
\li \c post()
|
\li \c post()
|
||||||
\li \c put()
|
\li \c put()
|
||||||
\li \c head()
|
\li \c head()
|
||||||
|
\li \c patch()
|
||||||
\li \c deleteResource()
|
\li \c deleteResource()
|
||||||
\li \c sendCustomRequest()
|
\li \c sendCustomRequest()
|
||||||
\row
|
\row
|
||||||
@ -116,6 +117,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
|
|||||||
\li -
|
\li -
|
||||||
\li -
|
\li -
|
||||||
\li X
|
\li X
|
||||||
|
\li -
|
||||||
\li X
|
\li X
|
||||||
\li -
|
\li -
|
||||||
\row
|
\row
|
||||||
@ -124,6 +126,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
|
|||||||
\li X
|
\li X
|
||||||
\li X
|
\li X
|
||||||
\li -
|
\li -
|
||||||
|
\li X
|
||||||
\li -
|
\li -
|
||||||
\li X
|
\li X
|
||||||
\row
|
\row
|
||||||
@ -132,6 +135,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
|
|||||||
\li X
|
\li X
|
||||||
\li X
|
\li X
|
||||||
\li -
|
\li -
|
||||||
|
\li X
|
||||||
\li -
|
\li -
|
||||||
\li -
|
\li -
|
||||||
\row
|
\row
|
||||||
@ -140,6 +144,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
|
|||||||
\li X
|
\li X
|
||||||
\li X
|
\li X
|
||||||
\li -
|
\li -
|
||||||
|
\li X
|
||||||
\li -
|
\li -
|
||||||
\li -
|
\li -
|
||||||
\row
|
\row
|
||||||
@ -148,6 +153,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
|
|||||||
\li X
|
\li X
|
||||||
\li X
|
\li X
|
||||||
\li -
|
\li -
|
||||||
|
\li X
|
||||||
\li -
|
\li -
|
||||||
\li -
|
\li -
|
||||||
\row
|
\row
|
||||||
@ -157,6 +163,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
|
|||||||
\li X
|
\li X
|
||||||
\li -
|
\li -
|
||||||
\li -
|
\li -
|
||||||
|
\li -
|
||||||
\li X
|
\li X
|
||||||
\row
|
\row
|
||||||
\li QIODevice
|
\li QIODevice
|
||||||
@ -164,6 +171,7 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
|
|||||||
\li X
|
\li X
|
||||||
\li X
|
\li X
|
||||||
\li -
|
\li -
|
||||||
|
\li X
|
||||||
\li -
|
\li -
|
||||||
\li X
|
\li X
|
||||||
\endtable
|
\endtable
|
||||||
@ -438,6 +446,77 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
|
|||||||
\overload
|
\overload
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\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(
|
\fn template<typename Functor, if_compatible_callback<Functor>> QRestReply *QRestAccessManager::head(
|
||||||
const QNetworkRequest &request,
|
const QNetworkRequest &request,
|
||||||
@ -800,6 +879,52 @@ QRestReply *QRestAccessManager::putWithDataImpl(const QNetworkRequest &request,
|
|||||||
return d->executeRequest([&]() { return d->qnam->put(request, data); }, context, slot);
|
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,
|
QRestReply *QRestAccessManager::customWithDataImpl(const QNetworkRequest &request,
|
||||||
const QByteArray& method, const QByteArray &data,
|
const QByteArray& method, const QByteArray &data,
|
||||||
const QObject *context,
|
const QObject *context,
|
||||||
|
@ -114,6 +114,11 @@ public:
|
|||||||
QREST_METHOD_WITH_DATA(put, const QByteArray &)
|
QREST_METHOD_WITH_DATA(put, const QByteArray &)
|
||||||
QREST_METHOD_WITH_DATA(put, QHttpMultiPart *)
|
QREST_METHOD_WITH_DATA(put, QHttpMultiPart *)
|
||||||
QREST_METHOD_WITH_DATA(put, QIODevice *)
|
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(const QByteArray &)
|
||||||
QREST_METHOD_CUSTOM_WITH_DATA(QIODevice *)
|
QREST_METHOD_CUSTOM_WITH_DATA(QIODevice *)
|
||||||
QREST_METHOD_CUSTOM_WITH_DATA(QHttpMultiPart *)
|
QREST_METHOD_CUSTOM_WITH_DATA(QHttpMultiPart *)
|
||||||
|
@ -89,3 +89,11 @@ manager->sendCustomRequest(request, "MYMETHOD", myData, this, [this](QRestRepl
|
|||||||
// ...
|
// ...
|
||||||
});
|
});
|
||||||
//! [9]
|
//! [9]
|
||||||
|
|
||||||
|
|
||||||
|
//! [10]
|
||||||
|
manager->patch(request, myData, this, [this](QRestReply *reply) {
|
||||||
|
if (reply->isSuccess())
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
//! [10]
|
||||||
|
@ -147,6 +147,8 @@ bool HttpTestServer::readMethod(QTcpSocket *socket)
|
|||||||
method = Method::Get;
|
method = Method::Get;
|
||||||
else if (fragment == "PUT")
|
else if (fragment == "PUT")
|
||||||
method = Method::Put;
|
method = Method::Put;
|
||||||
|
else if (fragment == "PATCH")
|
||||||
|
method = Method::Patch;
|
||||||
else if (fragment == "POST")
|
else if (fragment == "POST")
|
||||||
method = Method::Post;
|
method = Method::Post;
|
||||||
else if (fragment == "DELETE")
|
else if (fragment == "DELETE")
|
||||||
|
@ -54,6 +54,7 @@ public:
|
|||||||
Head,
|
Head,
|
||||||
Get,
|
Get,
|
||||||
Put,
|
Put,
|
||||||
|
Patch,
|
||||||
Post,
|
Post,
|
||||||
Delete,
|
Delete,
|
||||||
Custom,
|
Custom,
|
||||||
|
@ -108,6 +108,7 @@ void tst_QRestAccessManager::networkRequestReply()
|
|||||||
const QByteArray methodPOST{"POST"_ba};
|
const QByteArray methodPOST{"POST"_ba};
|
||||||
const QByteArray methodGET{"GET"_ba};
|
const QByteArray methodGET{"GET"_ba};
|
||||||
const QByteArray methodPUT{"PUT"_ba};
|
const QByteArray methodPUT{"PUT"_ba};
|
||||||
|
const QByteArray methodPATCH{"PATCH"_ba};
|
||||||
const QByteArray methodCUSTOM{"FOOBAR"_ba};
|
const QByteArray methodCUSTOM{"FOOBAR"_ba};
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
@ -209,6 +210,27 @@ void tst_QRestAccessManager::networkRequestReply()
|
|||||||
VERIFY_REPLY_OK(methodPUT);
|
VERIFY_REPLY_OK(methodPUT);
|
||||||
QCOMPARE(serverSideRequest.body, ioDeviceData);
|
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
|
//These must NOT compile
|
||||||
//manager.get(request, [](){}); // callback without context object
|
//manager.get(request, [](){}); // callback without context object
|
||||||
//manager.get(request, ""_ba, [](){}); // 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.post(request); // data is required
|
||||||
//manager.put(request, QString()); // wrong datatype
|
//manager.put(request, QString()); // wrong datatype
|
||||||
//manager.put(request); // data is required
|
//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.deleteResource(request, "f"_ba); // data not allowed
|
||||||
//manager.head(request, "f"_ba); // data not allowed
|
//manager.head(request, "f"_ba); // data not allowed
|
||||||
//manager.post(request, ""_ba, this, [](int param){}); // Wrong callback signature
|
//manager.post(request, ""_ba, this, [](int param){}); // Wrong callback signature
|
||||||
|
Loading…
x
Reference in New Issue
Block a user