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 {
36MiddlewareDependencyBuilder MakeDefaultUserDependency();
40 WithMiddlewareDependencyComponentBase(
47 virtual const middlewares::impl::MiddlewareDependency& GetMiddlewareDependency(
utils::impl::InternalTag)
const = 0;
50void LogConfiguration(std::string_view component_name,
const std::vector<std::string>& names);
52void LogValidateError(std::string_view middleware_name,
const std::exception& e);
59template <
typename MiddlewareBaseType,
typename HandlerInfo>
60class MiddlewareFactoryComponentBase :
public impl::WithMiddlewareDependencyComponentBase {
62 using MiddlewareBase = MiddlewareBaseType;
64 MiddlewareFactoryComponentBase(
67 MiddlewareDependencyBuilder&& builder = impl::MakeDefaultUserDependency()
69 : impl::WithMiddlewareDependencyComponentBase(config, context),
71 dependency_(std::move(builder).ExtractDependency(config.Name())) {}
79 virtual std::shared_ptr<
const MiddlewareBase>
84 virtual yaml_config::Schema GetMiddlewareConfigSchema()
const {
return GetStaticConfigSchema(); }
86 static yaml_config::Schema GetStaticConfigSchema() {
88type: object
89description: base class for grpc-server middleware
90additionalProperties: false
91properties:
92 enabled:
93 type: string
94 description: the flag to enable/disable middleware in the pipeline
95 defaultDescription: true
101 const middlewares::impl::MiddlewareDependency& GetMiddlewareDependency(
utils::impl::InternalTag)
const override {
105 const formats::
yaml::Value& GetGlobalConfig(
utils::impl::InternalTag)
const {
return global_config_; }
110 middlewares::impl::MiddlewareDependency dependency_;
60class MiddlewareFactoryComponentBase :
public impl::WithMiddlewareDependencyComponentBase {
…};
124template <
typename MiddlewareBase,
typename HandlerInfo>
126 public impl::PipelineCreatorInterface<MiddlewareBase, HandlerInfo> {
128 static yaml_config::Schema GetStaticConfigSchema() {
130type: object
131description: base class for all the gRPC service components
132additionalProperties: false
133properties:
134 disable-user-pipeline-middlewares:
135 type: boolean
136 description: flag to disable groups::User middlewares from pipeline
137 defaultDescription: false
138 disable-all-pipeline-middlewares:
139 type: boolean
140 description: flag to disable all middlewares from pipline
141 defaultDescription: false
142 middlewares:
143 type: object
144 description: overloads of configs of middlewares per service
145 additionalProperties:
146 type: object
147 description: a middleware config
148 additionalProperties: true
149 properties:
150 enabled:
151 type: boolean
152 description: enable middleware in the list
153 properties: {}
158 using MiddlewareFactory = MiddlewareFactoryComponentBase<MiddlewareBase, HandlerInfo>;
163 std::string_view pipeline_name
168 std::vector<std::shared_ptr<
const MiddlewareBase>> CreateMiddlewares(
const HandlerInfo& info)
const override;
172 struct MiddlewareInfo
final {
173 const MiddlewareFactory* factory{
nullptr};
177 std::vector<MiddlewareInfo> middleware_infos_{};
180template <
typename MiddlewareBase,
typename HandlerInfo>
181RunnerComponentBase<MiddlewareBase, HandlerInfo>::RunnerComponentBase(
184 std::string_view pipeline_name
187 const auto& middlewares = config
["middlewares"];
188 const auto& pipeline = context.FindComponent<impl::AnyMiddlewarePipelineComponent>(pipeline_name).GetPipeline();
189 const auto names = pipeline.GetPerServiceMiddlewares(config
.As<impl
::MiddlewareRunnerConfig
>());
190 impl::LogConfiguration(config.Name(), names);
191 for (
const auto& mid : names) {
192 const auto* factory = context.FindComponentOptional<MiddlewareFactory>(mid);
193 UINVARIANT(factory !=
nullptr, fmt::format(
"The middleware '{}' must exist", mid));
194 middleware_infos_.push_back(MiddlewareInfo{factory, middlewares
[mid
]});
199template <
typename MiddlewareBase,
typename HandlerInfo>
200std::vector<std::shared_ptr<
const MiddlewareBase>> RunnerComponentBase<MiddlewareBase, HandlerInfo>::CreateMiddlewares(
201 const HandlerInfo& info
203 std::vector<std::shared_ptr<
const MiddlewareBase>> middlewares{};
204 middlewares.reserve(middleware_infos_.size());
205 for (
const auto& [factory, local_config] : middleware_infos_) {
207 auto config = impl::ValidateAndMergeMiddlewareConfigs(
208 factory->GetGlobalConfig(
utils::impl::InternalTag{}), local_config, factory->GetMiddlewareConfigSchema()
210 middlewares.push_back(factory->CreateMiddleware(info, config));
211 }
catch (
const std::exception& e) {
212 impl::LogValidateError(factory->GetMiddlewareDependency(
utils::impl::InternalTag{}).middleware_name, e);
226template <
typename MiddlewareBase,
typename Middleware,
typename HandlerInfo>
227class SimpleMiddlewareFactoryComponent
final :
public MiddlewareFactoryComponentBase<MiddlewareBase, HandlerInfo> {
229 static constexpr std::string_view kName = Middleware::kName;
231 SimpleMiddlewareFactoryComponent(
235 : MiddlewareFactoryComponentBase<MiddlewareBase, HandlerInfo>(
238 middlewares::MiddlewareDependencyBuilder{Middleware::kDependency}
242 std::shared_ptr<
const MiddlewareBase> CreateMiddleware(
const HandlerInfo&,
const yaml_config::
YamlConfig&)
244 return std::make_shared<Middleware>();
252template <
typename MiddlewareBase,
typename Middleware,
typename HandlerInfo>
253inline constexpr bool components::kHasValidate<
254 middlewares::impl::SimpleMiddlewareFactoryComponent<MiddlewareBase, Middleware, HandlerInfo>> =
true;