fastweb.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. #include "fastweb.h"
  2. #include <regex>
  3. #include "net/http_website.h"
  4. #include "net/http_router.h"
  5. #include "net/http_interceptor.h"
  6. #include "net/http_reqpack.h"
  7. #include "module/http/request.h"
  8. #include "module/http/response.h"
  9. #include "module/globalfuns.h"
  10. #include "core/config.h"
  11. #include "core/statemanager.h"
  12. bool fastweb::start()
  13. {
  14. stop();
  15. // 虚拟机管理器
  16. if(sStateMgr->start() == false)
  17. {
  18. m_lastErrorDesc = sStateMgr->last_error();
  19. return false;
  20. }
  21. m_center = new network::http::center();
  22. network::http::start_config config;
  23. network::http::website_config ws_config;
  24. for_iter(iter, sConfig->domain)
  25. {
  26. network::http::host_config host_config;
  27. host_config.domain = iter->first;
  28. host_config.port = iter->second.port;
  29. host_config.ssl = iter->second.https;
  30. ws_config.host.push_back(host_config);
  31. }
  32. ws_config.name = "master";
  33. ws_config.router.threadpool.size = 40;
  34. ws_config.router.threadpool.queuemax = 10000;
  35. ws_config.session.dirpath = sConfig->website.session_dir;
  36. ws_config.session.timeout_sec = sConfig->website.session_timeout_sec;
  37. config.website.push_back(ws_config);
  38. for_iter(iter, sConfig->domain)
  39. {
  40. if(iter->second.https)
  41. config.cert.emplace(iter->first, iter->second.ssl);
  42. }
  43. if (!m_center->create(config))
  44. {
  45. m_lastErrorDesc = "start failed," + m_center->last_error();
  46. stop();
  47. return false;
  48. }
  49. auto website = m_center->website_byname(ws_config.name);
  50. auto router = website->router();
  51. // 初始化脚本
  52. if (initialization_script() == false)
  53. return false;
  54. // 加载服务脚本
  55. {
  56. auto luas = ylib::file::traverse(sConfig->scripts.app_dir, "(.*\\.lua)");
  57. for_iter(iter, luas) {
  58. if (iter->second == IS_DIRECTORY)
  59. continue;
  60. std::string path = strutils::replace(iter->first, '\\', '/');
  61. if (service_bytecode.create(path, sConfig->scripts.app_dir + "/" + path, true) == false)
  62. {
  63. m_lastErrorDesc = service_bytecode.last_error();
  64. return false;
  65. }
  66. }
  67. }
  68. // 加载拦截器脚本
  69. for_iter(iter, sConfig->website.interceptor_scripts) {
  70. if (interceptor_bytecode.create(iter->regex_express, iter->filepath, true) == false)
  71. {
  72. m_lastErrorDesc = interceptor_bytecode.last_error();
  73. return false;
  74. }
  75. }
  76. // 加入LUA服务映射
  77. {
  78. auto map = service_bytecode.map();
  79. for_iter(iter, map)
  80. {
  81. auto state = sStateMgr->get_state();
  82. std::string route_pattern;
  83. network::http::method method = network::http::ALL;
  84. try
  85. {
  86. auto result = state->script_file(iter->second->filepath);
  87. if (result.valid()) {
  88. auto router = (*state)["route"];
  89. auto type = router.get_type();
  90. if (router.is<sol::table>())
  91. {
  92. sol::optional<std::string> route_pattern_param = router[1];
  93. sol::optional<int> method_param = router[2];
  94. if (route_pattern_param && route_pattern_param->empty() == false)
  95. route_pattern = *route_pattern_param;
  96. if (method_param)
  97. method = (network::http::method)*method_param;
  98. }
  99. }
  100. }
  101. catch (const std::exception& e)
  102. {
  103. LOG_ERROR(e.what());
  104. }
  105. if (route_pattern.empty())
  106. route_pattern = sConfig->scripts.app_mapping_dir + iter->first;
  107. // OutPutLog
  108. {
  109. std::string log;
  110. log = "[subscribe] lua: " + iter->first + "\t pattern: " + route_pattern + "\t method: ";
  111. switch (method)
  112. {
  113. case ylib::network::http::GET:
  114. log.append("GET");
  115. break;
  116. case ylib::network::http::POST:
  117. log.append("POST");
  118. break;
  119. case ylib::network::http::PUT:
  120. log.append("PUT");
  121. break;
  122. case ylib::network::http::DEL:
  123. log.append("DEL");
  124. break;
  125. case ylib::network::http::HEAD:
  126. log.append("HEAD");
  127. break;
  128. case ylib::network::http::ALL:
  129. log.append("ALL");
  130. break;
  131. default:
  132. break;
  133. }
  134. LOG_INFO(log);
  135. }
  136. router->subscribe(route_pattern, method, &fastweb::subscribe_service,new std::string(iter->first));
  137. }
  138. }
  139. // 加入拦截器
  140. for(size_t i=0;i<sConfig->website.interceptor_scripts.size();i++)
  141. router->interceptor()->add(sConfig->website.interceptor_scripts[i].regex_express,&fastweb::subscribe_interceptor);
  142. router->other([&](network::http::request* request, network::http::response* response) {
  143. if (request->filepath() == "/")
  144. {
  145. bool find = false;
  146. for (size_t i = 0; i < sConfig->website.default_index.size(); i++)
  147. {
  148. std::string filepath = sConfig->website.static_dir + request->filepath() + sConfig->website.default_index[i];
  149. if (ylib::file::exist(filepath))
  150. {
  151. find = true;
  152. response->send_file(filepath);
  153. break;
  154. }
  155. }
  156. if (find == false)
  157. send_404(response);
  158. return;
  159. }
  160. send_file(response,request->filepath());
  161. });
  162. return m_center->start();
  163. }
  164. void fastweb::stop()
  165. {
  166. if (m_center != nullptr)
  167. {
  168. delete m_center;
  169. }
  170. m_center = nullptr;
  171. }
  172. bool fastweb::initialization_script()
  173. {
  174. auto script_filepath = sConfig->website.Initialization_script;
  175. if (script_filepath == "")
  176. return true;
  177. if (ylib::file::exist(script_filepath) == false)
  178. {
  179. m_lastErrorDesc = "Initialization script not found, filepath: " + script_filepath;
  180. return false;
  181. }
  182. auto state = sStateMgr->get_state();
  183. try
  184. {
  185. state->set_function("global_regist", module::global_regist);
  186. auto result = state->script_file(script_filepath);
  187. if (!result.valid()) {
  188. sol::error err = result;
  189. throw ylib::exception(err.what());
  190. }
  191. if (result.get<bool>() == false)
  192. {
  193. throw ylib::exception("user interrupt");
  194. }
  195. }
  196. catch (const std::exception& e)
  197. {
  198. m_lastErrorDesc = "Exception in executing initialization script: " + std::string(e.what());
  199. }
  200. // 不可DELETE,否则注册的全局变量会被自动销毁
  201. //delete state;
  202. return m_lastErrorDesc == "";
  203. }
  204. void fastweb::subscribe_service(network::http::request* request, network::http::response* response,void *extra)
  205. {
  206. std::string lua_name = *(std::string*)extra;
  207. // 文件原路径(非绝对路径)
  208. //std::string lua_name = strutils::right(request->filepath(), request->filepath().length() - sConfig->scripts.app_mapping_dir.length());
  209. auto lua = sStateMgr->get_state();
  210. std::string exception_string;
  211. try
  212. {
  213. auto bytecode = sFastWeb->service_bytecode.get(lua_name);
  214. if (bytecode.empty())
  215. throw ylib::exception("Serious error: Bytecode not found, possibly due to pre compilation modification error. Please recheck the script file, "+lua_name);
  216. auto lbResult = lua->load_buffer(bytecode.data(), bytecode.length(), "bytecode");
  217. if (lbResult.valid() == false)
  218. {
  219. sol::error err = lbResult;
  220. throw ylib::exception("Failed to load bytecode, " + std::string(err.what()));
  221. }
  222. module::request m_request(request);
  223. module::response m_response(response);
  224. lbResult();
  225. (*lua)["response"] = &m_response;
  226. (*lua)["request"] = &m_request;
  227. auto result = (*lua)["access"]();
  228. if (!result.valid()) {
  229. sol::error err = result;
  230. throw ylib::exception(err.what());
  231. }
  232. }
  233. catch (const std::exception& e)
  234. {
  235. exception_string = e.what();
  236. if(sConfig->website.debug)
  237. LOG_ERROR("[subscribe_service]["+ request->filepath() + "]: "+e.what());
  238. }
  239. lua->collect_garbage();
  240. sStateMgr->push_state(lua);
  241. if (exception_string.empty() == false)
  242. throw ylib::exception(exception_string);
  243. }
  244. bool fastweb::subscribe_interceptor(network::http::reqpack* reqpack, const std::string& express_string)
  245. {
  246. bool ok_continue = false;
  247. auto lua = sStateMgr->get_state();
  248. std::string exception_string;
  249. try
  250. {
  251. const std::string& bytecode = sFastWeb->interceptor_bytecode.get(express_string);
  252. if (bytecode.empty())
  253. throw ylib::exception("[interceptor] Serious error: Bytecode not found, possibly due to pre compilation modification error. Please recheck the script file, " + express_string);
  254. auto lbResult = lua->load_buffer(bytecode.data(), bytecode.length(), "bytecode");
  255. if (lbResult.valid() == false)
  256. {
  257. sol::error err = lbResult;
  258. throw ylib::exception("[interceptor] Failed to load bytecode, " + std::string(err.what()));
  259. }
  260. module::request m_request(reqpack->request());
  261. module::response m_response(reqpack->response());
  262. lbResult();
  263. (*lua)["response"] = m_response;
  264. (*lua)["request"] = m_request;
  265. auto result = (*lua)["access"]();
  266. if (!result.valid()) {
  267. sol::error err = result;
  268. throw ylib::exception(err.what());
  269. }
  270. ok_continue = result.get<bool>();
  271. }
  272. catch (const std::exception& e)
  273. {
  274. exception_string = e.what();
  275. if (sConfig->website.debug)
  276. LOG_ERROR("[subscribe_interceptor][" + reqpack->request()->filepath() + "]: " + e.what());
  277. }
  278. sStateMgr->push_state(lua);
  279. if (exception_string.empty() == false)
  280. throw ylib::exception(exception_string);
  281. return ok_continue;
  282. }
  283. void fastweb::send_file(network::http::response* response, std::string filepath)
  284. {
  285. filepath = sConfig->website.static_dir + filepath;
  286. if (ylib::file::exist(filepath))
  287. {
  288. response->send_file(filepath);
  289. }
  290. else
  291. {
  292. send_404(response);
  293. }
  294. }
  295. void fastweb::send_404(network::http::response* response)
  296. {
  297. std::string default_404 = sConfig->website.static_dir + "\\" + sConfig->website.default_404;
  298. if (sConfig->website.default_404 == "" || ylib::file::exist(default_404) == false)
  299. {
  300. response->send((std::string)"404 Not Found",404,"Not Found");
  301. }
  302. else
  303. {
  304. response->send_file(default_404,-1, 404, "Not Found");
  305. }
  306. }