From 12c906e910e9f15248506f29c0baf4bbad2f9e8e Mon Sep 17 00:00:00 2001 From: jie Date: Thu, 25 Nov 2021 18:00:28 +0800 Subject: [PATCH] utils: add serve file; router: log url; db: conversion between std::string & boost::json::string --- WebApp/WebApp.cpp | 2 +- WebApp/handlers.cpp | 10 +++--- WebApp/rendering.cpp | 53 ++-------------------------- WebApp/rendering.h | 2 -- bserv/include/bserv/database.hpp | 12 +++++++ bserv/include/bserv/router.hpp | 2 ++ bserv/include/bserv/utils.hpp | 13 +++++++ bserv/utils.cpp | 59 ++++++++++++++++++++++++++++++++ 8 files changed, 94 insertions(+), 59 deletions(-) diff --git a/WebApp/WebApp.cpp b/WebApp/WebApp.cpp index f83b946..82de688 100644 --- a/WebApp/WebApp.cpp +++ b/WebApp/WebApp.cpp @@ -35,7 +35,7 @@ int main(int argc, char* argv[]) { } if (argc == 2) { try { - std::string config_content = read_bin(argv[1]); + std::string config_content = bserv::utils::file::read_bin(argv[1]); //std::cout << config_content << std::endl; boost::json::object config_obj = boost::json::parse(config_content).as_object(); if (config_obj.contains("port")) diff --git a/WebApp/handlers.cpp b/WebApp/handlers.cpp index b01581a..94b5afc 100644 --- a/WebApp/handlers.cpp +++ b/WebApp/handlers.cpp @@ -28,7 +28,7 @@ bserv::db_relation_to_object orm_user{ std::optional get_user( bserv::db_transaction& tx, - const std::string& username) { + const boost::json::string& username) { bserv::db_result r = tx.exec( "select * from auth_user where username = ?", username); lginfo << r.query(); // this is how you log info @@ -101,7 +101,7 @@ boost::json::object user_register( } auto username = params["username"].as_string(); bserv::db_transaction tx{ conn }; - auto opt_user = get_user(tx, username.c_str()); + auto opt_user = get_user(tx, username); if (opt_user.has_value()) { return { {"success", false}, @@ -115,7 +115,7 @@ boost::json::object user_register( "first_name, last_name, email, is_active) values " "(?, ?, ?, ?, ?, ?, ?)", bserv::db_name("auth_user"), bserv::db_name("username"), - username.c_str(), + username, bserv::utils::security::encode_password( password.c_str()), false, get_or_empty(params, "first_name"), @@ -151,7 +151,7 @@ boost::json::object user_login( } auto username = params["username"].as_string(); bserv::db_transaction tx{ conn }; - auto opt_user = get_user(tx, username.c_str()); + auto opt_user = get_user(tx, username); if (!opt_user.has_value()) { return { {"success", false}, @@ -186,7 +186,7 @@ boost::json::object find_user( std::shared_ptr conn, const std::string& username) { bserv::db_transaction tx{ conn }; - auto user = get_user(tx, username); + auto user = get_user(tx, username.c_str()); if (!user.has_value()) { return { {"success", false}, diff --git a/WebApp/rendering.cpp b/WebApp/rendering.cpp index 6d03cfd..eadae09 100644 --- a/WebApp/rendering.cpp +++ b/WebApp/rendering.cpp @@ -7,7 +7,6 @@ std::string template_root_; std::string static_root_; -inja::Environment env; void init_rendering(const std::string& template_root) { template_root_ = template_root; @@ -27,61 +26,13 @@ std::nullopt_t render( const boost::json::object& context) { response.set(bserv::http::field::content_type, "text/html"); inja::json data = inja::json::parse(boost::json::serialize(context)); - response.body() = env.render_file(template_root_ + template_file, data); + response.body() = inja::Environment{}.render_file(template_root_ + template_file, data); response.prepare_payload(); return std::nullopt; } -// Return a reasonable mime type based on the extension of a file. -boost::beast::string_view -mime_type(boost::beast::string_view path) { - using boost::beast::iequals; - auto const ext = [&path] { - auto const pos = path.rfind("."); - if (pos == boost::beast::string_view::npos) - return boost::beast::string_view{}; - return path.substr(pos); - }(); - if (iequals(ext, ".htm")) return "text/html"; - if (iequals(ext, ".html")) return "text/html"; - if (iequals(ext, ".php")) return "text/html"; - if (iequals(ext, ".css")) return "text/css"; - if (iequals(ext, ".txt")) return "text/plain"; - if (iequals(ext, ".js")) return "application/javascript"; - if (iequals(ext, ".json")) return "application/json"; - if (iequals(ext, ".xml")) return "application/xml"; - if (iequals(ext, ".swf")) return "application/x-shockwave-flash"; - if (iequals(ext, ".flv")) return "video/x-flv"; - if (iequals(ext, ".png")) return "image/png"; - if (iequals(ext, ".jpe")) return "image/jpeg"; - if (iequals(ext, ".jpeg")) return "image/jpeg"; - if (iequals(ext, ".jpg")) return "image/jpeg"; - if (iequals(ext, ".gif")) return "image/gif"; - if (iequals(ext, ".bmp")) return "image/bmp"; - if (iequals(ext, ".ico")) return "image/vnd.microsoft.icon"; - if (iequals(ext, ".tiff")) return "image/tiff"; - if (iequals(ext, ".tif")) return "image/tiff"; - if (iequals(ext, ".svg")) return "image/svg+xml"; - if (iequals(ext, ".svgz")) return "image/svg+xml"; - return "application/text"; -} - -std::string read_bin(const std::string& file) { - std::ifstream fin(file, std::ios_base::in | std::ios_base::binary); - std::string res; - while (true) { - char c = (char)fin.get(); - if (fin.eof()) break; - res += c; - } - return res; -} - std::nullopt_t serve( bserv::response_type& response, const std::string& file) { - response.set(bserv::http::field::content_type, mime_type(file)); - response.body() = read_bin(static_root_ + file); - response.prepare_payload(); - return std::nullopt; + return bserv::utils::file::serve(response, static_root_ + file); } diff --git a/WebApp/rendering.h b/WebApp/rendering.h index e7b7ab8..d6eea6a 100644 --- a/WebApp/rendering.h +++ b/WebApp/rendering.h @@ -10,8 +10,6 @@ void init_rendering(const std::string& template_root); void init_static_root(const std::string& static_root); -std::string read_bin(const std::string& file); - std::nullopt_t render( bserv::response_type& response, const std::string& template_path, diff --git a/bserv/include/bserv/database.hpp b/bserv/include/bserv/database.hpp index 6582b27..91eefc8 100644 --- a/bserv/include/bserv/database.hpp +++ b/bserv/include/bserv/database.hpp @@ -149,6 +149,18 @@ namespace bserv { } }; + template <> + class db_value : public db_parameter { + private: + std::string value_; + public: + db_value(const boost::json::string& value) + : value_{ value } {} + std::string get_value(raw_db_transaction_type& tx) { + return tx.quote(value_); + } + }; + template <> class db_value : public db_parameter { private: diff --git a/bserv/include/bserv/router.hpp b/bserv/include/bserv/router.hpp index ad231ce..4fabbdf 100644 --- a/bserv/include/bserv/router.hpp +++ b/bserv/include/bserv/router.hpp @@ -22,6 +22,7 @@ #include "utils.hpp" #include "config.hpp" #include "websocket.hpp" +#include "logging.hpp" namespace bserv { @@ -421,6 +422,7 @@ namespace bserv { std::vector url_params; for (auto& ptr : paths_) { if (ptr->match(url, url_params)) { + lgtrace << "router: received request: " << url; request_resources resources{ *resources_, diff --git a/bserv/include/bserv/utils.hpp b/bserv/include/bserv/utils.hpp index 32d4b96..b21929c 100644 --- a/bserv/include/bserv/utils.hpp +++ b/bserv/include/bserv/utils.hpp @@ -7,6 +7,9 @@ #include #include #include +#include + +#include "client.hpp" namespace bserv::utils { @@ -57,6 +60,16 @@ namespace bserv::utils { std::map>> parse_url(std::string& s); + namespace file { + + std::string read_bin(const std::string& filename); + + std::nullopt_t serve( + response_type& response, + const std::string& filename); + + } // file + } // bserv::utils #endif // _UTILS_HPP \ No newline at end of file diff --git a/bserv/utils.cpp b/bserv/utils.cpp index 68ffad1..2a04c16 100644 --- a/bserv/utils.cpp +++ b/bserv/utils.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -233,4 +234,62 @@ namespace bserv::utils { return std::make_tuple(url, dict_params, list_params); } + namespace file { + + std::string read_bin(const std::string& filename) { + std::ifstream fin(filename, std::ios_base::in | std::ios_base::binary); + std::string res; + while (true) { + char c = (char)fin.get(); + if (fin.eof()) break; + res += c; + } + return res; + } + + // returns a reasonable mime type based on the extension of a file. + boost::beast::string_view + mime_type(boost::beast::string_view path) { + using boost::beast::iequals; + auto const ext = [&path] { + auto const pos = path.rfind("."); + if (pos == boost::beast::string_view::npos) + return boost::beast::string_view{}; + return path.substr(pos); + }(); + if (iequals(ext, ".htm")) return "text/html"; + if (iequals(ext, ".html")) return "text/html"; + if (iequals(ext, ".php")) return "text/html"; + if (iequals(ext, ".css")) return "text/css"; + if (iequals(ext, ".txt")) return "text/plain"; + if (iequals(ext, ".js")) return "application/javascript"; + if (iequals(ext, ".json")) return "application/json"; + if (iequals(ext, ".xml")) return "application/xml"; + if (iequals(ext, ".swf")) return "application/x-shockwave-flash"; + if (iequals(ext, ".flv")) return "video/x-flv"; + if (iequals(ext, ".png")) return "image/png"; + if (iequals(ext, ".jpe")) return "image/jpeg"; + if (iequals(ext, ".jpeg")) return "image/jpeg"; + if (iequals(ext, ".jpg")) return "image/jpeg"; + if (iequals(ext, ".gif")) return "image/gif"; + if (iequals(ext, ".bmp")) return "image/bmp"; + if (iequals(ext, ".ico")) return "image/vnd.microsoft.icon"; + if (iequals(ext, ".tiff")) return "image/tiff"; + if (iequals(ext, ".tif")) return "image/tiff"; + if (iequals(ext, ".svg")) return "image/svg+xml"; + if (iequals(ext, ".svgz")) return "image/svg+xml"; + return "application/text"; + } + + std::nullopt_t serve( + response_type& response, + const std::string& filename) { + response.set(bserv::http::field::content_type, mime_type(filename)); + response.body() = read_bin(filename); + response.prepare_payload(); + return std::nullopt; + } + + } // file + } // bserv::utils \ No newline at end of file