| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- #include "fastweb.h"
- #include <regex>
- #include "net/http_website.h"
- #include "net/http_router.h"
- #include "net/http_interceptor.h"
- #include "net/http_reqpack.h"
- #include "module/http/request.h"
- #include "module/http/response.h"
- #include "module/globalfuns.h"
- #include "core/config.h"
- #include "core/statemanager.h"
- bool fastweb::start()
- {
- stop();
- // 虚拟机管理器
- if(sStateMgr->start() == false)
- {
- m_lastErrorDesc = sStateMgr->last_error();
- return false;
- }
- m_center = new network::http::center();
- network::http::start_config config;
- network::http::website_config ws_config;
-
- for_iter(iter, sConfig->domain)
- {
- network::http::host_config host_config;
- host_config.domain = iter->first;
- host_config.port = iter->second.port;
- host_config.ssl = iter->second.https;
- ws_config.host.push_back(host_config);
- }
- ws_config.name = "master";
-
- ws_config.router.threadpool.size = 40;
- ws_config.router.threadpool.queuemax = 10000;
- ws_config.session.dirpath = sConfig->website.session_dir;
- ws_config.session.timeout_sec = sConfig->website.session_timeout_sec;
- config.website.push_back(ws_config);
- for_iter(iter, sConfig->domain)
- {
- if(iter->second.https)
- config.cert.emplace(iter->first, iter->second.ssl);
- }
- if (!m_center->create(config))
- {
- m_lastErrorDesc = "start failed," + m_center->last_error();
- stop();
- return false;
- }
- auto website = m_center->website_byname(ws_config.name);
- auto router = website->router();
-
- // 初始化脚本
- if (initialization_script() == false)
- return false;
- // 加载服务脚本
- {
- auto luas = ylib::file::traverse(sConfig->scripts.app_dir, "(.*\\.lua)");
- for_iter(iter, luas) {
- if (iter->second == IS_DIRECTORY)
- continue;
- std::string path = strutils::replace(iter->first, '\\', '/');
- if (service_bytecode.create(path, sConfig->scripts.app_dir + "/" + path, true) == false)
- {
- m_lastErrorDesc = service_bytecode.last_error();
- return false;
- }
- }
- }
- // 加载拦截器脚本
- for_iter(iter, sConfig->website.interceptor_scripts) {
- if (interceptor_bytecode.create(iter->regex_express, iter->filepath, true) == false)
- {
- m_lastErrorDesc = interceptor_bytecode.last_error();
- return false;
- }
- }
- // 加入LUA服务映射
- {
- auto map = service_bytecode.map();
- for_iter(iter, map)
- {
- auto state = sStateMgr->get_state();
- std::string route_pattern;
- network::http::method method = network::http::ALL;
- try
- {
- auto result = state->script_file(iter->second->filepath);
- if (result.valid()) {
- auto router = (*state)["route"];
- auto type = router.get_type();
- if (router.is<sol::table>())
- {
- sol::optional<std::string> route_pattern_param = router[1];
- sol::optional<int> method_param = router[2];
- if (route_pattern_param && route_pattern_param->empty() == false)
- route_pattern = *route_pattern_param;
- if (method_param)
- method = (network::http::method)*method_param;
- }
- }
- }
- catch (const std::exception& e)
- {
- LOG_ERROR(e.what());
- }
- if (route_pattern.empty())
- route_pattern = sConfig->scripts.app_mapping_dir + iter->first;
- // OutPutLog
- {
- std::string log;
- log = "[subscribe] lua: " + iter->first + "\t pattern: " + route_pattern + "\t method: ";
- switch (method)
- {
- case ylib::network::http::GET:
- log.append("GET");
- break;
- case ylib::network::http::POST:
- log.append("POST");
- break;
- case ylib::network::http::PUT:
- log.append("PUT");
- break;
- case ylib::network::http::DEL:
- log.append("DEL");
- break;
- case ylib::network::http::HEAD:
- log.append("HEAD");
- break;
- case ylib::network::http::ALL:
- log.append("ALL");
- break;
- default:
- break;
- }
- LOG_INFO(log);
- }
- router->subscribe(route_pattern, method, &fastweb::subscribe_service,new std::string(iter->first));
- }
-
- }
-
- // 加入拦截器
- for(size_t i=0;i<sConfig->website.interceptor_scripts.size();i++)
- router->interceptor()->add(sConfig->website.interceptor_scripts[i].regex_express,&fastweb::subscribe_interceptor);
- router->other([&](network::http::request* request, network::http::response* response) {
- if (request->filepath() == "/")
- {
- bool find = false;
- for (size_t i = 0; i < sConfig->website.default_index.size(); i++)
- {
- std::string filepath = sConfig->website.static_dir + request->filepath() + sConfig->website.default_index[i];
- if (ylib::file::exist(filepath))
- {
- find = true;
- response->send_file(filepath);
- break;
- }
- }
- if (find == false)
- send_404(response);
- return;
- }
- send_file(response,request->filepath());
- });
- return m_center->start();
- }
- void fastweb::stop()
- {
- if (m_center != nullptr)
- {
- delete m_center;
- }
- m_center = nullptr;
- }
- bool fastweb::initialization_script()
- {
- auto script_filepath = sConfig->website.Initialization_script;
- if (script_filepath == "")
- return true;
- if (ylib::file::exist(script_filepath) == false)
- {
- m_lastErrorDesc = "Initialization script not found, filepath: " + script_filepath;
- return false;
- }
- auto state = sStateMgr->get_state();
- try
- {
- state->set_function("global_regist", module::global_regist);
- auto result = state->script_file(script_filepath);
- if (!result.valid()) {
- sol::error err = result;
- throw ylib::exception(err.what());
- }
- if (result.get<bool>() == false)
- {
- throw ylib::exception("user interrupt");
- }
- }
- catch (const std::exception& e)
- {
- m_lastErrorDesc = "Exception in executing initialization script: " + std::string(e.what());
- }
- // 不可DELETE,否则注册的全局变量会被自动销毁
- //delete state;
- return m_lastErrorDesc == "";
- }
- void fastweb::subscribe_service(network::http::request* request, network::http::response* response,void *extra)
- {
- std::string lua_name = *(std::string*)extra;
- // 文件原路径(非绝对路径)
- //std::string lua_name = strutils::right(request->filepath(), request->filepath().length() - sConfig->scripts.app_mapping_dir.length());
- auto lua = sStateMgr->get_state();
- std::string exception_string;
- try
- {
- auto bytecode = sFastWeb->service_bytecode.get(lua_name);
- if (bytecode.empty())
- throw ylib::exception("Serious error: Bytecode not found, possibly due to pre compilation modification error. Please recheck the script file, "+lua_name);
- auto lbResult = lua->load_buffer(bytecode.data(), bytecode.length(), "bytecode");
- if (lbResult.valid() == false)
- {
- sol::error err = lbResult;
- throw ylib::exception("Failed to load bytecode, " + std::string(err.what()));
- }
- module::request m_request(request);
- module::response m_response(response);
-
- lbResult();
- (*lua)["response"] = &m_response;
- (*lua)["request"] = &m_request;
- auto result = (*lua)["access"]();
- if (!result.valid()) {
- sol::error err = result;
- throw ylib::exception(err.what());
- }
- }
- catch (const std::exception& e)
- {
- exception_string = e.what();
- if(sConfig->website.debug)
- LOG_ERROR("[subscribe_service]["+ request->filepath() + "]: "+e.what());
- }
- lua->collect_garbage();
- sStateMgr->push_state(lua);
- if (exception_string.empty() == false)
- throw ylib::exception(exception_string);
- }
- bool fastweb::subscribe_interceptor(network::http::reqpack* reqpack, const std::string& express_string)
- {
-
- bool ok_continue = false;
- auto lua = sStateMgr->get_state();
- std::string exception_string;
- try
- {
- const std::string& bytecode = sFastWeb->interceptor_bytecode.get(express_string);
- if (bytecode.empty())
- throw ylib::exception("[interceptor] Serious error: Bytecode not found, possibly due to pre compilation modification error. Please recheck the script file, " + express_string);
- auto lbResult = lua->load_buffer(bytecode.data(), bytecode.length(), "bytecode");
- if (lbResult.valid() == false)
- {
- sol::error err = lbResult;
- throw ylib::exception("[interceptor] Failed to load bytecode, " + std::string(err.what()));
- }
- module::request m_request(reqpack->request());
- module::response m_response(reqpack->response());
- lbResult();
- (*lua)["response"] = m_response;
- (*lua)["request"] = m_request;
- auto result = (*lua)["access"]();
- if (!result.valid()) {
- sol::error err = result;
- throw ylib::exception(err.what());
- }
- ok_continue = result.get<bool>();
- }
- catch (const std::exception& e)
- {
- exception_string = e.what();
- if (sConfig->website.debug)
- LOG_ERROR("[subscribe_interceptor][" + reqpack->request()->filepath() + "]: " + e.what());
- }
- sStateMgr->push_state(lua);
- if (exception_string.empty() == false)
- throw ylib::exception(exception_string);
- return ok_continue;
- }
- void fastweb::send_file(network::http::response* response, std::string filepath)
- {
- filepath = sConfig->website.static_dir + filepath;
- if (ylib::file::exist(filepath))
- {
- response->send_file(filepath);
- }
- else
- {
- send_404(response);
- }
- }
- void fastweb::send_404(network::http::response* response)
- {
- std::string default_404 = sConfig->website.static_dir + "\\" + sConfig->website.default_404;
- if (sConfig->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");
- }
- }
|