优化,增加动态订阅

This commit is contained in:
xx
2024-06-08 14:31:20 +08:00
parent 8fb96b705d
commit eafccc9117
16 changed files with 283 additions and 163 deletions

View File

@@ -31,7 +31,8 @@ Initialization_script=${www}/api/lib/init.lua
debug=1
; 绑定域名
domain=["local.newobj.org","127.0.0.1"]
; 允许请求URL的路径直接映射到网站路径中的lua。如你的站点只允许订阅绑定模式则设置为0关闭此功能以提高安全性。
direct_url_mapping=1
[log]
; 开启或关闭
enable=1

View File

@@ -87,10 +87,7 @@ bool fastweb::app::start(const std::string& config_filepath)
if (initialization_script() == false)
return false;
// 加载订阅
subscribe->load(router);
this->subscribe->start();
return m_center->start();
}

View File

@@ -100,6 +100,7 @@ void fastweb::config::cache()
website.Initialization_script = m_ini.read("website", "Initialization_script");
website.debug = m_ini.read("website", "debug") == "1";
website.domain = ylib::json::from(m_ini.read("website", "domain")).to<std::vector<std::string>>();
website.direct_url_mapping = m_ini.read("website", "direct_url_mapping") == "1";
log.enable = m_ini.read("log", "enable") == "1";
log.dir = m_ini.read("log", "dir");

View File

@@ -31,6 +31,7 @@ namespace fastweb
std::string Initialization_script;
bool debug = false;
std::vector<std::string> domain;
bool direct_url_mapping = false;
};
struct log {

View File

@@ -12,43 +12,40 @@ fastweb::interceptor_manager::~interceptor_manager()
{
clear();
}
bool fastweb::interceptor_manager::add(const std::string& regex_express, const std::string& filepath)
bool fastweb::interceptor_manager::add(const std::string& pattern, const std::string& filepath)
{
if (interceptor_manager::interceptor.exist(regex_express))
{
LOG_WARN("`" + regex_express + "` interceptor is invalid, duplicate rule, filepath: " + filepath);
return false;
}
interceptor_manager::interceptor.add(regex_express, filepath);
app()->router->interceptor()->add(regex_express, [this](network::http::reqpack* reqpack, const std::string& express_string)->bool {
return this->callback(reqpack, express_string);
app()->router->interceptor()->add(pattern,filepath, [&](network::http::reqpack* reqpack, const std::string& pattern,const std::string& filepath)->bool {
return this->callback(reqpack, pattern, filepath);
});
return true;
}
bool fastweb::interceptor_manager::remove(const std::string& regex_express)
bool fastweb::interceptor_manager::remove(const std::string& pattern)
{
interceptor_manager::interceptor.del(regex_express);
return app()->router->interceptor()->remove(regex_express);
return app()->router->interceptor()->remove(pattern);
}
bool fastweb::interceptor_manager::exist(const std::string& regex_express)
bool fastweb::interceptor_manager::exist(const std::string& pattern)
{
return interceptor_manager::interceptor.exist(regex_express);
return app()->router->interceptor()->exist(pattern);
}
void fastweb::interceptor_manager::clear()
{
interceptor_manager::interceptor.clear();
if(app()->router != nullptr)
app()->router->interceptor()->clear();
}
bool fastweb::interceptor_manager::callback(network::http::reqpack* reqpack, const std::string& express_string)
bool fastweb::interceptor_manager::callback(network::http::reqpack* reqpack, const std::string& pattern, const std::string& filepath)
{
if (ylib::file::ext(filepath) != "lua")
{
reqpack->response()->send_file(filepath);
return false;
}
bool ok_continue = false;
auto lua = app()->state->get();
std::string exception_string;
try
{
sol::load_result script = lua->state->load_file(interceptor_manager::interceptor[express_string]);
sol::load_result script = lua->state->load_file(app()->config->website.dir+ filepath);
if (!script.valid()) {
sol::error err = script;
throw ylib::exception(err.what());

View File

@@ -18,18 +18,17 @@ namespace fastweb
interceptor_manager(fastweb::app* app);
~interceptor_manager();
bool add(const std::string& regex_express,const std::string& filepath);
bool remove(const std::string& regex_express);
bool exist(const std::string& regex_express);
bool add(const std::string& pattern,const std::string& filepath);
bool remove(const std::string& pattern);
bool exist(const std::string& pattern);
void clear();
private:
/// <summary>
/// 服务回调
/// </summary>
/// <param name="reqpack"></param>
/// <param name="express_string"></param>
bool callback(network::http::reqpack* reqpack, const std::string& express_string);
private:
ylib::map<std::string, std::string> interceptor;
/// <param name="pattern"></param>
/// <param name="filepath"></param>
bool callback(network::http::reqpack* reqpack, const std::string& pattern,const std::string& filepath);
};
}

View File

@@ -25,42 +25,61 @@ void fastweb::log::print(const std::string& type,const std::string& msg,const st
#else
ylib::println(msg, (ylib::ConsoleTextColor)color);
#endif
if (app()->config->log.enable)
{
std::string logcontent = __now_time + " " + type + " " + msg
std::string logcontent = __now_time + " " + type + " " + msg
#ifdef _WIN32
+ "\r\n";
+ "\r\n";
#else
+ "\n";
+ "\n";
#endif
std::string new_time = time::now_time(app()->config->log.name);
if (new_time == "")
m_queue.push(logcontent);
}
bool fastweb::log::run()
{
if (app()->config == nullptr)
{
system::sleep_msec(1000);
return true;
}
if (app()->config->log.enable == false)
{
system::sleep_msec(1000);
return true;
}
std::string logcontent;
std::string new_time = time::now_time(app()->config->log.name);
if (new_time == "")
{
std::cout << "error: The log file name is incorrect: " << app()->config->log.name << std::endl;
return false;
}
if (m_current_name != new_time)
{
m_current_name = new_time;
ylib::file::create_dir(app()->config->log.dir, true);
std::string newfilepath = app()->config->log.dir + "/" + new_time;
m_file.close();
if (m_file.open(newfilepath) == false)
{
std::cout << "error: The log file name is incorrect: " << app()->config->log.name << std::endl;
return;
}
if (m_current_name != new_time)
{
ylib::file::create_dir(app()->config->log.dir, true);
std::string newfilepath = app()->config->log.dir + "/" + new_time;
m_file.close();
if (m_file.open(newfilepath) == false)
{
std::cout << "error: open log file failed, filepath: " << newfilepath << std::endl;
return;
}
std::cout << "error: open log file failed, filepath: " << newfilepath << std::endl;
return false;
}
}
while (m_queue.pop(logcontent))
{
m_file.appead(logcontent);
}
system::sleep_msec(1000);
return true;
}
fastweb::log::log(fastweb::app* ptr):Interface(ptr)
{
::ithread::start();
}
fastweb::log::~log()
{
::ithread::stop();
::ithread::wait();
}
void fastweb::log::success(const std::string& msg, const std::string& filepath, const std::string& func, int line)
{

View File

@@ -2,9 +2,11 @@
#include <string>
#include "util/file.h"
#include "core/define.h"
#include "util/thread.h"
#include "util/queue.hpp"
namespace fastweb
{
class log :public Interface {
class log :public Interface,private ylib::ithread {
public:
log(fastweb::app* ptr);
~log();
@@ -17,10 +19,13 @@ namespace fastweb
void lua(const std::string& msg);
private:
void print(const std::string& type, const std::string& msg, const std::string& filepath, const std::string& func, int line, int color, bool error);
bool run() override;
private:
// 当前文件名
std::string m_current_name;
// 文件
ylib::file_io m_file;
// 日志队列
ylib::queue<std::string> m_queue;
};
}

View File

@@ -15,6 +15,7 @@
#include "module/http/session.h"
#include "module/http/httpclient.h"
#include "module/http/interceptor.h"
#include "module/http/subscribe.h"
#include "module/globalfuns.h"
#include "module/mutex.h"
#include "module/codec.h"
@@ -117,6 +118,7 @@ void fastweb::module_manager::load_core(sol::state* lua)
module::request::regist(lua);
module::response::regist(lua);
module::interceptor::regist(lua);
module::subscribe::regist(lua);
module::session::regist(lua);
module::httpclient::regist(lua);
module::globalfuncs::regist(lua);

View File

@@ -1,110 +1,61 @@
#include "subscribemanager.h"
#include "core/subscribemanager.h"
#include "core/config.h"
#include "core/app.h"
#include "core/statemanager.h"
#include "module/http/request.h"
#include "module/http/response.h"
fastweb::subscribe_manager::subscribe_manager(fastweb::app* ptr):Interface(ptr)
#include "net/http_subscribe.h"
fastweb::subscribe_manager::subscribe_manager(fastweb::app* app) :Interface(app)
{
}
fastweb::subscribe_manager::~subscribe_manager()
{
clear();
}
void fastweb::subscribe_manager::load(network::http::router* router)
void fastweb::subscribe_manager::start()
{
clear();
m_router = router;
router->other([&](network::http::request* request, network::http::response* response) {
this->other(request,response);
});
}
app()->router->other([&](network::http::request* request, network::http::response* response) {
this->other(request, response);
});
}
bool fastweb::subscribe_manager::add(const std::string& pattern, const std::string& filepath)
{
app()->router->subscribe()->add(pattern, filepath, [&](network::http::request* request, network::http::response* response, const std::string& pattern, const std::string& filepath)->bool {
return this->callback(request, response, pattern, filepath);
});
return true;
}
bool fastweb::subscribe_manager::remove(const std::string& pattern)
{
return app()->router->subscribe()->remove(pattern);
}
bool fastweb::subscribe_manager::exist(const std::string& pattern)
{
return app()->router->subscribe()->exist(pattern);
}
void fastweb::subscribe_manager::clear()
{
if (m_router != nullptr)
{
m_router->clear_subscribe();
}
for (size_t i = 0; i < m_subextra.size(); i++)
delete m_subextra[i];
m_subextra.clear();
m_router = nullptr;
}
void fastweb::subscribe_manager::other(network::http::request* request, network::http::response* response)
{
auto send_404 = [&](network::http::response* response) {
std::string default_404 = app()->config->website.dir + "\\" + app()->config->website.default_404;
if (app()->config->website.default_404 == "" || ylib::file::exist(default_404) == false)
{
response->send((std::string)"404 Not Found", 404, "Not Found");
}
else
{
response->send_file(default_404, -1, 404, "Not Found");
}
};
auto send_file = [&](network::http::response* response, std::string filepath)
{
if (ylib::file::exist(filepath))
{
if (ylib::file::ext(filepath) == "lua")
{
exec(filepath,request,response);
return;
}
response->send_file(filepath);
}
else
{
send_404(response);
}
};
std::string filepath;
if (strutils::right(request->filepath(),1) == "/")
{
for (size_t i = 0; i < app()->config->website.default_index.size(); i++)
{
filepath = app()->config->website.dir + request->filepath() + app()->config->website.default_index[i];
if (ylib::file::exist(filepath))
break;
}
}
else
filepath = app()->config->website.dir + request->filepath();
send_file(response, filepath);
if(app()->router != nullptr)
app()->router->subscribe()->clear();
}
void fastweb::subscribe_manager::exec(const std::string& filepath, network::http::request* request, network::http::response* response)
bool fastweb::subscribe_manager::callback(network::http::request* request, network::http::response* response, const std::string& pattern, const std::string& filepath)
{
bool ok_continue = false;
auto lua = app()->state->get();
std::string exception_string;
try
{
//auto lbResult = lua->state->load_file(filepath);
//if (lbResult.valid() == false)
//{
// sol::error err = lbResult;
// throw ylib::exception("Failed to load script, " + std::string(err.what()));
//}
//module::request m_request(request);
//module::response m_response(response);
//(*lua->state)["response"] = &m_response;
//(*lua->state)["request"] = &m_request;
//lbResult();
sol::load_result script = lua->state->load_file(filepath);
sol::load_result script = lua->state->load_file(app()->config->website.dir + filepath);
if (!script.valid()) {
sol::error err = script;
throw ylib::exception(err.what());
}
module::request m_request(request);
module::response m_response(response);
(*lua->state)["response"] = &m_response;
(*lua->state)["request"] = &m_request;
(*lua->state)["response"] = m_response;
(*lua->state)["request"] = m_request;
sol::protected_function_result result = script();
if (!result.valid()) {
@@ -116,12 +67,72 @@ void fastweb::subscribe_manager::exec(const std::string& filepath, network::http
{
exception_string = e.what();
if (app()->config->website.debug)
LOG_ERROR("[subscribe_service][" + request->filepath() + "]: " + e.what());
LOG_ERROR("[subscribe][" + request->filepath() + "]: " + e.what());
}
// 清理
lua->state->collect_garbage();
app()->state->push(lua);
if (exception_string.empty() == false)
throw ylib::exception(exception_string);
return ok_continue;
}
void fastweb::subscribe_manager::other(network::http::request* request, network::http::response* response)
{
std::string filepath = request->filepath();
if (filepath.empty())
filepath = "/";
// 搜寻默认页面
if (filepath[filepath.length()-1] == '/')
{
std::string default_filepath;
for (size_t i = 0; i < app()->config->website.default_index.size(); i++)
{
default_filepath = app()->config->website.dir + filepath + app()->config->website.default_index[i];
if (ylib::file::exist(default_filepath))
{
filepath += app()->config->website.default_index[i];
break;
}
}
}
std::string ext = ylib::file::ext(filepath);
// 判断LUA
if (ext == "lua")
{
if (app()->config->website.direct_url_mapping)
{
callback(request,response,filepath,filepath);
}
else
{
send_404(response);
}
return;
}
// 发送静态文件
std::string absolute_path = app()->config->website.dir + filepath;
if (ylib::file::exist(absolute_path))
response->send_file(absolute_path);
else
send_404(response);
}
void fastweb::subscribe_manager::send_404(network::http::response* response)
{
std::string default_404 = app()->config->website.dir + "\\" + app()->config->website.default_404;
if (app()->config->website.default_404 == "" || ylib::file::exist(default_404) == false)
{
response->send((std::string)"404 Not Found", 404, "Not Found");
}
else
{
response->send_file(default_404, -1, 404, "Not Found");
}
}

View File

@@ -1,41 +1,48 @@
#pragma once
#include "sol/sol.hpp"
#include "core/structs.h"
#include "core/define.h"
#include "net/http_reqpack.h"
#include "net/http_request.h"
#include "net/http_response.h"
#include "net/http_router.h"
#include "util/map.hpp"
namespace fastweb
{
/// <summary>
/// 订阅管理器
/// </summary>
class subscribe_manager:public Interface {
class subscribe_manager :public Interface {
public:
subscribe_manager(fastweb::app* ptr);
subscribe_manager(fastweb::app* app);
~subscribe_manager();
void load(network::http::router* router);
void start();
bool add(const std::string& pattern, const std::string& filepath);
bool remove(const std::string& pattern);
bool exist(const std::string& pattern);
void clear();
private:
/// <summary>
/// 服务回调
/// </summary>
/// <param name="request"></param>
/// <param name="response"></param>
/// <param name="pattern"></param>
/// <param name="filepath"></param>
bool callback(network::http::request* request, network::http::response* response, const std::string& pattern, const std::string& filepath);
/// <summary>
/// 其它
/// </summary>
/// <param name="request"></param>
/// <param name="response"></param>
/// <param name="extra"></param>
void other(network::http::request* request, network::http::response* response);
/// <summary>
/// 执行lua
/// </summary>
/// <param name="filepath"></param>
/// <param name="request"></param>
/// <param name="response"></param>
void exec(const std::string& filepath, network::http::request* request, network::http::response* response);
private:
network::http::router* m_router = nullptr;
std::vector<std::string*> m_subextra;
/// <summary>
/// 未找到页面
/// </summary>
/// <param name="response"></param>
void send_404(network::http::response* response);
};
}

View File

@@ -9,22 +9,22 @@ module::interceptor::~interceptor()
{
}
bool module::interceptor::add(const std::string& express_string, const std::string& filepath, sol::this_state ts)
bool module::interceptor::add(const std::string& pattern, const std::string& filepath, sol::this_state ts)
{
GET_APP;
return app->interceptor->add(express_string,app->config->website.dir+ filepath);
return app->interceptor->add(pattern,filepath);
}
bool module::interceptor::remove(const std::string& express_string, sol::this_state ts)
bool module::interceptor::remove(const std::string& pattern, sol::this_state ts)
{
GET_APP;
return app->interceptor->remove(express_string);
return app->interceptor->remove(pattern);
}
bool module::interceptor::exist(const std::string& express_string, sol::this_state ts)
bool module::interceptor::exist(const std::string& pattern, sol::this_state ts)
{
GET_APP;
return app->interceptor->exist(express_string);
return app->interceptor->exist(pattern);
}
void module::interceptor::clear(sol::this_state ts)

View File

@@ -13,21 +13,21 @@ namespace module
/// <summary>
/// 添加
/// </summary>
/// <param name="express_string"></param>
/// <param name="pattern"></param>
/// <param name="filepath"></param>
/// <returns></returns>
static bool add(const std::string& express_string,const std::string& filepath, sol::this_state ts);
static bool add(const std::string& pattern,const std::string& filepath, sol::this_state ts);
/// <summary>
/// 移除
/// </summary>
/// <param name="express_string"></param>
static bool remove(const std::string& express_string, sol::this_state ts);
/// <param name="pattern"></param>
static bool remove(const std::string& pattern, sol::this_state ts);
/// <summary>
/// 是否存在
/// </summary>
/// <param name="express_string"></param>
/// <param name="pattern"></param>
/// <returns></returns>
static bool exist(const std::string& express_string, sol::this_state ts);
static bool exist(const std::string& pattern, sol::this_state ts);
/// <summary>
/// 清空
/// </summary>

View File

@@ -0,0 +1,44 @@
#include "subscribe.h"
#include "core/app.h"
module::subscribe::subscribe()
{
}
module::subscribe::~subscribe()
{
}
bool module::subscribe::add(const std::string& express_string, const std::string& filepath, sol::this_state ts)
{
GET_APP;
return app->subscribe->add(express_string,filepath);
}
bool module::subscribe::remove(const std::string& express_string, sol::this_state ts)
{
GET_APP;
return app->subscribe->remove(express_string);
}
bool module::subscribe::exist(const std::string& express_string, sol::this_state ts)
{
GET_APP;
return app->subscribe->exist(express_string);
}
void module::subscribe::clear(sol::this_state ts)
{
GET_APP;
return app->subscribe->clear();
}
void module::subscribe::regist(sol::state* lua)
{
lua->new_usertype<module::subscribe>("subscribe",
"add", &module::subscribe::add,
"remove", &module::subscribe::remove,
"exist", &module::subscribe::exist,
"clear", &module::subscribe::clear
);
}

View File

@@ -0,0 +1,39 @@
#pragma once
#include "net/http_request.h"
#include "net/http_response.h"
#include "sol/sol.hpp"
namespace module
{
class subscribe
{
public:
subscribe();
~subscribe();
/// <summary>
/// 添加
/// </summary>
/// <param name="pattern"></param>
/// <param name="filepath"></param>
/// <returns></returns>
static bool add(const std::string& pattern,const std::string& filepath, sol::this_state ts);
/// <summary>
/// 移除
/// </summary>
/// <param name="pattern"></param>
static bool remove(const std::string& pattern, sol::this_state ts);
/// <summary>
/// 是否存在
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
static bool exist(const std::string& pattern, sol::this_state ts);
/// <summary>
/// 清空
/// </summary>
static void clear(sol::this_state ts);
static void regist(sol::state* lua);
};
}

View File

@@ -1,9 +1,6 @@
print("init fast web success!")
-- 自定义模块演示
local hello = hello.new()
print("Custom Module: "..hello:name())
-- 增加拦截器
interceptor.add("/api/*.*","/api/lib/interceptor.lua")
return true