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 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
|
||||
@ -438,6 +446,77 @@ Q_LOGGING_CATEGORY(lcQrest, "qt.network.access.rest")
|
||||
\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(
|
||||
const QNetworkRequest &request,
|
||||
@ -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,
|
||||
|
@ -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 *)
|
||||
|
@ -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]
|
||||
|
@ -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")
|
||||
|
@ -54,6 +54,7 @@ public:
|
||||
Head,
|
||||
Get,
|
||||
Put,
|
||||
Patch,
|
||||
Post,
|
||||
Delete,
|
||||
Custom,
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user