8#include <userver/components/component_base.hpp>
9#include <userver/components/component_config.hpp>
10#include <userver/components/component_context.hpp>
11#include <userver/utils/assert.hpp>
12#include <userver/utils/impl/internal_tag.hpp>
13#include <userver/yaml_config/merge_schemas.hpp>
15#include <userver/middlewares/impl/middleware_pipeline_config.hpp>
16#include <userver/middlewares/impl/pipeline_creator_interface.hpp>
17#include <userver/middlewares/pipeline.hpp>
19USERVER_NAMESPACE_BEGIN
21namespace middlewares {
36MiddlewareDependencyBuilder MakeDefaultUserDependency();
40 WithMiddlewareDependencyComponentBase(
46 virtual const middlewares::impl::MiddlewareDependency& GetMiddlewareDependency(
utils::impl::InternalTag)
const = 0;
49void LogConfiguration(std::string_view component_name,
const std::vector<std::string>& names);
51void LogValidateError(std::string_view middleware_name,
const std::exception& e);
58template <
typename MiddlewareBaseType,
typename HandlerInfo>
59class MiddlewareFactoryComponentBase :
public impl::WithMiddlewareDependencyComponentBase {
61 using MiddlewareBase = MiddlewareBaseType;
63 MiddlewareFactoryComponentBase(
66 MiddlewareDependencyBuilder&& builder = impl::MakeDefaultUserDependency()
68 : impl::WithMiddlewareDependencyComponentBase(config, context),
70 dependency_(std::move(builder).ExtractDependency(config
.Name())) {}
78 virtual std::shared_ptr<
const MiddlewareBase>
83 virtual yaml_config::Schema GetMiddlewareConfigSchema()
const {
return GetStaticConfigSchema(); }
85 static yaml_config::Schema GetStaticConfigSchema() {
87type: object
88description: base class for grpc-server middleware
89additionalProperties: false
90properties:
91 enabled:
92 type: string
93 description: the flag to enable/disable middleware in the pipeline
94 defaultDescription: true
100 const middlewares::impl::MiddlewareDependency& GetMiddlewareDependency(
utils::impl::InternalTag)
const override {
104 const formats::
yaml::Value& GetGlobalConfig(
utils::impl::InternalTag)
const {
return global_config_; }
109 middlewares::impl::MiddlewareDependency dependency_;
59class MiddlewareFactoryComponentBase :
public impl::WithMiddlewareDependencyComponentBase {
…};
123template <
typename MiddlewareBase,
typename HandlerInfo>
125 public impl::PipelineCreatorInterface<MiddlewareBase, HandlerInfo> {
127 static yaml_config::Schema GetStaticConfigSchema() {
129type: object
130description: base class for all the gRPC service components
131additionalProperties: false
132properties:
133 disable-user-pipeline-middlewares:
134 type: boolean
135 description: flag to disable groups::User middlewares from pipeline
136 defaultDescription: false
137 disable-all-pipeline-middlewares:
138 type: boolean
139 description: flag to disable all middlewares from pipeline
140 defaultDescription: false
141 middlewares:
142 type: object
143 description: overloads of configs of middlewares per service
144 additionalProperties:
145 type: object
146 description: a middleware config
147 additionalProperties: true
148 properties:
149 enabled:
150 type: boolean
151 description: enable middleware in the list
152 properties: {}
157 using MiddlewareFactory = MiddlewareFactoryComponentBase<MiddlewareBase, HandlerInfo>;
162 std::string_view pipeline_name
167 std::vector<std::shared_ptr<
const MiddlewareBase>> CreateMiddlewares(
const HandlerInfo& info)
const override;
171 struct MiddlewareInfo
final {
172 const MiddlewareFactory* factory{
nullptr};
176 std::vector<MiddlewareInfo> middleware_infos_{};
179template <
typename MiddlewareBase,
typename HandlerInfo>
180RunnerComponentBase<MiddlewareBase, HandlerInfo>::RunnerComponentBase(
183 std::string_view pipeline_name
186 const auto& middlewares = config
["middlewares"];
187 const auto& pipeline = context.FindComponent<impl::AnyMiddlewarePipelineComponent>(pipeline_name).GetPipeline();
188 const auto names = pipeline.GetPerServiceMiddlewares(config
.As<impl
::MiddlewareRunnerConfig
>());
189 impl::LogConfiguration(config
.Name(), names);
190 for (
const auto& mid : names) {
191 const auto* factory = context.FindComponentOptional<MiddlewareFactory>(mid);
192 UINVARIANT(factory !=
nullptr, fmt::format(
"The middleware '{}' must exist", mid));
193 middleware_infos_.push_back(MiddlewareInfo{factory, middlewares
[mid
]});
198template <
typename MiddlewareBase,
typename HandlerInfo>
199std::vector<std::shared_ptr<
const MiddlewareBase>> RunnerComponentBase<MiddlewareBase, HandlerInfo>::CreateMiddlewares(
200 const HandlerInfo& info
202 std::vector<std::shared_ptr<
const MiddlewareBase>> middlewares{};
203 middlewares.reserve(middleware_infos_.size());
204 for (
const auto& [factory, local_config] : middleware_infos_) {
206 auto config = impl::ValidateAndMergeMiddlewareConfigs(
207 factory->GetGlobalConfig(
utils::impl::InternalTag{}), local_config, factory->GetMiddlewareConfigSchema()
209 middlewares.push_back(factory->CreateMiddleware(info, config));
210 }
catch (
const std::exception& e) {
211 impl::LogValidateError(factory->GetMiddlewareDependency(
utils::impl::InternalTag{}).middleware_name, e);
225template <
typename MiddlewareBase,
typename Middleware,
typename HandlerInfo>
226class SimpleMiddlewareFactoryComponent
final :
public MiddlewareFactoryComponentBase<MiddlewareBase, HandlerInfo> {
228 static constexpr std::string_view kName = Middleware::kName;
230 SimpleMiddlewareFactoryComponent(
234 : MiddlewareFactoryComponentBase<MiddlewareBase, HandlerInfo>(
237 middlewares::MiddlewareDependencyBuilder{Middleware::kDependency}
241 std::shared_ptr<
const MiddlewareBase> CreateMiddleware(
const HandlerInfo&,
const yaml_config::
YamlConfig&)
243 return std::make_shared<Middleware>();
251template <
typename MiddlewareBase,
typename Middleware,
typename HandlerInfo>
252inline constexpr bool components::kHasValidate<
253 middlewares::impl::SimpleMiddlewareFactoryComponent<MiddlewareBase, Middleware, HandlerInfo>> =
true;