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/simple_middleware_pipeline.hpp>
17#include <userver/middlewares/pipeline.hpp>
19USERVER_NAMESPACE_BEGIN
21namespace middlewares {
32MiddlewareDependencyBuilder MakeDefaultUserDependency();
34class WithMiddlewareDependencyComponentBase :
public components::ComponentBase {
36 WithMiddlewareDependencyComponentBase(
41 : components::ComponentBase(config, context) {}
43 virtual const middlewares::impl::MiddlewareDependency& GetMiddlewareDependency(
utils::impl::InternalTag)
const = 0;
51template <
typename MiddlewareBaseType,
typename HandlerInfo>
54 using MiddlewareBase = MiddlewareBaseType;
56 MiddlewareFactoryComponentBase(
59 MiddlewareDependencyBuilder&& builder = impl::MakeDefaultUserDependency()
61 : impl::WithMiddlewareDependencyComponentBase(config, context),
62 global_config_(config.As<formats::yaml::Value>()),
63 dependency_(std::move(builder).Extract(config.Name())) {}
71 virtual std::shared_ptr<MiddlewareBase>
78 static yaml_config::Schema GetStaticConfigSchema() {
79 return yaml_config::MergeSchemas<components::ComponentBase>(R"(
80type: object
81description: base class for grpc-server middleware
82additionalProperties: false
83properties:
84 enabled:
85 type: string
86 description: the flag to enable/disable middleware in the pipeline
87 defaultDescription: true
88)");
93 const middlewares::impl::MiddlewareDependency& GetMiddlewareDependency(
utils::impl::InternalTag)
const override {
97 const formats::
yaml::Value& GetGlobalConfig(
utils::impl::InternalTag)
const {
return global_config_; }
102 middlewares::impl::MiddlewareDependency dependency_;
116template <
typename MiddlewareBase,
typename HandlerInfo>
118 public impl::PipelineCreatorInterface<MiddlewareBase, HandlerInfo> {
120 static yaml_config::Schema GetStaticConfigSchema() {
121 return yaml_config::MergeSchemas<components::ComponentBase>(R"(
122type: object
123description: base class for all the gRPC service components
124additionalProperties: false
125properties:
126 disable-user-pipeline-middlewares:
127 type: boolean
128 description: flag to disable groups::User middlewares from pipeline
129 defaultDescription: false
130 disable-all-pipeline-middlewares:
131 type: boolean
132 description: flag to disable all middlewares from pipline
133 defaultDescription: false
134 middlewares:
135 type: object
136 description: overloads of configs of middlewares per service
137 additionalProperties:
138 type: object
139 description: a middleware config
140 additionalProperties: true
141 properties:
142 enabled:
143 type: boolean
144 description: enable middleware in the list
145 properties: {}
146)");
155 std::string_view pipeline_name
160 std::vector<std::shared_ptr<MiddlewareBase>> CreateMiddlewares(
const HandlerInfo& info)
const override;
164 struct MiddlewareInfo
final {
165 const MiddlewareFactory* factory{
nullptr};
169 std::vector<MiddlewareInfo> middleware_infos_{};
172template <
typename MiddlewareBase,
typename HandlerInfo>
176 std::string_view pipeline_name
178 : components::ComponentBase(config, context) {
179 const auto& middlewares = config[
"middlewares"];
180 const auto& pipeline = context.FindComponent<impl::AnyMiddlewarePipelineComponent>(pipeline_name).GetPipeline();
181 for (
const auto& mid : pipeline.GetPerServiceMiddlewares(config.As<impl::MiddlewareRunnerConfig>())) {
182 const auto* factory = context.FindComponentOptional<MiddlewareFactory>(mid);
183 UINVARIANT(factory !=
nullptr, fmt::format(
"The middleware '{}' must exist", mid));
184 middleware_infos_.push_back(MiddlewareInfo{factory, middlewares[mid]});
188template <
typename MiddlewareBase,
typename HandlerInfo>
189std::vector<std::shared_ptr<MiddlewareBase>>
RunnerComponentBase<MiddlewareBase, HandlerInfo>::CreateMiddlewares(
190 const HandlerInfo& info
192 std::vector<std::shared_ptr<MiddlewareBase>> middlewares{};
193 middlewares.reserve(middleware_infos_.size());
194 for (
const auto& [factory, local_config] : middleware_infos_) {
195 auto config = impl::ValidateAndMergeMiddlewareConfigs(
196 factory->GetGlobalConfig(utils::impl::InternalTag{}), local_config, factory->GetMiddlewareConfigSchema()
198 middlewares.push_back(factory->CreateMiddleware(info, config));
209template <
typename MiddlewareBase,
typename Middleware,
typename HandlerInfo>
212 static constexpr std::string_view kName = Middleware::kName;
214 SimpleMiddlewareFactoryComponent(
221 middlewares::MiddlewareDependencyBuilder{Middleware::kDependency}
227 return std::make_shared<Middleware>();
237 middlewares::impl::SimpleMiddlewareFactoryComponent<MiddlewareBase, Middleware, HandlerInfo>> =
true;