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);
53yaml_config::Schema GetMiddlewareFactoryComponentBaseSchema();
68template <
typename MiddlewareBaseType,
typename HandlerInfo>
69class MiddlewareFactoryComponentBase :
public impl::WithMiddlewareDependencyComponentBase {
71 using MiddlewareBase = MiddlewareBaseType;
73 MiddlewareFactoryComponentBase(
76 MiddlewareDependencyBuilder&& builder = impl::MakeDefaultUserDependency()
78 : impl::WithMiddlewareDependencyComponentBase(config, context),
80 dependency_(std::move(builder).ExtractDependency(config
.Name()))
89 virtual std::shared_ptr<
const MiddlewareBase> CreateMiddleware(
90 const HandlerInfo& info,
96 virtual yaml_config::Schema GetMiddlewareConfigSchema()
const {
return GetStaticConfigSchema(); }
98 static yaml_config::Schema GetStaticConfigSchema() {
return impl::GetMiddlewareFactoryComponentBaseSchema(); }
102 const middlewares::impl::MiddlewareDependency& GetMiddlewareDependency(utils::
impl::InternalTag)
const override {
106 const formats::
yaml::Value& GetGlobalConfig(utils::
impl::InternalTag)
const {
return global_config_; }
111 middlewares::impl::MiddlewareDependency dependency_;
131template <
typename MiddlewareBase,
typename HandlerInfo>
132class RunnerComponentBase
134 public impl::PipelineCreatorInterface<MiddlewareBase, HandlerInfo> {
136 static yaml_config::Schema GetStaticConfigSchema() {
return impl::GetRunnerComponentBaseSchema(); }
139 using MiddlewareFactory = MiddlewareFactoryComponentBase<MiddlewareBase, HandlerInfo>;
144 std::string_view pipeline_name
149 std::vector<std::shared_ptr<
const MiddlewareBase>> CreateMiddlewares(
const HandlerInfo& info)
const override;
153 struct MiddlewareInfo
final {
154 const MiddlewareFactory* factory{
nullptr};
158 std::vector<MiddlewareInfo> middleware_infos_{};
161template <
typename MiddlewareBase,
typename HandlerInfo>
162RunnerComponentBase<MiddlewareBase, HandlerInfo>::RunnerComponentBase(
165 std::string_view pipeline_name
168 const auto& middlewares = config
["middlewares"];
169 const auto& pipeline = context.FindComponent<impl::AnyMiddlewarePipelineComponent>(pipeline_name).GetPipeline();
170 const auto names = pipeline.GetPerServiceMiddlewares(config
.As<impl
::MiddlewareRunnerConfig
>());
171 impl::LogConfiguration(config
.Name(), names);
172 for (
const auto& mid : names) {
173 const auto* factory = context.FindComponentOptional<MiddlewareFactory>(mid);
174 UINVARIANT(factory !=
nullptr, fmt::format(
"The middleware '{}' must exist", mid));
175 middleware_infos_.push_back(MiddlewareInfo{factory, middlewares
[mid
]});
180template <
typename MiddlewareBase,
typename HandlerInfo>
181std::vector<std::shared_ptr<
const MiddlewareBase>> RunnerComponentBase<
183 HandlerInfo>::CreateMiddlewares(
const HandlerInfo& info)
const {
184 std::vector<std::shared_ptr<
const MiddlewareBase>> middlewares{};
185 middlewares.reserve(middleware_infos_.size());
186 for (
const auto& [factory, local_config] : middleware_infos_) {
188 auto config = impl::ValidateAndMergeMiddlewareConfigs(
189 factory->GetGlobalConfig(utils::
impl::InternalTag{}),
191 factory->GetMiddlewareConfigSchema()
193 middlewares.push_back(factory->CreateMiddleware(info, config));
194 }
catch (
const std::exception& e) {
195 impl::LogValidateError(factory->GetMiddlewareDependency(utils::
impl::InternalTag{}).middleware_name, e);
209template <
typename MiddlewareBase,
typename Middleware,
typename HandlerInfo>
210class SimpleMiddlewareFactoryComponent
final :
public MiddlewareFactoryComponentBase<MiddlewareBase, HandlerInfo> {
212 static constexpr std::string_view kName = Middleware::kName;
214 SimpleMiddlewareFactoryComponent(
218 : MiddlewareFactoryComponentBase<
220 HandlerInfo>(config, context, middlewares::MiddlewareDependencyBuilder{Middleware::kDependency}) {}
223 std::shared_ptr<
const MiddlewareBase> CreateMiddleware(
const HandlerInfo&,
const yaml_config::
YamlConfig&)
225 return std::make_shared<Middleware>();
233template <
typename MiddlewareBase,
typename Middleware,
typename HandlerInfo>
234inline constexpr bool components::kHasValidate<
235 middlewares::impl::SimpleMiddlewareFactoryComponent<MiddlewareBase, Middleware, HandlerInfo>> =
true;