Older/Server/ServiceLogic.inl
2023-07-21 16:17:01 +08:00

131 lines
4.9 KiB
C++

#ifndef SERVICELOGIC_INL
#define SERVICELOGIC_INL
#include "BoostLog.h"
#include "ServiceLogic.h"
#include "WeChatContext/WeChatContext.h"
#include <boost/beast/http/empty_body.hpp>
#include <boost/beast/http/file_body.hpp>
#include <boost/json/parse.hpp>
#include <boost/json/serialize.hpp>
#include <boost/nowide/fstream.hpp>
#include <boost/url.hpp>
#include <filesystem>
namespace ServiceLogic {
template <class Send>
static void onGetBlogImage(SharedStatePtr state, StringRequest &&request, Send &&send) {
using namespace boost::beast;
boost::urls::url url(request.target());
if (url.path().size() < 12) return;
auto file = url.path().substr(12);
auto root = state->notebookRoot();
auto path = ResponseUtility::pathCat(root, file);
boost::nowide::ifstream ifs(path, boost::nowide::ifstream::binary);
std::vector<char> file_string(std::istreambuf_iterator<char>{ifs}, std::istreambuf_iterator<char>{});
boost::beast::error_code ec;
http::response<boost::beast::http::vector_body<char>> s;
s.set(http::field::server, BOOST_BEAST_VERSION_STRING);
s.set(http::field::content_type, ResponseUtility::mimeType(path));
s.keep_alive(request.keep_alive());
s.body() = std::move(file_string);
s.prepare_payload();
return send(std::move(s));
}
template <class Send>
static void onGetBlogContent(SharedStatePtr state, StringRequest &&request, Send &&send, const std::string &prefix) {
using namespace boost::beast;
boost::urls::url url(request.target());
auto file = url.path().substr(prefix.length());
auto root = state->notebookRoot();
auto path = ResponseUtility::pathCat(root, file);
LOG(info) << "get file: " << path;
if (!std::filesystem::exists(path)) {
return send(notFound(request));
}
boost::nowide::ifstream ifs(path);
std::string file_string(std::istreambuf_iterator<char>{ifs}, std::istreambuf_iterator<char>{});
http::response<boost::beast::http::string_body> s;
s.set(http::field::server, BOOST_BEAST_VERSION_STRING);
s.set(http::field::content_type, "text/markdown;charset=UTF-8");
s.keep_alive(request.keep_alive());
s.body() = file_string;
s.prepare_payload();
return send(std::move(s));
}
template <class Send>
void onDownload(SharedStatePtr state, StringRequest &&request, Send &&send) {
LOG(info) << "onDownload";
using namespace boost::beast;
std::string_view file;
if (request.target() == "/download") {
auto requestData = boost::json::parse(request.body());
file = requestData.as_object()["file"].as_string();
} else {
file = request.target().substr(9);
}
auto path = ResponseUtility::pathCat(state->fileRoot(), file);
LOG(info) << "get file: " << path;
// Attempt to open the file
boost::beast::error_code ec;
http::file_body::value_type body;
body.open(path.c_str(), boost::beast::file_mode::scan, ec);
// Handle the case where the file doesn't exist
if (ec == boost::system::errc::no_such_file_or_directory) {
return send(notFound(request));
} else if (ec) { // Handle an unknown error
return send(serverError(request, ec.message()));
}
// Cache the size since we need it after the move
auto const size = body.size();
// Respond to GET request
http::response<http::file_body> 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.set(http::field::content_description, file);
res.set(http::field::accept_charset, "utf-8");
res.content_length(size);
res.keep_alive(request.keep_alive());
return send(std::move(res));
}
template <class Send>
static void onWechat(SharedStatePtr state, const StringRequest &request, Send &&send) {
using namespace boost::beast;
boost::urls::url url(request.target());
auto context = Amass::Singleton<WeChatContext>::instance();
http::response<boost::beast::http::string_body> response;
if (request.count("Content-Type") > 0 && request.at("Content-Type") == "text/xml") {
response.body() = context->reply(request.body());
} else {
auto query = url.params();
if (auto iterator = query.find("echostr"); iterator != query.end()) {
response.body() = (*iterator)->value;
}
}
boost::beast::error_code ec;
response.set(http::field::server, BOOST_BEAST_VERSION_STRING);
response.set(http::field::content_type, "text/xml;charset=UTF-8");
response.keep_alive(request.keep_alive());
response.prepare_payload();
return send(std::move(response));
}
} // namespace ServiceLogic
#endif // SERVICELOGIC_INL