utils: add serve file; router: log url; db: conversion between std::string & boost::json::string

This commit is contained in:
jie 2021-11-25 18:00:28 +08:00
parent 774efcec0d
commit 12c906e910
8 changed files with 94 additions and 59 deletions

View File

@ -35,7 +35,7 @@ int main(int argc, char* argv[]) {
} }
if (argc == 2) { if (argc == 2) {
try { 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; //std::cout << config_content << std::endl;
boost::json::object config_obj = boost::json::parse(config_content).as_object(); boost::json::object config_obj = boost::json::parse(config_content).as_object();
if (config_obj.contains("port")) if (config_obj.contains("port"))

View File

@ -28,7 +28,7 @@ bserv::db_relation_to_object orm_user{
std::optional<boost::json::object> get_user( std::optional<boost::json::object> get_user(
bserv::db_transaction& tx, bserv::db_transaction& tx,
const std::string& username) { const boost::json::string& username) {
bserv::db_result r = tx.exec( bserv::db_result r = tx.exec(
"select * from auth_user where username = ?", username); "select * from auth_user where username = ?", username);
lginfo << r.query(); // this is how you log info lginfo << r.query(); // this is how you log info
@ -101,7 +101,7 @@ boost::json::object user_register(
} }
auto username = params["username"].as_string(); auto username = params["username"].as_string();
bserv::db_transaction tx{ conn }; 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()) { if (opt_user.has_value()) {
return { return {
{"success", false}, {"success", false},
@ -115,7 +115,7 @@ boost::json::object user_register(
"first_name, last_name, email, is_active) values " "first_name, last_name, email, is_active) values "
"(?, ?, ?, ?, ?, ?, ?)", bserv::db_name("auth_user"), "(?, ?, ?, ?, ?, ?, ?)", bserv::db_name("auth_user"),
bserv::db_name("username"), bserv::db_name("username"),
username.c_str(), username,
bserv::utils::security::encode_password( bserv::utils::security::encode_password(
password.c_str()), false, password.c_str()), false,
get_or_empty(params, "first_name"), get_or_empty(params, "first_name"),
@ -151,7 +151,7 @@ boost::json::object user_login(
} }
auto username = params["username"].as_string(); auto username = params["username"].as_string();
bserv::db_transaction tx{ conn }; 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()) { if (!opt_user.has_value()) {
return { return {
{"success", false}, {"success", false},
@ -186,7 +186,7 @@ boost::json::object find_user(
std::shared_ptr<bserv::db_connection> conn, std::shared_ptr<bserv::db_connection> conn,
const std::string& username) { const std::string& username) {
bserv::db_transaction tx{ conn }; bserv::db_transaction tx{ conn };
auto user = get_user(tx, username); auto user = get_user(tx, username.c_str());
if (!user.has_value()) { if (!user.has_value()) {
return { return {
{"success", false}, {"success", false},

View File

@ -7,7 +7,6 @@
std::string template_root_; std::string template_root_;
std::string static_root_; std::string static_root_;
inja::Environment env;
void init_rendering(const std::string& template_root) { void init_rendering(const std::string& template_root) {
template_root_ = template_root; template_root_ = template_root;
@ -27,61 +26,13 @@ std::nullopt_t render(
const boost::json::object& context) { const boost::json::object& context) {
response.set(bserv::http::field::content_type, "text/html"); response.set(bserv::http::field::content_type, "text/html");
inja::json data = inja::json::parse(boost::json::serialize(context)); 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(); response.prepare_payload();
return std::nullopt; 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( std::nullopt_t serve(
bserv::response_type& response, bserv::response_type& response,
const std::string& file) { const std::string& file) {
response.set(bserv::http::field::content_type, mime_type(file)); return bserv::utils::file::serve(response, static_root_ + file);
response.body() = read_bin(static_root_ + file);
response.prepare_payload();
return std::nullopt;
} }

View File

@ -10,8 +10,6 @@ void init_rendering(const std::string& template_root);
void init_static_root(const std::string& static_root); void init_static_root(const std::string& static_root);
std::string read_bin(const std::string& file);
std::nullopt_t render( std::nullopt_t render(
bserv::response_type& response, bserv::response_type& response,
const std::string& template_path, const std::string& template_path,

View File

@ -149,6 +149,18 @@ namespace bserv {
} }
}; };
template <>
class db_value<boost::json::string> : 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 <> template <>
class db_value<bool> : public db_parameter { class db_value<bool> : public db_parameter {
private: private:

View File

@ -22,6 +22,7 @@
#include "utils.hpp" #include "utils.hpp"
#include "config.hpp" #include "config.hpp"
#include "websocket.hpp" #include "websocket.hpp"
#include "logging.hpp"
namespace bserv { namespace bserv {
@ -421,6 +422,7 @@ namespace bserv {
std::vector<std::string> url_params; std::vector<std::string> url_params;
for (auto& ptr : paths_) { for (auto& ptr : paths_) {
if (ptr->match(url, url_params)) { if (ptr->match(url, url_params)) {
lgtrace << "router: received request: " << url;
request_resources resources{ request_resources resources{
*resources_, *resources_,

View File

@ -7,6 +7,9 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <random> #include <random>
#include <optional>
#include "client.hpp"
namespace bserv::utils { namespace bserv::utils {
@ -57,6 +60,16 @@ namespace bserv::utils {
std::map<std::string, std::vector<std::string>>> std::map<std::string, std::vector<std::string>>>
parse_url(std::string& s); 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 } // bserv::utils
#endif // _UTILS_HPP #endif // _UTILS_HPP

View File

@ -4,6 +4,7 @@
#include <mutex> #include <mutex>
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <fstream>
#include <cryptopp/cryptlib.h> #include <cryptopp/cryptlib.h>
#include <cryptopp/pwdbased.h> #include <cryptopp/pwdbased.h>
@ -233,4 +234,62 @@ namespace bserv::utils {
return std::make_tuple(url, dict_params, list_params); 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 } // bserv::utils