diff options
author | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-16 20:38:33 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-16 20:38:33 +0300 |
commit | 8468858a796013ec5547c9292c0a80a5a9172804 (patch) | |
tree | fa5685bdc480863dcaa9b124ee12cd948eadb2d5 | |
parent | 76cbe125b7d39dca64a0de7b86eee37fd575e4df (diff) | |
download | ydb-8468858a796013ec5547c9292c0a80a5a9172804.tar.gz |
Automatically check protobuf has validate option KIKIMR-14369
ref:a62a84bad3a8555c27d06bcc0992c72a740a715c
-rw-r--r-- | ydb/core/grpc_services/base/base.h | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/ydb/core/grpc_services/base/base.h b/ydb/core/grpc_services/base/base.h index 38380586218..2b9344e8fd4 100644 --- a/ydb/core/grpc_services/base/base.h +++ b/ydb/core/grpc_services/base/base.h @@ -1029,22 +1029,58 @@ private: TMaybe<NRpcService::TRlPath> RlPath; }; +template<ui32 TRpcId, typename TReq, typename TResp, bool IsOperation, typename TDerived> +class TGRpcRequestValidationWrapperImpl : + public TGRpcRequestWrapperImpl<TRpcId, TReq, TResp, IsOperation, TDerived> { + +public: + static IActor* CreateRpcActor(typename std::conditional<IsOperation, IRequestOpCtx, IRequestNoOpCtx>::type* msg); + TGRpcRequestValidationWrapperImpl(NGrpc::IRequestContextBase* ctx) + : TGRpcRequestWrapperImpl<TRpcId, TReq, TResp, IsOperation, TDerived>(ctx) + { } + + bool Validate(TString& error) override { + return this->GetProtoRequest()->validate(error); + } +}; + +// SFINAE +// Check protobuf has validate feature +template<typename TProto> +struct TProtoHasValidate { +private: + static int Detect(...); + // validate function has prototype: bool validate(TProtoStringType&) const + static TProtoStringType Dummy_; + template<typename U> + static decltype(std::declval<U>().validate(Dummy_)) Detect(const U&); +public: + static constexpr bool Value = std::is_same<bool, decltype(Detect(std::declval<TProto>()))>::value; +}; + class IFacilityProvider; template <typename TReq, typename TResp, bool IsOperation> class TGrpcRequestCall - : public TGRpcRequestWrapperImpl< - TRpcServices::EvGrpcRuntimeRequest, TReq, TResp, IsOperation, TGrpcRequestCall<TReq, TResp, IsOperation>> { + : public std::conditional_t<TProtoHasValidate<TReq>::Value, + TGRpcRequestValidationWrapperImpl< + TRpcServices::EvGrpcRuntimeRequest, TReq, TResp, IsOperation, TGrpcRequestCall<TReq, TResp, IsOperation>>, + TGRpcRequestWrapperImpl< + TRpcServices::EvGrpcRuntimeRequest, TReq, TResp, IsOperation, TGrpcRequestCall<TReq, TResp, IsOperation>>> + { typedef typename std::conditional<IsOperation, IRequestOpCtx, IRequestNoOpCtx>::type TRequestIface; public: static constexpr bool IsOp = IsOperation; static IActor* CreateRpcActor(typename std::conditional<IsOperation, IRequestOpCtx, IRequestNoOpCtx>::type* msg); + using TBase = std::conditional_t<TProtoHasValidate<TReq>::Value, + TGRpcRequestValidationWrapperImpl< + TRpcServices::EvGrpcRuntimeRequest, TReq, TResp, IsOperation, TGrpcRequestCall<TReq, TResp, IsOperation>>, + TGRpcRequestWrapperImpl< + TRpcServices::EvGrpcRuntimeRequest, TReq, TResp, IsOperation, TGrpcRequestCall<TReq, TResp, IsOperation>>>; TGrpcRequestCall(NGrpc::IRequestContextBase* ctx, void (*cb)(std::unique_ptr<TRequestIface>, const IFacilityProvider&), TRequestAuxSettings auxSettings = {}) - : TGRpcRequestWrapperImpl< - TRpcServices::EvGrpcRuntimeRequest, TReq, TResp, IsOperation, - TGrpcRequestCall<TReq, TResp, IsOperation>>(ctx) + : TBase(ctx) , PassMethod(cb) , AuxSettings(std::move(auxSettings)) { } |