/* * Copyright 2019-present ScyllaDB */ /* * This file is part of Scylla. * * Scylla is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Scylla is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Scylla. If not, see . */ #pragma once #include "alternator/executor.hh" #include #include #include #include #include #include "alternator/auth.hh" #include "utils/small_vector.hh" #include "utils/updateable_value.hh" #include namespace alternator { using chunked_content = rjson::chunked_content; class server { static constexpr size_t content_length_limit = 16*MB; using alternator_callback = std::function(executor&, executor::client_state&, tracing::trace_state_ptr, service_permit, rjson::value, std::unique_ptr)>; using alternator_callbacks_map = std::unordered_map; http_server _http_server; http_server _https_server; executor& _executor; cql3::query_processor& _qp; service::storage_proxy& _proxy; key_cache _key_cache; bool _enforce_authorization; utils::small_vector, 2> _enabled_servers; gate _pending_requests; alternator_callbacks_map _callbacks; semaphore* _memory_limiter; utils::updateable_value _max_concurrent_requests; class json_parser { static constexpr size_t yieldable_parsing_threshold = 16*KB; chunked_content _raw_document; rjson::value _parsed_document; std::exception_ptr _current_exception; semaphore _parsing_sem{1}; condition_variable _document_waiting; condition_variable _document_parsed; abort_source _as; future<> _run_parse_json_thread; public: json_parser(); // Moving a chunked_content into parse() allows parse() to free each // chunk as soon as it is parsed, so when chunks are relatively small, // we don't need to store the sum of unparsed and parsed sizes. future parse(chunked_content&& content); future<> stop(); }; json_parser _json_parser; public: server(executor& executor, cql3::query_processor& qp, service::storage_proxy& proxy); future<> init(net::inet_address addr, std::optional port, std::optional https_port, std::optional creds, bool enforce_authorization, semaphore* memory_limiter, utils::updateable_value max_concurrent_requests); future<> stop(); private: void set_routes(seastar::httpd::routes& r); // If verification succeeds, returns the authenticated user's username future verify_signature(const seastar::httpd::request&, const chunked_content&); future handle_api_request(std::unique_ptr req); }; }