30constexpr std::string_view kConfigBase = R"~(# yaml
31components_manager:
32 task_processors: # Task processor is an executor for coroutine tasks
33 main-task-processor: # Make a task processor for CPU-bound coroutine tasks.
34 worker_threads: 4 # Process tasks in 4 threads.
35
36 fs-task-processor: # Make a separate task processor for filesystem bound tasks.
37 worker_threads: 1
38
39 default_task_processor: main-task-processor # Task processor in which components start.
40
41 components: # Configuring components that were registered via component_list)~";
43constexpr std::string_view kConfigServerTemplate = R"~(
44 server:
45 listener: # configuring the main listening socket...
46 port: {} # ...to listen on this port and...
47 task_processor: main-task-processor # ...process incoming requests on this task processor.
48)~";
50constexpr std::string_view kConfigLoggingTemplate = R"~(
51 logging:
52 fs-task-processor: fs-task-processor
53 loggers:
54 default:
55 file_path: '@stderr'
56 level: {}
57 overflow_behavior: discard # Drop logs if the system is too busy to write them down.
58)~";
60constexpr std::string_view kConfigHandlerTemplate{
61 "path: {0} # Registering handler by URL '{0}'.\n"
63 "task_processor: main-task-processor # Run it on CPU bound task processor\n"
67 std::unordered_map<std::string, HttpBase::
Callback> http_functions;
68 std::optional<http::
ContentType> default_content_type;
69 std::string db_schema;
72SharedPyaload globals{};
78DependenciesBase::~DependenciesBase() =
default;
90 callback_{globals.http_functions.at(config
.Name())}
92 if (!callback_.content_type && globals.default_content_type) {
93 callback_.content_type = *globals.default_content_type;
97 std::string HandleRequestThrow(
const server::
http::HttpRequest& request, server::
request::RequestContext&)
99 if (callback_.content_type) {
102 return callback_.function(request, deps_);
105 FormattedErrorData GetFormattedExternalErrorBody(
const CustomHandlerException& exc)
const override {
106 if (callback_.content_type == http::
content_type::kApplicationJson) {
117 const impl::DependenciesBase& deps_;
121HttpBase::HttpBase(
int argc,
const char*
const argv[])
124 static_config_{kConfigBase},
128HttpBase::~HttpBase() {
129 static_config_.append(fmt::format(kConfigServerTemplate, port_));
130 static_config_.append(fmt::format(kConfigLoggingTemplate,
ToString(level_
)));
132 namespace po = boost::program_options;
133 po::variables_map vm;
135 std::string config_dump;
136 std::string schema_dump;
140 (
"dump-config", po::value(&config_dump)->implicit_value(
""),
"path to dump the server config")
141 (
"dump-db-schema", po::value(&schema_dump)->implicit_value(
""),
"path to dump the DB schema")
142 (
"config,c", po::value<std::string>(),
"path to server config")
147 po::store(po::parse_command_line(argc_, argv_, desc), vm);
149 }
catch (
const std::exception& ex) {
150 std::cerr << ex.what() <<
'\n' << desc <<
'\n';
154 if (vm.count(
"help")) {
155 std::cerr << desc <<
'\n';
159 if (vm.count(
"dump-config")) {
160 if (config_dump.empty()) {
161 std::cout << static_config_ << std::endl;
163 std::ofstream(config_dump) << static_config_;
168 if (vm.count(
"dump-db-schema")) {
169 if (schema_dump.empty()) {
170 std::cout << schema_dump << std::endl;
172 std::ofstream(schema_dump) << globals.db_schema;
190 auto component_name = fmt::format(
"{}-{}", path, fmt::join(methods,
","));
192 globals.http_functions.emplace(component_name, std::move(func));
194 AddComponentConfig(component_name, fmt::format(kConfigHandlerTemplate, path, fmt::join(methods,
",")));
197void HttpBase::AddComponentConfig(std::string_view name, std::string_view config) {
198 static_config_ += fmt::format(
"\n {}:", name);
199 if (config.empty()) {
200 static_config_ +=
" {}\n";
202 if (config.back() ==
'\n') {
203 config = std::string_view{config.data(), config.size() - 1};
205 static_config_ += boost::algorithm::replace_all_copy(
"\n" + std::string{config},
"\n",
"\n ");
206 static_config_ +=
'\n';
210void HttpBase::
DbSchema(std::string_view schema) { globals.db_schema = schema; }
212const std::string& HttpBase::
GetDbSchema()
noexcept {
return globals.db_schema; }
214void HttpBase::
Port(std::uint16_t port) { port_ = port; }
222 if (!db_schema.empty()) {
227void PgDep::RegisterOn(HttpBase& app) {
230 "dbconnection#env: POSTGRESQL\n"
231 "dbconnection#fallback: 'postgresql://testsuite@localhost:15433/postgres'\n"
232 "blocking_task_processor: fs-task-processor\n"
233 "dns_resolver: async\n"
248 "pool-statistics-disable: false\n"
249 "thread-name-prefix: http-client\n"
251 "fs-task-processor: fs-task-processor\n"
254 clients
::http
::MiddlewarePipelineComponent
>(clients
::http
::MiddlewarePipelineComponent
::kName, "");