#include "CourtApi.h" #include #include #include #include #include #include #include #include #include const char* serverDomain = "mirsud.spb.ru"; namespace { boost::asio::ssl::context sslContext(boost::asio::ssl::context::tlsv13_client); using ssl_stream = boost::asio::ssl::stream; } // namespace ssl_stream connect(boost::asio::io_context& asioContext, const std::string& hostname) { sslContext.set_verify_mode(boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert); sslContext.set_default_verify_paths(); boost::certify::enable_native_https_server_verification(sslContext); ssl_stream stream(asioContext, sslContext); static boost::asio::ip::tcp::resolver resolver(asioContext); auto const results = resolver.resolve(hostname, "https"); boost::certify::set_server_hostname(stream, hostname); boost::certify::sni_hostname(stream, hostname); boost::beast::get_lowest_layer(stream).connect(results); stream.handshake(boost::asio::ssl::stream_base::client); return stream; } std::pair get(ssl_stream& stream, const std::string& hostname, const std::string& url, std::optional payload = {}) { // Создать HTTP-запрос boost::beast::http::request request; request.method(boost::beast::http::verb::get); request.target(url); request.keep_alive(true); request.set(boost::beast::http::field::host, hostname); if (payload) { request.set(boost::beast::http::field::content_type, "application/json"); request.body() = std::move(*payload); } std::cout << "tx: " << request << std::endl; boost::beast::http::write(stream, request); boost::beast::http::response response; boost::beast::flat_buffer buffer; boost::beast::http::read(stream, buffer, response); std::cout << "rx: " << response << std::endl; return {response.base().result_int(), response.body()}; } nlohmann::json getResults(ssl_stream& stream, const std::string_view& uuid) { int status; std::string result; std::tie(status, result) = get(stream, serverDomain, fmt::format("/cases/api/results/?id={}", uuid)); if (status == 200) { return nlohmann::json::parse(result); } else throw std::runtime_error( fmt::format("failed to retrieve JSON (server returned code {})", status)); } nlohmann::json getCaseDetails(boost::asio::io_context& asioContext, int courtId, const std::string_view& caseNumber) { ssl_stream stream = connect(asioContext, serverDomain); int status; std::string result; std::tie(status, result) = get(stream, serverDomain, fmt::format("/cases/api/detail/?id={}&court_site_id={}", caseNumber, courtId)); if (status == 200) { auto uuid = nlohmann::json::parse(result).at("id").get(); for (int i = 0; i < 10; i++) { auto results = getResults(stream, uuid); bool finished = results.at("finished").get(); if (finished) return results.at("result"); else std::this_thread::sleep_for(std::chrono::seconds(1)); } throw std::runtime_error("failed to get results in time"); } else throw std::runtime_error( fmt::format("failed to retrieve JSON (server returned code {})", status)); } std::vector parseHistory(const nlohmann::json& details) { std::vector items; const auto& history = details.at("history"); for (const auto& obj : history) { CaseHistoryItem item; item.date = obj.at("date").get(); item.time = obj.at("time").get(); item.status = obj.at("status").get(); item.publishDate = obj.at("publish_date").get(); item.publishTime = obj.at("publish_time").get(); items.push_back(std::move(item)); } return items; }