diff --git a/config.ini b/config.ini index f54ee2b..649bf23 100644 --- a/config.ini +++ b/config.ini @@ -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 diff --git a/src/core/app.cpp b/src/core/app.cpp index 8248eed..02c9acf 100644 --- a/src/core/app.cpp +++ b/src/core/app.cpp @@ -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(); } diff --git a/src/core/config.cpp b/src/core/config.cpp index bfc4efb..a826ecc 100644 --- a/src/core/config.cpp +++ b/src/core/config.cpp @@ -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>(); + 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"); diff --git a/src/core/config.h b/src/core/config.h index c5f404d..e3478eb 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -31,6 +31,7 @@ namespace fastweb std::string Initialization_script; bool debug = false; std::vector domain; + bool direct_url_mapping = false; }; struct log { diff --git a/src/core/interceptormanager.cpp b/src/core/interceptormanager.cpp index c5d25b9..6c3917f 100644 --- a/src/core/interceptormanager.cpp +++ b/src/core/interceptormanager.cpp @@ -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()); diff --git a/src/core/interceptormanager.h b/src/core/interceptormanager.h index e89cfa3..97115db 100644 --- a/src/core/interceptormanager.h +++ b/src/core/interceptormanager.h @@ -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: /// /// 服务回调 /// /// - /// - bool callback(network::http::reqpack* reqpack, const std::string& express_string); - private: - ylib::map interceptor; + /// + /// + bool callback(network::http::reqpack* reqpack, const std::string& pattern,const std::string& filepath); }; } diff --git a/src/core/log.cpp b/src/core/log.cpp index 5ab92cd..ebab0f0 100644 --- a/src/core/log.cpp +++ b/src/core/log.cpp @@ -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) { diff --git a/src/core/log.h b/src/core/log.h index 8445879..6f09736 100644 --- a/src/core/log.h +++ b/src/core/log.h @@ -2,9 +2,11 @@ #include #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 m_queue; }; } diff --git a/src/core/modulemanager.cpp b/src/core/modulemanager.cpp index 8e23dcb..9f7faa0 100644 --- a/src/core/modulemanager.cpp +++ b/src/core/modulemanager.cpp @@ -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); diff --git a/src/core/subscribemanager.cpp b/src/core/subscribemanager.cpp index bfe1c90..eb0170b 100644 --- a/src/core/subscribemanager.cpp +++ b/src/core/subscribemanager.cpp @@ -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"); + } } diff --git a/src/core/subscribemanager.h b/src/core/subscribemanager.h index cc15596..3a34876 100644 --- a/src/core/subscribemanager.h +++ b/src/core/subscribemanager.h @@ -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 { /// /// 订阅管理器 /// - 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: + /// + /// 服务回调 + /// + /// + /// + /// + /// + bool callback(network::http::request* request, network::http::response* response, const std::string& pattern, const std::string& filepath); /// /// 其它 /// /// /// - /// void other(network::http::request* request, network::http::response* response); - /// - /// 执行lua - /// - /// - /// - /// - void exec(const std::string& filepath, network::http::request* request, network::http::response* response); private: - network::http::router* m_router = nullptr; - std::vector m_subextra; + /// + /// 未找到页面 + /// + /// + void send_404(network::http::response* response); }; } diff --git a/src/module/http/interceptor.cpp b/src/module/http/interceptor.cpp index 321fc23..8b0fa9c 100644 --- a/src/module/http/interceptor.cpp +++ b/src/module/http/interceptor.cpp @@ -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) diff --git a/src/module/http/interceptor.h b/src/module/http/interceptor.h index 0d2f7fc..c5f25e9 100644 --- a/src/module/http/interceptor.h +++ b/src/module/http/interceptor.h @@ -13,21 +13,21 @@ namespace module /// /// 添加 /// - /// + /// /// /// - 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); /// /// 移除 /// - /// - static bool remove(const std::string& express_string, sol::this_state ts); + /// + static bool remove(const std::string& pattern, sol::this_state ts); /// /// 是否存在 /// - /// + /// /// - static bool exist(const std::string& express_string, sol::this_state ts); + static bool exist(const std::string& pattern, sol::this_state ts); /// /// 清空 /// diff --git a/src/module/http/subscribe.cpp b/src/module/http/subscribe.cpp new file mode 100644 index 0000000..c1a11f3 --- /dev/null +++ b/src/module/http/subscribe.cpp @@ -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("subscribe", + "add", &module::subscribe::add, + "remove", &module::subscribe::remove, + "exist", &module::subscribe::exist, + "clear", &module::subscribe::clear + ); +} diff --git a/src/module/http/subscribe.h b/src/module/http/subscribe.h new file mode 100644 index 0000000..35b1893 --- /dev/null +++ b/src/module/http/subscribe.h @@ -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(); + /// + /// 添加 + /// + /// + /// + /// + static bool add(const std::string& pattern,const std::string& filepath, sol::this_state ts); + /// + /// 移除 + /// + /// + static bool remove(const std::string& pattern, sol::this_state ts); + /// + /// 是否存在 + /// + /// + /// + static bool exist(const std::string& pattern, sol::this_state ts); + /// + /// 清空 + /// + static void clear(sol::this_state ts); + + static void regist(sol::state* lua); + }; +} + diff --git a/www/api/lib/init.lua b/www/api/lib/init.lua index 6aa0a15..14d565e 100644 --- a/www/api/lib/init.lua +++ b/www/api/lib/init.lua @@ -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 \ No newline at end of file