mirror of https://github.com/qt/qtgrpc.git
Deprecate serverMetadata for server{Initial,Trailing}Metadata
We forgot to deprecate the server-metadata interfaces when we deprecated
the client-metadata. The same problems apply here too!
Found during the 6.10 API-review.
[ChangeLog][Deprecation Notice]
Deprecate the metadata()/serverMetadata()/setServerMetadata() methods on
QGrpcOperation and QGrpcOperationContext that use QHash in favor of the
new server{Initial,Trailing}Metadata interfaces, that use QMultiHash and
provide the correct handling of the received metadata in their
respective phase. This is a behavior change as the old metadata()
interface now only returns the initial metadata.
Fixes: QTBUG-138039
Pick-to: 6.10
Change-Id: I307ee81fc353a0f4316fea2d10f56bb6910ae859
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
This commit is contained in:
parent
814c0b6ac2
commit
0e2803842a
|
|
@ -771,7 +771,7 @@ void Http2Handler::handleHeaders(const HPack::HttpHeader &headers, HeaderPhase p
|
|||
false,
|
||||
};
|
||||
|
||||
QHash<QByteArray, QByteArray> metadata;
|
||||
QMultiHash<QByteArray, QByteArray> metadata;
|
||||
std::optional<QtGrpc::StatusCode> statusCode;
|
||||
QString statusMessage;
|
||||
|
||||
|
|
@ -837,16 +837,14 @@ void Http2Handler::handleHeaders(const HPack::HttpHeader &headers, HeaderPhase p
|
|||
|
||||
switch (phase) {
|
||||
case HeaderPhase::Initial:
|
||||
m_operation->setServerMetadata(std::move(metadata));
|
||||
m_operation->setServerInitialMetadata(std::move(metadata));
|
||||
break;
|
||||
case HeaderPhase::TrailersOnly:
|
||||
[[fallthrough]];
|
||||
case HeaderPhase::Trailers: {
|
||||
auto md = m_operation->serverMetadata();
|
||||
md.insert(metadata);
|
||||
m_operation->setServerMetadata(std::move(md));
|
||||
case HeaderPhase::Trailers:
|
||||
m_operation->setServerTrailingMetadata(std::move(metadata));
|
||||
finish({ *statusCode, statusMessage });
|
||||
} break;
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,16 +155,69 @@ void QGrpcOperation::cancel()
|
|||
emit d->operationContext->cancelRequested();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the server metadata received from the channel.
|
||||
#if QT_DEPRECATED_SINCE(6, 13)
|
||||
|
||||
\note For \l {QGrpcHttp2Channel} {HTTP/2 channels} it usually includes the
|
||||
HTTP headers received from the server.
|
||||
/*!
|
||||
\deprecated [6.13] Use serverInitialMetadata() and serverTrailingMetadata() instead.
|
||||
|
||||
\include qgrpcoperation.cpp serverInitialMetadata
|
||||
|
||||
\sa serverInitialMetadata() serverTrailingMetadata()
|
||||
*/
|
||||
const QHash<QByteArray, QByteArray> &QGrpcOperation::metadata() const & noexcept
|
||||
{
|
||||
Q_D(const QGrpcOperation);
|
||||
return d->operationContext->serverMetadata();
|
||||
QT_IGNORE_DEPRECATIONS(return d->operationContext->serverMetadata();)
|
||||
}
|
||||
|
||||
#endif // QT_DEPRECATED_SINCE(6, 13)
|
||||
|
||||
/*!
|
||||
\since 6.10
|
||||
|
||||
//! [serverInitialMetadata]
|
||||
Returns the initial metadata received from the server before any response
|
||||
messages.
|
||||
|
||||
Initial metadata is sent by the server immediately after the call is
|
||||
established. It may include key-value pairs that provide context for the
|
||||
call.
|
||||
|
||||
\note For \l {QGrpcHttp2Channel} {HTTP/2 channels}, this is delivered
|
||||
via response headers.
|
||||
//! [serverInitialMetadata]
|
||||
|
||||
The metadata may contain multiple entries under the same key.
|
||||
|
||||
\sa serverTrailingMetadata()
|
||||
*/
|
||||
const QMultiHash<QByteArray, QByteArray> &QGrpcOperation::serverInitialMetadata() const & noexcept
|
||||
{
|
||||
Q_D(const QGrpcOperation);
|
||||
return d->operationContext->serverInitialMetadata();
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.10
|
||||
|
||||
//! [serverTrailingMetadata]
|
||||
Returns the trailing metadata received from the server after all response
|
||||
messages.
|
||||
|
||||
Trailing metadata is sent only by the server once all response messages
|
||||
have been sent and just before the RPC completes. It may include key-value
|
||||
pairs providing additional context about the completed call.
|
||||
|
||||
\note For \l {QGrpcHttp2Channel} {HTTP/2 channels}, this is delivered
|
||||
via response trailers.
|
||||
//! [serverTrailingMetadata]
|
||||
|
||||
The metadata may contain multiple entries under the same key.
|
||||
*/
|
||||
const QMultiHash<QByteArray, QByteArray> &QGrpcOperation::serverTrailingMetadata() const & noexcept
|
||||
{
|
||||
Q_D(const QGrpcOperation);
|
||||
return d->operationContext->serverTrailingMetadata();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <QtCore/qhash.h>
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtCore/qstringfwd.h>
|
||||
#include <QtCore/qtdeprecationdefinitions.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
|
|
@ -37,8 +38,16 @@ public:
|
|||
}
|
||||
bool read(QProtobufMessage *message) const;
|
||||
|
||||
#if QT_DEPRECATED_SINCE(6, 13)
|
||||
QT_DEPRECATED_VERSION_X_6_13("Use serverInitialMetadata()")
|
||||
[[nodiscard]] const QHash<QByteArray, QByteArray> &metadata() const & noexcept;
|
||||
void metadata() const && = delete;
|
||||
#endif
|
||||
|
||||
[[nodiscard]] const QMultiHash<QByteArray, QByteArray> &
|
||||
serverInitialMetadata() const & noexcept;
|
||||
[[nodiscard]] const QMultiHash<QByteArray, QByteArray> &
|
||||
serverTrailingMetadata() const & noexcept;
|
||||
|
||||
[[nodiscard]] QLatin1StringView method() const noexcept;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#include <QtGrpc/private/qgrpccommonoptions_p.h>
|
||||
#include <QtGrpc/qgrpccalloptions.h>
|
||||
#include <QtGrpc/qgrpcoperationcontext.h>
|
||||
#include <QtGrpc/qgrpcstatus.h>
|
||||
|
|
@ -158,8 +159,12 @@ public:
|
|||
QByteArray argument;
|
||||
QGrpcCallOptions options;
|
||||
std::shared_ptr<QAbstractProtobufSerializer> serializer;
|
||||
QHash<QByteArray, QByteArray> serverMetadata;
|
||||
QMetaType responseMetaType;
|
||||
QMultiHash<QByteArray, QByteArray> serverInitialMetadata;
|
||||
#if QT_DEPRECATED_SINCE(6, 13)
|
||||
QHash<QByteArray, QByteArray> deprServerInitialMetadata;
|
||||
#endif
|
||||
QMultiHash<QByteArray, QByteArray> serverTrailingMetadata;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
|
@ -235,33 +240,112 @@ QGrpcOperationContext::serializer() const
|
|||
return d->serializer;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the metadata received from the server.
|
||||
#if QT_DEPRECATED_SINCE(6, 13)
|
||||
|
||||
\note This method is used implicitly by the QGrpcOperation counterpart.
|
||||
/*!
|
||||
\deprecated [6.13] Use serverInitialMetadata() and serverTrailingMetadata() instead.
|
||||
|
||||
\include qgrpcoperation.cpp serverInitialMetadata
|
||||
\note This method is used implicitly by QGrpcOperation.
|
||||
|
||||
\sa serverInitialMetadata() QGrpcOperation::serverInitialMetadata()
|
||||
*/
|
||||
const QHash<QByteArray, QByteArray> &QGrpcOperationContext::serverMetadata() const & noexcept
|
||||
{
|
||||
Q_D(const QGrpcOperationContext);
|
||||
return d->serverMetadata;
|
||||
return d->deprServerInitialMetadata;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn void QGrpcOperationContext::setServerMetadata(const QHash<QByteArray, QByteArray> &metadata)
|
||||
\fn void QGrpcOperationContext::setServerMetadata(QHash<QByteArray, QByteArray> &&metadata)
|
||||
\deprecated [6.13] Use setServerInitialMetadata() instead.
|
||||
|
||||
Sets the server \a metadata received from the service.
|
||||
Sets the metadata received from the server at the start of the RPC.
|
||||
|
||||
\sa setServerInitialMetadata()
|
||||
*/
|
||||
void QGrpcOperationContext::setServerMetadata(const QHash<QByteArray, QByteArray> &metadata)
|
||||
{
|
||||
Q_D(QGrpcOperationContext);
|
||||
d->serverMetadata = metadata;
|
||||
if (d->deprServerInitialMetadata == metadata)
|
||||
return;
|
||||
d->deprServerInitialMetadata = metadata;
|
||||
d->serverInitialMetadata = QMultiHash<QByteArray, QByteArray>(metadata);
|
||||
}
|
||||
|
||||
void QGrpcOperationContext::setServerMetadata(QHash<QByteArray, QByteArray> &&metadata)
|
||||
{
|
||||
Q_D(QGrpcOperationContext);
|
||||
d->serverMetadata = std::move(metadata);
|
||||
if (d->deprServerInitialMetadata == metadata)
|
||||
return;
|
||||
d->deprServerInitialMetadata = std::move(metadata);
|
||||
d->serverInitialMetadata = QMultiHash<QByteArray, QByteArray>(d->deprServerInitialMetadata);
|
||||
}
|
||||
|
||||
#endif // QT_DEPRECATED_SINCE(6, 13)
|
||||
|
||||
/*!
|
||||
\since 6.10
|
||||
|
||||
\include qgrpcoperation.cpp serverInitialMetadata
|
||||
\note This method is used implicitly by QGrpcOperation.
|
||||
|
||||
\sa QGrpcOperation::serverInitialMetadata() serverTrailingMetadata()
|
||||
*/
|
||||
const QMultiHash<QByteArray, QByteArray> &
|
||||
QGrpcOperationContext::serverInitialMetadata() const & noexcept
|
||||
{
|
||||
Q_D(const QGrpcOperationContext);
|
||||
return d->serverInitialMetadata;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.10
|
||||
|
||||
Sets the \a metadata received from the server at the start of the RPC.
|
||||
|
||||
\sa serverInitialMetadata()
|
||||
*/
|
||||
void QGrpcOperationContext::setServerInitialMetadata(QMultiHash<QByteArray, QByteArray> &&metadata)
|
||||
{
|
||||
Q_D(QGrpcOperationContext);
|
||||
if (d->serverInitialMetadata == metadata)
|
||||
return;
|
||||
d->serverInitialMetadata = std::move(metadata);
|
||||
#if QT_DEPRECATED_SINCE(6, 13)
|
||||
d->deprServerInitialMetadata = QtGrpcPrivate::mergeHash(d->serverInitialMetadata);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.10
|
||||
|
||||
\include qgrpcoperation.cpp serverTrailingMetadata
|
||||
\note This method is used implicitly by QGrpcOperation.
|
||||
|
||||
\sa QGrpcOperation::serverTrailingMetadata() setServerTrailingMetadata()
|
||||
*/
|
||||
const QMultiHash<QByteArray, QByteArray> &
|
||||
QGrpcOperationContext::serverTrailingMetadata() const & noexcept
|
||||
{
|
||||
Q_D(const QGrpcOperationContext);
|
||||
return d->serverTrailingMetadata;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.10
|
||||
|
||||
Sets the trailing \a metadata received from the server after all response
|
||||
messages.
|
||||
|
||||
\sa serverTrailingMetadata()
|
||||
*/
|
||||
void QGrpcOperationContext::setServerTrailingMetadata(QMultiHash<QByteArray, QByteArray> &&metadata)
|
||||
{
|
||||
Q_D(QGrpcOperationContext);
|
||||
if (d->serverTrailingMetadata == metadata)
|
||||
return;
|
||||
d->serverTrailingMetadata = std::move(metadata);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <QtCore/qhash.h>
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtCore/qstringfwd.h>
|
||||
#include <QtCore/qtdeprecationdefinitions.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
|
@ -39,10 +40,25 @@ public:
|
|||
void callOptions() const && = delete;
|
||||
[[nodiscard]] const QGrpcCallOptions &callOptions() const & noexcept;
|
||||
|
||||
#if QT_DEPRECATED_SINCE(6, 13)
|
||||
void serverMetadata() const && = delete;
|
||||
QT_DEPRECATED_VERSION_X_6_13("Use serverInitialMetadata()")
|
||||
[[nodiscard]] const QHash<QByteArray, QByteArray> &serverMetadata() const & noexcept;
|
||||
QT_DEPRECATED_VERSION_X_6_13("Use setServerInitialMetadata(QMultiHash&&)")
|
||||
void setServerMetadata(const QHash<QByteArray, QByteArray> &metadata);
|
||||
QT_DEPRECATED_VERSION_X_6_13("Use setServerInitialMetadata(QMultiHash&&)")
|
||||
void setServerMetadata(QHash<QByteArray, QByteArray> &&metadata);
|
||||
#endif // QT_DEPRECATED_SINCE(6, 13)
|
||||
|
||||
void serverInitialMetadata() const && = delete;
|
||||
[[nodiscard]] const QMultiHash<QByteArray, QByteArray> &
|
||||
serverInitialMetadata() const & noexcept;
|
||||
void setServerInitialMetadata(QMultiHash<QByteArray, QByteArray> &&metadata);
|
||||
|
||||
void serverTrailingMetadata() const && = delete;
|
||||
[[nodiscard]] const QMultiHash<QByteArray, QByteArray> &
|
||||
serverTrailingMetadata() const & noexcept;
|
||||
void setServerTrailingMetadata(QMultiHash<QByteArray, QByteArray> &&metadata);
|
||||
|
||||
[[nodiscard]] QMetaType responseMetaType() const;
|
||||
void setResponseMetaType(QMetaType metaType);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@ private Q_SLOTS:
|
|||
void deferredCancel();
|
||||
void asyncClientStatusMessage();
|
||||
void asyncStatusMessage();
|
||||
#if QT_DEPRECATED_SINCE(6, 13)
|
||||
void deprecatedMetadata();
|
||||
#endif
|
||||
void metadata();
|
||||
};
|
||||
|
||||
|
|
@ -139,7 +142,9 @@ void QtGrpcClientUnaryCallTest::asyncStatusMessage()
|
|||
QCOMPARE(args.first().value<QGrpcStatus>().message(), request.testFieldString());
|
||||
}
|
||||
|
||||
void QtGrpcClientUnaryCallTest::metadata()
|
||||
#if QT_DEPRECATED_SINCE(6, 13)
|
||||
|
||||
void QtGrpcClientUnaryCallTest::deprecatedMetadata()
|
||||
{
|
||||
QGrpcCallOptions opt;
|
||||
QHash<QByteArray, QByteArray> clientMd{
|
||||
|
|
@ -158,19 +163,52 @@ void QtGrpcClientUnaryCallTest::metadata()
|
|||
QCOMPARE_EQ(args.count(), 1);
|
||||
QVERIFY(args.first().value<QGrpcStatus>().isOk());
|
||||
|
||||
const auto &md = reply->metadata();
|
||||
QT_IGNORE_DEPRECATIONS(const auto &md = reply->metadata();)
|
||||
auto initialIt = md.equal_range("response_initial");
|
||||
QCOMPARE_EQ(std::distance(initialIt.first, initialIt.second), 1);
|
||||
QCOMPARE_EQ(initialIt.first.value(), "2");
|
||||
}
|
||||
|
||||
auto trailingIt = md.equal_range("response_trailing");
|
||||
QCOMPARE_EQ(std::distance(trailingIt.first, trailingIt.second), 1);
|
||||
#endif // QT_DEPRECATED_SINCE(6, 13)
|
||||
|
||||
void QtGrpcClientUnaryCallTest::metadata()
|
||||
{
|
||||
QGrpcCallOptions opt;
|
||||
QMultiHash<QByteArray, QByteArray> clientMd{
|
||||
{ "request_initial", "3" },
|
||||
{ "request_trailing", "2" },
|
||||
{ "request_sum", "20" },
|
||||
{ "request_sum", "10" }
|
||||
};
|
||||
opt.setMetadata(clientMd);
|
||||
auto reply = client()->testMetadata({}, opt);
|
||||
QSignalSpy replyFinishedSpy(reply.get(), &QGrpcCallReply::finished);
|
||||
QVERIFY(replyFinishedSpy.isValid());
|
||||
|
||||
QTRY_COMPARE_EQ_WITH_TIMEOUT(replyFinishedSpy.count(), 1, FailTimeout);
|
||||
const auto &args = replyFinishedSpy.first();
|
||||
QCOMPARE_EQ(args.count(), 1);
|
||||
QVERIFY(args.first().value<QGrpcStatus>().isOk());
|
||||
|
||||
const auto &initialMd = reply->serverInitialMetadata();
|
||||
auto initialIt = initialMd.equal_range("response_initial");
|
||||
QCOMPARE_EQ(std::distance(initialIt.first, initialIt.second), 3);
|
||||
QCOMPARE_EQ(initialIt.first.value(), "2");
|
||||
std::advance(initialIt.first, 1);
|
||||
QCOMPARE_EQ(initialIt.first.value(), "1");
|
||||
std::advance(initialIt.first, 1);
|
||||
QCOMPARE_EQ(initialIt.first.value(), "0");
|
||||
|
||||
const auto &trailingMd = reply->serverTrailingMetadata();
|
||||
auto trailingIt = trailingMd.equal_range("response_trailing");
|
||||
QCOMPARE_EQ(std::distance(trailingIt.first, trailingIt.second), 2);
|
||||
QCOMPARE_EQ(trailingIt.first.value(), "1");
|
||||
std::advance(trailingIt.first, 1);
|
||||
QCOMPARE_EQ(trailingIt.first.value(), "0");
|
||||
|
||||
auto sumIt = md.equal_range("response_sum");
|
||||
auto sumIt = trailingMd.equal_range("response_sum");
|
||||
QCOMPARE_EQ(std::distance(sumIt.first, sumIt.second), 1);
|
||||
auto sum = sumIt.first.value();
|
||||
QVERIFY(sum == "20"_ba || sum == "10"_ba);
|
||||
QCOMPARE_EQ(sumIt.first.value(), "30"_ba);
|
||||
}
|
||||
|
||||
QTEST_MAIN(QtGrpcClientUnaryCallTest)
|
||||
|
|
|
|||
Loading…
Reference in New Issue