#include "ServiceLogic.h" #include "Core/Logger.h" #include "Core/Singleton.h" #include "HttpSession.h" #include "Settings.h" #include #include #include #include namespace ServiceLogic { using namespace boost::beast; std::string extractToken(const std::string &cookieHeader, const std::string &tokenName = "access_token") { // 格式示例:"access_token=abc123; Path=/; Expires=Wed, 21 Oct 2023 07:28:00 GMT" size_t startPos = cookieHeader.find(tokenName + "="); if (startPos == std::string::npos) { return ""; } startPos += tokenName.size() + 1; // 跳过 "token_name=" size_t endPos = cookieHeader.find(';', startPos); if (endPos == std::string::npos) { endPos = cookieHeader.size(); } std::string token = cookieHeader.substr(startPos, endPos - startPos); // 移除可能的引号和空格 token.erase(std::remove(token.begin(), token.end(), '"'), token.end()); token.erase(std::remove(token.begin(), token.end(), ' '), token.end()); return token; } boost::beast::http::response serverError(const boost::beast::http::request &request, std::string_view errorMessage) { using namespace boost::beast; http::response res{http::status::internal_server_error, request.version()}; res.set(http::field::server, BOOST_BEAST_VERSION_STRING); res.set(http::field::content_type, "text/html"); res.keep_alive(request.keep_alive()); std::ostringstream oss; oss << "An error occurred: '" << errorMessage << "'"; res.body() = oss.str(); res.prepare_payload(); return res; } http::response badRequest(const http::request &request, std::string_view why) { http::response res{http::status::bad_request, request.version()}; res.set(http::field::server, BOOST_BEAST_VERSION_STRING); res.set(http::field::content_type, "text/html"); res.keep_alive(request.keep_alive()); res.body() = std::string(why); res.prepare_payload(); return res; } void staticFilesDeploy() { using namespace Core; using namespace boost::urls; auto application = Singleton::instance(); // clang-format off application->insertUrl("/{path*}", [](Danki::HttpSession &session, const Danki::Application::Request &request, const matches &matches) { using namespace boost::beast; url_view view(request.target()); auto target = view.path(); LOG(info) << target; if (target.find("..") != boost::beast::string_view::npos) { session.reply(ServiceLogic::badRequest(request, "Illegal request-target")); return; } auto settings = Singleton::instance(); std::string path = ResponseUtility::pathCat(settings->documentRoot(), target); if (target.back() == '/') path.append("index.html"); if (std::filesystem::is_directory(path)) path.append("/index.html"); boost::beast::error_code ec; http::file_body::value_type body; body.open(path.c_str(), boost::beast::file_mode::scan, ec); if (ec == boost::beast::errc::no_such_file_or_directory) { std::ostringstream oss; oss << "The resource '" << target << "' was not found."; LOG(error) << oss.str(); session.errorReply(request, http::status::not_found, oss.str()); return; } else if (ec) { session.reply(ServiceLogic::serverError(request, ec.message())); return; } auto const size = body.size(); http::response res{std::piecewise_construct, std::make_tuple(std::move(body)), std::make_tuple(http::status::ok, request.version())}; res.set(http::field::server, BOOST_BEAST_VERSION_STRING); res.set(http::field::content_type, ResponseUtility::mimeType(path)); res.content_length(size); res.keep_alive(request.keep_alive()); session.reply(std::move(res)); }); // clang-format on } } // namespace ServiceLogic