123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778 |
- /**
- *
- * @file config.hpp
- * @author zxw
- * Copyright 2024, yjrobotics. All rights reserved.
- *
- * robotics
- *
- */
- #pragma once
- //asio2
- #include <asio2/asio2.hpp>
- //robotics
- #include "utils.hpp"
- #include "json.hpp"
- #include "CImg.h"
- namespace robotics {
- namespace v3 {
- namespace mvc {
- class web_reflect {
- public:
- /**
- * @brief
- * @param obj
- */
- static std::map<std::string, std::string> get_object_value(rttr::instance obj) {
- std::map<std::string, std::string> result;
- auto propertys = obj.get_type().get_properties();
- for (auto& property : propertys) {
- std::string propName(property.get_name());
- rttr::variant propValue = property.get_value(obj);
- rttr::type propType = property.get_type();
- if (propType == rttr::type::get<int>()) {
- result[propName] = std::to_string(propValue.get_value<int>());
- }
- else if (propType == rttr::type::get<std::int64_t>()) {
- result[propName] = std::to_string(propValue.get_value<std::int64_t>());
- }
- else if (propType == rttr::type::get<float>()) {
- result[propName] = v3::utils::format("{:.2f}", propValue.get_value<float>());
- }
- else if (propType == rttr::type::get<double>()) {
- result[propName] = v3::utils::format("{:.2f}", propValue.get_value<double>());
- }
- else if (propType == rttr::type::get<long>()) {
- result[propName] = std::to_string(propValue.get_value<long>());
- }
- else if (propType == rttr::type::get<bool>()) {
- result[propName] = propValue.get_value<bool>() ? "true" : "false";
- }
- else if (propType == rttr::type::get<std::string>()) {
- result[propName] = propValue.get_value<std::string>();
- }
- else if (propType == rttr::type::get<v3::datetime>()) {
- result[propName] = propValue.get_value<v3::datetime>().to_string();
- }
- else if (propType == rttr::type::get<std::vector<int>>()) {
- auto vecValue = propValue.get_value<std::vector<int>>();
- result[propName] = v3::utils::join(vecValue, ",");
- }
- else if (propType == rttr::type::get<std::vector<std::int64_t>>()) {
- auto vecValue = propValue.get_value<std::vector<std::int64_t>>();
- result[propName] = v3::utils::join(vecValue, ",");
- }
- else if (propType == rttr::type::get<std::vector<float>>()) {
- auto vecValue = propValue.get_value<std::vector<float>>();
- result[propName] = v3::utils::join(vecValue, ",");
- }
- else if (propType == rttr::type::get<std::vector<double>>()) {
- auto vecValue = propValue.get_value<std::vector<double>>();
- result[propName] = v3::utils::join(vecValue, ",");
- }
- else if (propType == rttr::type::get<std::vector<long>>()) {
- auto vecValue = propValue.get_value<std::vector<long>>();
- result[propName] = v3::utils::join(vecValue, ",");
- }
- else if (propType == rttr::type::get<std::vector<bool>>()) {
- auto vecValue = propValue.get_value<std::vector<bool>>();
- result[propName] = v3::utils::join(vecValue, ",");
- }
- else if (propType == rttr::type::get<std::vector<std::string>>()) {
- auto vecValue = propValue.get_value<std::vector<std::string>>();
- result[propName] = v3::utils::join(vecValue, ",");
- }
- else if (propType == rttr::type::get<std::vector<v3::datetime>>()) {
- auto vecValue = propValue.get_value<std::vector<v3::datetime>>();
- result[propName] = v3::utils::join(vecValue, ",");
- }
- }
- return result;
- }
- /**
- * @brief
- * @param obj
- * @param values
- */
- static void set_object_value(rttr::instance obj, std::map<std::string, std::string>const& values) {
- rttr::instance obj1 = obj.get_type().get_raw_type().is_wrapper() ? obj.get_wrapped_instance() : obj;
- const auto propertys = obj1.get_derived_type().get_properties();
- for (auto& property : propertys) {
- auto name = std::string(property.get_name());
- auto type = property.get_type();
- if (!values.contains(name))
- continue;
- std::string value = values.find(name)->second;
- if (type == rttr::type::get<int>()) {
- property.set_value(obj1, atoi(value.c_str()));
- }
- else if (type == rttr::type::get<std::int64_t>()) {
- property.set_value(obj, std::int64_t(std::atoll(value.c_str())));
- }
- else if (type == rttr::type::get<float>()) {
- property.set_value(obj, float(std::atof(value.c_str())));
- }
- else if (type == rttr::type::get<double>()) {
- property.set_value(obj, double(std::atof(value.c_str())));
- }
- else if (type == rttr::type::get<long>()) {
- property.set_value(obj, long(std::atol(value.c_str())));
- }
- else if (type == rttr::type::get<bool>()) {
- if (value == "1" || value == "true" || value == "TRUE" || value == "True") {
- property.set_value(obj, true);
- }
- else {
- property.set_value(obj, false);
- }
- }
- else if (type == rttr::type::get<std::string>()) {
- property.set_value(obj, value);
- }
- else if (type == rttr::type::get<v3::datetime>()) {
- property.set_value(obj, v3::datetime(value));
- }
- else if (type == rttr::type::get<std::vector<int>>()) {
- std::vector<std::string> vec = v3::utils::split(value, ",");
- std::vector<int> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(std::atoi(vecIt.c_str()));
- }
- property.set_value(obj, vecValue);
- }
- else if (type == rttr::type::get<std::vector<std::int64_t>>()) {
- std::vector<std::string> vec = v3::utils::split(value, ",");
- std::vector<std::int64_t> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(std::atoll(vecIt.c_str()));
- }
- property.set_value(obj, vecValue);
- }
- else if (type == rttr::type::get<std::vector<float>>()) {
- std::vector<std::string> vec = v3::utils::split(value, ",");
- std::vector<float> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(std::atof(vecIt.c_str()));
- }
- property.set_value(obj, vecValue);
- }
- else if (type == rttr::type::get<std::vector<double>>()) {
- std::vector<std::string> vec = v3::utils::split(value, ",");
- std::vector<double> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(std::atof(vecIt.c_str()));
- }
- property.set_value(obj, vecValue);
- }
- else if (type == rttr::type::get<std::vector<long>>()) {
- std::vector<std::string> vec = v3::utils::split(value, ",");
- std::vector<long> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(std::atol(vecIt.c_str()));
- }
- property.set_value(obj, vecValue);
- }
- else if (type == rttr::type::get<std::vector<bool>>()) {
- std::vector<std::string> vec = v3::utils::split(value, ",");
- std::vector<bool> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(vecIt == "1" || vecIt == "true" || vecIt == "TRUE" || vecIt == "True");
- }
- property.set_value(obj, vecValue);
- }
- else if (type == rttr::type::get<std::vector<std::string>>()) {
- std::vector<std::string> vecValue = v3::utils::split(value, ",");
- property.set_value(obj, vecValue);
- }
- else if (type == rttr::type::get<std::vector<v3::datetime>>()) {
- std::vector<std::string> vec = v3::utils::split(value, ",");
- std::vector<v3::datetime> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(v3::datetime(vecIt));
- }
- property.set_value(obj, vecValue);
- }
- }
- }
- };
- class cookie_id {
- public:
- static std::string get_id() {
- static std::string g_cookie_id;
- if (g_cookie_id.empty()) {
- g_cookie_id = v3::utils::uuid();
- }
- return g_cookie_id;
- }
- };
- class cookie {
- public:
- cookie() {
- //name = "SessionId";
- name = cookie_id::get_id();
- value = v3::utils::base64_encode(v3::utils::uuid());
- path = "path=/";
- time = 30 * 60 * 1000;
- last_expire_time = v3::datetime::current_time_stamp() + time;
- }
- /**
- * @brief cookie名称
- */
- std::string name;
- /**
- * @brief cookie值
- */
- std::string value;
- /**
- * @brief cookie路径
- */
- std::string path;
- /**
- * @brief cookie时间
- */
- time_t time = 0;
- /**
- * @brief 上次刷新时间
- */
- time_t last_expire_time = 0;
- /**
- * @brief 对比
- * @param cookie
- * @param remove
- * @return
- */
- bool compare(std::shared_ptr<cookie> cookie, bool& remove) {
- bool result = false;
- remove = false;
- if (cookie) {
- result = (name == cookie->name && value == cookie->value);
- if (result) {
- time_t current_time = v3::datetime::current_time_stamp();
- if (last_expire_time < current_time) {
- remove = true;
- result = false;
- }
- else {
- last_expire_time = v3::datetime::current_time_stamp() + time;
- }
- }
- }
- return result;
- }
- };
- class cookies {
- public:
- /**
- * @brief 解析
- * @param cookie_str
- * @return
- */
- static std::shared_ptr<cookies> analysis(std::string const& cookie_str) {
- std::shared_ptr<cookies> result;
- std::vector<std::string> cookies_tmp = v3::utils::split(cookie_str, ";");
- for (auto& item : cookies_tmp) {
- int index = item.find('=');
- if (index == std::string::npos)
- continue;
- std::shared_ptr<cookie> add(new cookie);
- add->name = item.substr(0, index);
- add->value = item.substr(index + 1);
- add->name = v3::utils::trim(add->name);
- add->value = v3::utils::trim(add->value);
- if (add->name != "path") {
- if (!result) {
- result.reset(new cookies);
- }
- result->cookies_.push_back(add);
- }
- }
- return result;
- }
- /**
- * @brief 对比
- * @param value
- * @return
- */
- bool compare(std::shared_ptr<cookies> value) {
- bool result = false;
- if (!value)
- return result;
- for (auto& value_elem : value->cookies_) {
- for (int i = 0; i < cookies_.size(); ++i) {
- bool is_remove = false;
- bool exist = cookies_[i]->compare(value_elem, is_remove);
- if (is_remove) {
- cookies_.erase(cookies_.begin() + i);
- --i;
- continue;
- }
- if (exist) {
- result = true;
- }
- }
- }
- return result;
- }
- /**
- * @brief 数量
- * @return
- */
- int count() {
- return int(cookies_.size());
- }
- /**
- * @brief 添加
- * @param cookie
- */
- void add(std::shared_ptr<cookie> cookie) {
- cookies_.push_back(cookie);
- }
- private:
- std::vector<std::shared_ptr<cookie>> cookies_;
- };
- struct session {
- /**
- * @brief 关闭
- */
- bool close = false;
- /**
- * @brief
- */
- bool authen = false;
- /**
- * @brief
- */
- std::shared_ptr<cookies> cookies_;
- /**
- * @brief
- */
- std::map<std::string, std::any> user_data;
- };
- class sessions {
- public:
- /**
- * @brief
- */
- static void add_session(std::shared_ptr<session> session) {
- std::lock_guard<std::mutex> locker(mutex_());
- sessions_().push_back(session);
- }
- /**
- * @brief
- */
- static std::shared_ptr<session> get_session(std::string const& cookie_str) {
- std::shared_ptr<session> result;
- std::shared_ptr<cookies> cookies = cookies::analysis(cookie_str);
- {
- std::lock_guard<std::mutex> locker(mutex_());
- for (int i = 0; i < sessions_().size(); ++i) {
- if (sessions_()[i]->cookies_->compare(cookies) && !sessions_()[i]->close) {
- result = sessions_()[i];
- }
- else if (sessions_()[i]->cookies_->count() <= 0 || sessions_()[i]->close) {
- sessions_().erase(sessions_().begin() + i);
- i--;
- }
- }
- }
- return result;
- }
- private:
- static std::vector<std::shared_ptr<session>>& sessions_() {
- static std::vector<std::shared_ptr<session>> g_sessions;
- return g_sessions;
- }
- static std::mutex& mutex_() {
- static std::mutex g_mutex;
- return g_mutex;
- }
- };
- enum class captcha_type {
- /**
- * @brief 成功
- */
- success,
- /**
- * @brief 失败
- */
- fail,
- /**
- * @brief 没有验证码
- */
- no
- };
- struct controller_action;
- class http_context {
- public:
- class curr {
- public:
- /**
- * @brief 当前context
- * @return
- */
- static std::shared_ptr<http_context> current() {
- return http_context::current();
- }
- /**
- * @brief 是否有权限
- * @return
- */
- static bool authen() {
- return current()->authen();
- }
- /**
- * @brief 设置权限
- * @param value
- */
- static void set_authen(bool value = true) {
- current()->set_authen(value);
- }
- /**
- * @brief 设置session
- * @param key
- * @param value
- */
- static void add_session(std::string const& key, std::any const& value) {
- current()->add_session(key, value);
- }
- /**
- * @brief 添加session并设置权限
- * @param key
- * @param value
- */
- static void add_authen_session(std::string const& key, std::any const& value) {
- add_session(key, value);
- set_authen();
- }
- /**
- * @brief 获取session
- * @param key
- * @return
- */
- static std::any& session(std::string const& key) {
- return current()->session(key);
- }
- /**
- * @brief 获取session
- * @tparam _Ret
- * @param key
- * @param succ
- * @return
- */
- template<typename _Ret>
- static bool get_session(std::string const& key, _Ret& result) {
- std::any any_value = current()->session(key);
- if (any_value.type() != typeid(_Ret)) {
- return false;
- }
- result = std::any_cast<_Ret>(any_value);
- return true;
- }
- /**
- * @brief 添加cookie
- * @param timeout
- */
- static void add_cookie(int timeout = 30) {
- current()->add_cookie(timeout);
- }
- /**
- * @brief 删除cookie
- */
- static void remove_cookie() {
- current()->remove_cookie();
- }
- /**
- * @brief 重置cookie
- * @param timeout
- */
- static void reset_cookie(int timeout = 30) {
- remove_cookie();
- add_cookie(timeout);
- }
- /**
- * @brief 验证码比较
- * @param key
- * @param captcha_code
- * @return
- */
- static captcha_type captcha_compare(std::string const& key, std::string const& captcha_code) {
- std::string value;
- if (!get_session<std::string>(key, value))
- return mvc::captcha_type::no;
- else if (v3::utils::case_insensitive_compare(value, captcha_code))
- return mvc::captcha_type::success;
- else
- return mvc::captcha_type::fail;
- }
- /**
- * @brief 验证码比较
- * @param key
- * @param captcha_code
- * @param success
- * @param message
- * @return
- */
- static bool captcha_compare(std::string const& key, std::string const& captcha_code, bool& success, std::string& message) {
- auto result = captcha_compare(key, captcha_code);
- if (mvc::captcha_type::no == result) {
- success = false;
- message = "验证码不存在!";
- return false;
- }
- else if (mvc::captcha_type::fail == result) {
- success = false;
- message = "验证码错误!";
- return false;
- }
- else {
- success = true;
- message = "成功!";
- return true;
- }
- }
- };
- /**
- * @brief
- */
- static void new_curr_http_context(http::web_request& req, http::web_response& rep) {
- rep.clear();
- new http_context(req, rep);
- }
- /**
- * @brief
- */
- static void remove_curr_http_context() {
- std::lock_guard<std::mutex> locker(mutex_());
- http_context_list_().erase(std::this_thread::get_id());
- }
- /**
- * @brief
- * @param route
- * @return
- */
- static std::shared_ptr<http_context> current() {
- std::lock_guard<std::mutex> locker(mutex_());
- return http_context_list_()[std::this_thread::get_id()];
- }
- /**
- * @brief
- */
- bool authen() {
- if (current_session_)
- return current_session_->authen;
- return false;
- }
- /**
- * @brief
- */
- void set_authen(bool value = true) {
- if (current_session_)
- current_session_->authen = value;
- }
- /**
- * @brief
- */
- void add_session(std::string const& key, std::any const& value) {
- if (!current_session_)
- throw std::runtime_error("not cookie!");
- current_session_->user_data[key] = value;
- }
- /**
- * @brief
- */
- std::any& session(std::string const& key) {
- static std::any g_any;
- if (current_session_) {
- if (current_session_->user_data.find(key) != current_session_->user_data.end()) {
- return current_session_->user_data[key];
- }
- }
- g_any = std::any();
- return g_any;
- }
- /**
- * @brief
- */
- void add_cookie(int timeout = 30) {
- std::shared_ptr<cookie> item(new cookie);
- item->time = timeout * (1000 * 60);
- item->last_expire_time = v3::datetime::current_time_stamp() + item->time;
- if (current_session_ && !current_session_->close) {
- if (!current_session_->cookies_)
- current_session_->cookies_.reset(new cookies);
- current_session_->cookies_->add(item);
- }
- else {
- current_session_.reset(new mvc::session);
- current_session_->cookies_.reset(new cookies);
- current_session_->cookies_->add(item);
- mvc::sessions::add_session(current_session_);
- }
- std::string set_cookie_str;
- set_cookie_str += item->name;
- set_cookie_str += "=";
- set_cookie_str += item->value;
- set_cookie_str += ";";
- set_cookie_str += item->path;
- response.set(http::field::set_cookie, set_cookie_str);
- }
- /**
- * @brief
- */
- void remove_cookie() {
- if (current_session_) {
- current_session_->close = true;
- }
- response.set(http::field::set_cookie, "SessionId=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT");
- }
- /**
- * @brief
- */
- void set_controller_action(std::shared_ptr<controller_action> value) {
- controller_action_ = value;
- }
- /**
- * @brief
- */
- std::shared_ptr<controller_action> get_controller_action() {
- return controller_action_;
- }
- /**
- * @brief
- */
- http::web_request& request;
- /**
- * @brief
- */
- http::web_response& response;
- /**
- * @brief
- */
- std::filesystem::path root_directory;
- private:
- http_context(http::web_request& req, http::web_response& rep) :
- request(req),
- response(rep),
- root_directory(rep.get_root_directory()) {
- if (req.find(http::field::cookie) != req.end()) {
- current_session_ = sessions::get_session(std::string(req.find(http::field::cookie)->value().begin(), req.find(http::field::cookie)->value().end()));
- }
- std::lock_guard<std::mutex> locker(mutex_());
- http_context_list_()[std::this_thread::get_id()].reset(this);
- }
- private:
- std::shared_ptr<mvc::session> current_session_;
- std::shared_ptr<controller_action> controller_action_;
- private:
- static std::mutex& mutex_() {
- static std::mutex g_mutex;
- return g_mutex;
- }
- static std::map<std::thread::id, std::shared_ptr<http_context>>& http_context_list_() {
- static std::map<std::thread::id, std::shared_ptr<http_context>> g_http_context_list;
- return g_http_context_list;
- }
- };
- class http_context_gc {
- public:
- http_context_gc(http::web_request& req, http::web_response& rep) {
- http_context::new_curr_http_context(req, rep);
- }
- virtual ~http_context_gc() {
- http_context::remove_curr_http_context();
- }
- };
- enum class pseudo_type {
- NON = 0,
- MASK,
- MODEL,
- FOR,
- IF,
- SWITCH,
- FILE
- };
- struct class_value {
- bool is_list = false;
- std::string class_name;
- std::vector<std::map<std::string, std::string>> class_value;
- };
- struct ipseudo_label {
- ipseudo_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
- type(value_type.first),
- label(value_type.second) {
- }
- /**
- * @brief 类型
- */
- pseudo_type type;
- /**
- * @brief 原始代码
- */
- std::string html_code;
- /**
- * @brief 临时原始代码
- */
- std::string html_code_tmp;
- /**
- * @brief 类名
- */
- std::string class_name;
- /**
- * @brief 标签
- */
- std::pair<std::string, std::string> label;
- /**
- * @brief 实体类数据列表
- */
- std::vector<std::map<std::string, std::string>> class_value_list;
- /**
- * @brief 子标签
- */
- std::vector<std::shared_ptr<ipseudo_label>> childs;
- /**
- * @brief 解析返回html
- */
- virtual std::string analysis() = 0;
- /**
- * @brief 设置属性值
- */
- void set_class_value(std::vector<std::shared_ptr<class_value>>const& value) {
- for (auto it : childs) {
- it->set_class_value(value);
- }
- for (auto it : value) {
- if (class_name != it->class_name)
- continue;
- if (it->is_list && type == pseudo_type::FOR) {
- class_value_list = it->class_value;
- break;
- }
- else if (!it->is_list) {
- class_value_list = it->class_value;
- break;
- }
- }
- }
- /**
- * @brief 解析基础信息
- */
- virtual void analysis_baseinfo() = 0;
- protected:
- std::string extract(std::string const& value, std::pair<std::string, std::string> const& pair, int& index) {
- std::string result;
- bool ok = false;
- int count = 0;
- for (size_t i = 0; i < value.size(); ++i) {
- if (i + 1 >= pair.first.size() &&
- value[i] == pair.first[pair.first.size() - 1] &&
- value.substr(i - pair.first.size() + 1, pair.first.size()) == pair.first) {
- count++;
- if (count == 1) {
- ok = true;
- continue;
- }
- }
- if (ok &&
- value.size() >= i + pair.second.size() &&
- value[i] == pair.second[0] &&
- value.substr(i, pair.second.size()) == pair.second) {
- count--;
- if (count == 0) {
- index = i + 1;
- return result;
- }
- }
- if (ok) {
- result += value[i];
- }
- }
- index = -1;
- return result;
- }
- std::vector<std::string> extractList(std::string const& value, std::pair<std::string, std::string> const& pair) {
- std::vector<std::string> result;
- int index = 0;
- int pos = 0;
- while (index > -1) {
- pos += index;
- std::string ret = extract(value.substr(pos, value.size() - pos), pair, index);
- if (index != -1)
- result.push_back(ret);
- }
- return result;
- }
- };
- struct pseudo_mask_label : public ipseudo_label {
- pseudo_mask_label(std::pair<pseudo_type, std::pair<std::string, std::string>>const& value_type) :
- ipseudo_label(value_type) {
- }
- std::string mask_name;
- virtual std::string analysis()override {
- for (auto child : childs) {
- std::string childValue = child->analysis();
- html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
- }
- int index = 0;
- std::string header = extract(html_code_tmp, { "${mask","}" }, index);
- header = "${mask" + header + "}";
- std::string tmp = extract(html_code_tmp, { header,"{/mask}" }, index);
- return tmp;
- }
- virtual void analysis_baseinfo() override {
- html_code_tmp = html_code;
- for (auto child : childs) {
- child->analysis_baseinfo();
- }
- //获取mask名称
- int index = 0;
- mask_name = extract(html_code, { "name='","'" }, index);
- }
- };
- struct pseudo_model_label : public ipseudo_label {
- pseudo_model_label(std::pair<pseudo_type, std::pair<std::string, std::string>>const& value_type) :
- ipseudo_label(value_type) {
- }
- virtual std::string analysis()override {
- for (auto child : childs) {
- std::string childValue = child->analysis();
- html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
- }
- std::string propName;
- std::string propValue;
- std::map<std::string, std::string> mapPropValue;
- {
- int index = 0;
- std::string tmp = extract(html_code_tmp, { "name='","'" }, index);
- std::string::size_type pos = tmp.find('.');
- if (pos != std::string::npos) {
- propName = tmp.substr(pos + 1, tmp.size() - pos - 1);
- }
- }
- //获取值
- {
- int index = 0;
- std::string tmp = extract(html_code_tmp.substr(index, html_code_tmp.size() - index), { "value='[","]'" }, index);
- //属性值
- if (tmp == "#value") {
- propValue = tmp;
- }
- else {
- auto values = v3::utils::split(tmp, ",");
- for (auto value : values) {
- auto valueItem = v3::utils::split(value, ":");
- if (valueItem.size() == 2) {
- if (valueItem[0].size() >= 2 && valueItem[1].size() >= 2 &&
- valueItem[0][0] == '\'' && valueItem[0][valueItem[0].size() - 1] == '\'' &&
- valueItem[1][0] == '\'' && valueItem[1][valueItem[1].size() - 1] == '\'') {
- valueItem[0].erase(valueItem[0].begin());
- valueItem[0].erase(valueItem[0].begin() + valueItem[0].size() - 1);
- valueItem[1].erase(valueItem[1].begin());
- valueItem[1].erase(valueItem[1].begin() + valueItem[1].size() - 1);
- mapPropValue[valueItem[0]] = valueItem[1];
- }
- }
- }
- }
- }
- if (propName.empty()) {
- return "";
- }
- //属性值
- if (!propValue.empty() && !class_value_list.empty()) {
- if (class_value_list[0].find(propName) != class_value_list[0].end()) {
- return class_value_list[0][propName];
- }
- }
- else if (!mapPropValue.empty() && !class_value_list.empty()) {
- if (class_value_list[0].find(propName) != class_value_list[0].end()) {
- std::string value = class_value_list[0][propName];
- //选择值
- if (mapPropValue.find(value) != mapPropValue.end()) {
- return mapPropValue[value];
- }
- //默认值
- else if (mapPropValue.find("default") != mapPropValue.end()) {
- if (mapPropValue["default"] == "#value") {
- return class_value_list[0][propName];
- }
- else {
- return mapPropValue["default"];
- }
- }
- }
- }
- return "";
- }
- virtual void analysis_baseinfo() override {
- html_code_tmp = html_code;
- for (auto child : childs) {
- child->analysis_baseinfo();
- }
- //获取类名属性名
- int index = 0;
- std::string tmp = extract(html_code, { "name='","'" }, index);
- std::string::size_type pos = tmp.find('.');
- if (pos != std::string::npos) {
- class_name = tmp.substr(0, pos);
- }
- }
- };
- struct pseudo_for_label : public ipseudo_label {
- pseudo_for_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
- ipseudo_label(value_type) {
- }
- virtual std::string analysis()override {
- for (auto child : childs) {
- std::string childValue = child->analysis();
- html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
- }
- std::string resultValue;
- std::string itemName;
- std::string forLabel;
- std::vector<std::string> forItemLabelList;
- std::map<std::string, std::map<std::string, std::map<std::string, std::string>>> forItemLabelValueList;
- //获取ITEM名称
- {
- int index = 0;
- itemName = extract(html_code_tmp, { "item='","'" }, index);
- if (itemName.empty())
- return "";
- }
- //提取for标签值
- {
- int index = 0;
- std::string header = extract(html_code_tmp, { "${for","}" }, index);
- header = "${for" + header + "}";
- forLabel = extract(html_code_tmp, { header,"{/for}" }, index);
- }
- //提取foritem标签
- {
- forItemLabelList = extractList(forLabel, { "{item","/}" });
- for (auto& it : forItemLabelList) {
- it = "{item" + it + "/}";
- }
- if (forItemLabelList.empty())
- return forLabel;
- }
- //提取foritem参数
- {
- int index = 0;
- std::string header = "name='" + itemName + ".";
- for (auto it : forItemLabelList) {
- std::string propName = extract(it, { header,"'" }, index);
- if (propName.empty())
- continue;
- std::string value = extract(it, { "value='[","]'" }, index);
- if (value.empty())
- continue;
- if (value == "#value") {
- forItemLabelValueList[it][propName][value] = value;
- }
- else {
- auto values = v3::utils::split(value, ",");
- for (auto valueIt : values) {
- auto valueItem = v3::utils::split(valueIt, "':'");
- if (valueItem.size() == 2) {
- valueItem[0] += "'";
- valueItem[1] = "'" + valueItem[1];
- if (valueItem[0].size() >= 2 && valueItem[1].size() >= 2 &&
- valueItem[0][0] == '\'' && valueItem[0][valueItem[0].size() - 1] == '\'' &&
- valueItem[1][0] == '\'' && valueItem[1][valueItem[1].size() - 1] == '\'') {
- valueItem[0].erase(valueItem[0].begin());
- valueItem[0].erase(valueItem[0].begin() + valueItem[0].size() - 1);
- valueItem[1].erase(valueItem[1].begin());
- valueItem[1].erase(valueItem[1].begin() + valueItem[1].size() - 1);
- forItemLabelValueList[it][propName][valueItem[0]] = valueItem[1];
- }
- }
- }
- }
- }
- }
- //遍历值
- {
- int index = 0;
- for (auto item : class_value_list) {
- index++;
- std::string itemValue = forLabel;
- for (auto forItem : forItemLabelList) {
- //没有查找到值赋值为空
- if (forItemLabelValueList.find(forItem) == forItemLabelValueList.end()) {
- itemValue = v3::utils::replace(itemValue, forItem, "");
- continue;
- }
- //查找属性
- if (forItemLabelValueList[forItem].find("for-index") != forItemLabelValueList[forItem].end()) {
- //默认值
- if (forItemLabelValueList[forItem]["for-index"].find("#value") != forItemLabelValueList[forItem]["for-index"].end()) {
- itemValue = v3::utils::replace(itemValue, forItem, std::to_string(index));
- }
- else {
- if (forItemLabelValueList[forItem]["for-index"].find(std::to_string(index)) != forItemLabelValueList[forItem]["for-index"].end()) {
- itemValue = v3::utils::replace(itemValue, forItem, forItemLabelValueList[forItem]["for-index"][std::to_string(index)]);
- }
- else if (forItemLabelValueList[forItem]["for-index"].find("default") != forItemLabelValueList[forItem]["for-index"].end()) {
- itemValue = v3::utils::replace(itemValue, forItem, forItemLabelValueList[forItem]["for-index"]["default"]);
- }
- else {
- itemValue = v3::utils::replace(itemValue, forItem, "");
- }
- }
- continue;
- }
- else {
- std::string propNameItem;
- std::map<std::string, std::string> propValueItem;
- auto childItem = forItemLabelValueList[forItem];
- for (auto childItemIt : childItem) {
- propNameItem = childItemIt.first;
- propValueItem = childItemIt.second;
- }
- if (propNameItem.empty()) {
- itemValue = v3::utils::replace(itemValue, forItem, "");
- continue;
- }
- if (item.find(propNameItem) != item.end()) {
- if (item.find(propNameItem) != item.end()) {
- if (propValueItem.find("#value") != propValueItem.end()) {
- itemValue = v3::utils::replace(itemValue, forItem, item[propNameItem]);
- }
- else if (propValueItem.find(item[propNameItem]) != propValueItem.end()) {
- itemValue = v3::utils::replace(itemValue, forItem, propValueItem[item[propNameItem]]);
- }
- else if (propValueItem.find("default") != propValueItem.end()) {
- if (propValueItem["default"] == "#value") {
- itemValue = v3::utils::replace(itemValue, forItem, item[propNameItem]);
- }
- else {
- itemValue = v3::utils::replace(itemValue, forItem, propValueItem["default"]);
- }
- }
- else {
- itemValue = v3::utils::replace(itemValue, forItem, "");
- }
- }
- else {
- itemValue = v3::utils::replace(itemValue, forItem, "");
- }
- }
- else {
- itemValue = v3::utils::replace(itemValue, forItem, "");
- }
- }
- }
- resultValue += itemValue;
- }
- }
- return resultValue;
- }
- virtual void analysis_baseinfo() override {
- html_code_tmp = html_code;
- for (auto child : childs) {
- child->analysis_baseinfo();
- }
- //获取类名属性名
- int index = 0;
- class_name = extract(html_code, { "list='","'" }, index);
- }
- };
- struct pseudo_if_label : public ipseudo_label {
- pseudo_if_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
- ipseudo_label(value_type) {
- }
- virtual std::string analysis()override {
- for (auto child : childs) {
- std::string childValue = child->analysis();
- html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
- }
- std::string propName;
- std::string propValue;
- std::string symbol;
- std::vector<std::string> labelValue;
- //提取标签内容
- {
- labelValue = extractList(html_code_tmp, { "}","{" });
- if (labelValue.empty())
- return "";
- }
- //判断结构体是否有值
- {
- if (class_value_list.empty()) {
- if (labelValue.size() == 2) {
- return labelValue[1];
- }
- return "";
- }
- }
- //获取类名属性名
- {
- int index = 0;
- std::string tmp = extract(html_code_tmp, { "name='","'" }, index);
- std::string::size_type pos = tmp.find('.');
- if (pos != std::string::npos) {
- propName = tmp.substr(pos + 1, tmp.size() - pos - 1);
- }
- }
- //判断类名
- {
- if (propName.empty()) {
- if (labelValue.size() == 2) {
- return labelValue[1];
- }
- return "";
- }
- }
- //判断属性名称是否存在
- {
- if (class_value_list[0].find(propName) == class_value_list[0].end()) {
- if (labelValue.size() == 2) {
- return labelValue[1];
- }
- return "";
- }
- }
- //提取操作符 逻辑对比值
- {
- int index = 0;
- propValue = extract(html_code_tmp, { "value=='","'" }, index);
- //==
- if (propValue.empty()) {
- propValue = extract(html_code_tmp, { "value!='","'" }, index);
- //!=
- if (propValue.empty()) {
- propValue = extract(html_code_tmp, { "value>='","'" }, index);
- //>=
- if (propValue.empty()) {
- propValue = extract(html_code_tmp, { "value<='","'" }, index);
- //<=
- if (propValue.empty()) {
- if (labelValue.size() == 2) {
- return labelValue[1];
- }
- return "";
- }
- else
- symbol = "<=";
- }
- else
- symbol = ">=";
- }
- else
- symbol = "!=";
- }
- else
- symbol = "==";
- }
- //判断
- {
- if (symbol == "==" && propValue.compare(class_value_list[0][propName]) == 0) {
- return labelValue[0];
- }
- else if (symbol == "!=" && propValue.compare(class_value_list[0][propName]) != 0) {
- return labelValue[0];
- }
- else if (symbol == ">=" && propValue.compare(class_value_list[0][propName]) >= 0) {
- return labelValue[0];
- }
- else if (symbol == "<=" && propValue.compare(class_value_list[0][propName]) <= 0) {
- return labelValue[0];
- }
- else {
- if (labelValue.size() == 2)
- return labelValue[1];
- }
- }
- return "";
- }
- virtual void analysis_baseinfo() override {
- html_code_tmp = html_code;
- for (auto child : childs) {
- child->analysis_baseinfo();
- }
- //获取类名属性名
- int index = 0;
- std::string tmp = extract(html_code, { "name='","'" }, index);
- std::string::size_type pos = tmp.find('.');
- if (pos != std::string::npos) {
- class_name = tmp.substr(0, pos);
- }
- }
- };
- struct pseudo_switch_label : public ipseudo_label {
- pseudo_switch_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
- ipseudo_label(value_type) {
- }
- virtual std::string analysis()override {
- for (auto child : childs) {
- std::string childValue = child->analysis();
- html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
- }
- std::string propName;
- std::string labelValueDefault;
- std::vector<std::string> labelValue;
- //获取类名属性名
- {
- int index = 0;
- std::string tmp = extract(html_code_tmp, { "name='","'" }, index);
- std::string::size_type pos = tmp.find('.');
- if (pos != std::string::npos) {
- propName = tmp.substr(pos + 1, tmp.size() - pos - 1);
- }
- }
- //提取标签内容
- {
- int index = 0;
- labelValue = extractList(html_code_tmp, { "{case","/case}" });
- labelValueDefault = extract(html_code_tmp, { "{default}","{/default}" }, index);
- if (labelValue.empty() && labelValueDefault.empty()) {
- return "";
- }
- else if (labelValue.empty() && !labelValueDefault.empty()) {
- if (labelValueDefault.find("#value") != std::string::npos) {
- if (class_value_list.empty())
- return "";
- if (propName.empty())
- return "";
- if (class_value_list[0].find(propName) == class_value_list[0].end())
- return "";
- return class_value_list[0][propName];
- }
- return labelValueDefault;
- }
- }
- //判断属性值
- {
- if (class_value_list.empty()) {
- if (labelValueDefault.empty())
- return "";
- if (labelValueDefault.find("#value") != std::string::npos)
- return "";
- return labelValueDefault;
- }
- if (propName.empty()) {
- if (labelValueDefault.empty())
- return "";
- if (labelValueDefault.find("#value") != std::string::npos)
- return "";
- return labelValueDefault;
- }
- if (class_value_list[0].find(propName) == class_value_list[0].end()) {
- if (labelValueDefault.empty())
- return "";
- if (labelValueDefault.find("#value") != std::string::npos)
- return "";
- return labelValueDefault;
- }
- }
- //遍历值
- {
- for (auto it : labelValue) {
- int index = 0;
- std::string propValue = extract(it, { "value='","'" }, index);
- if (class_value_list[0][propName] == propValue) {
- return extract(it, { "}","{" }, index);
- }
- }
- }
- //判断默认值
- {
- if (labelValueDefault.empty())
- return "";
- if (labelValueDefault.find("#value") != std::string::npos) {
- return v3::utils::replace(labelValueDefault, "#value", class_value_list[0][propName]);
- }
- return labelValueDefault;
- }
- }
- virtual void analysis_baseinfo() override {
- html_code_tmp = html_code;
- for (auto child : childs) {
- child->analysis_baseinfo();
- }
- //获取类名属性名
- int index = 0;
- std::string tmp = extract(html_code, { "name='","'" }, index);
- std::string::size_type pos = tmp.find('.');
- if (pos != std::string::npos) {
- class_name = tmp.substr(0, pos);
- }
- }
- };
- struct pseudo_file_label : public ipseudo_label {
- pseudo_file_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
- ipseudo_label(value_type) {
- }
- virtual std::string analysis()override {
- for (auto child : childs) {
- std::string childValue = child->analysis();
- html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
- }
- int index = 0;
- std::string path_tmp = extract(html_code_tmp, { "path='","'" }, index);
- std::filesystem::path path = path_tmp;
- std::filesystem::path filepath;
- filepath = http_context::current()->response.get_root_directory();
- filepath.make_preferred();
- filepath /= path.make_preferred().relative_path();
- if (filepath.empty())
- return "";
- if (std::filesystem::exists(filepath)) {
- std::ifstream file(filepath, std::ios::in);
- if (file.is_open()) {
- return std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
- }
- }
- return "";
- }
- virtual void analysis_baseinfo() override {
- html_code_tmp = html_code;
- for (auto child : childs) {
- child->analysis_baseinfo();
- }
- }
- };
- struct pseudo_extract_class_value {
- template<typename ..._Args>
- static std::vector<std::shared_ptr<class_value>> get_class_value(_Args&&...args) {
- std::vector<std::shared_ptr<class_value>> result;
- auto tuple = std::forward_as_tuple(std::forward<_Args>(args)...);
- v3::utils::for_each(tuple, [&](auto& it) {
- auto value = serialize(it);
- result.push_back(value); });
- return result;
- }
- private:
- static std::string get_prop_value(rttr::variant const& value) {
- std::string result;
- if (value.get_type() == rttr::type::get<int>()) {
- result = std::to_string(value.get_value<int>());
- }
- else if (value.get_type() == rttr::type::get<std::int64_t>()) {
- result = std::to_string(value.get_value<std::int64_t>());
- }
- else if (value.get_type() == rttr::type::get<float>()) {
- result = v3::utils::format("{:.2f}", value.get_value<float>());
- }
- else if (value.get_type() == rttr::type::get<double>()) {
- result = v3::utils::format("{:.2f}", value.get_value<double>());
- }
- else if (value.get_type() == rttr::type::get<long>()) {
- result = std::to_string(value.get_value<long>());
- }
- else if (value.get_type() == rttr::type::get<bool>()) {
- if (value.get_value<bool>())
- result = "true";
- else
- result = "false";
- }
- else if (value.get_type() == rttr::type::get<std::string>()) {
- result = value.get_value<std::string>();
- }
- else if (value.get_type() == rttr::type::get<v3::datetime>()) {
- auto t = value.get_value<v3::datetime>();
- result = t.to_string();
- }
- else if (value.get_type() == rttr::type::get<std::vector<int>>()) {
- auto values = value.get_value<std::vector<int>>();
- for (int i = 0; i < values.size(); ++i) {
- if (i + 1 == values.size()) {
- result += std::to_string(values[i]);
- }
- else {
- result += std::to_string(values[i]) + ",";
- }
- }
- }
- else if (value.get_type() == rttr::type::get<std::vector<std::int64_t>>()) {
- auto values = value.get_value<std::vector<std::int64_t>>();
- for (int i = 0; i < values.size(); ++i) {
- if (i + 1 == values.size()) {
- result += std::to_string(values[i]);
- }
- else {
- result += std::to_string(values[i]) + ",";
- }
- }
- }
- else if (value.get_type() == rttr::type::get<std::vector<float>>()) {
- auto values = value.get_value<std::vector<float>>();
- for (int i = 0; i < values.size(); ++i) {
- if (i + 1 == values.size()) {
- result += v3::utils::format("{:.2f}", values[i]);
- }
- else {
- result += v3::utils::format("{:.2f}", values[i]) + ",";
- }
- }
- }
- else if (value.get_type() == rttr::type::get<std::vector<double>>()) {
- auto values = value.get_value<std::vector<double>>();
- for (int i = 0; i < values.size(); ++i) {
- if (i + 1 == values.size()) {
- result += v3::utils::format("{:.2f}", values[i]);
- }
- else {
- result += v3::utils::format("{:.2f}", values[i]) + ",";
- }
- }
- }
- else if (value.get_type() == rttr::type::get<std::vector<long>>()) {
- auto values = value.get_value<std::vector<long>>();
- for (int i = 0; i < values.size(); ++i) {
- if (i + 1 == values.size()) {
- result += std::to_string(values[i]);
- }
- else {
- result += std::to_string(values[i]) + ",";
- }
- }
- }
- else if (value.get_type() == rttr::type::get<std::vector<bool>>()) {
- auto values = value.get_value<std::vector<bool>>();
- for (int i = 0; i < values.size(); ++i) {
- if (i + 1 == values.size()) {
- result += values[i] ? "true" : "false";
- }
- else {
- result += values[i] ? "true," : "false,";
- }
- }
- }
- else if (value.get_type() == rttr::type::get<std::vector<std::string>>()) {
- auto values = value.get_value<std::vector<std::string>>();
- for (int i = 0; i < values.size(); ++i) {
- if (i + 1 == values.size()) {
- result += values[i];
- }
- else {
- result += values[i] + ",";
- }
- }
- }
- else if (value.get_type() == rttr::type::get<std::vector<v3::datetime>>()) {
- auto values = value.get_value<std::vector<v3::datetime>>();
- for (int i = 0; i < values.size(); ++i) {
- if (i + 1 == values.size()) {
- result += values[i].to_string();
- }
- else {
- result += values[i].to_string() + ",";
- }
- }
- }
- return result;
- }
- template<typename _Type>
- static std::shared_ptr<class_value> serialize(std::vector<std::shared_ptr<_Type>> const& values) {
- std::vector<_Type> valueTmp;
- for (auto it : values) {
- valueTmp.push_back(*it);
- }
- return serialize(valueTmp);
- }
- template<typename _Type>
- static std::shared_ptr<class_value> serialize(std::vector<_Type*> values) {
- std::vector<_Type> valueTmp;
- for (auto it : values) {
- valueTmp.push_back(*it);
- }
- return serialize(valueTmp);
- }
- template<typename _Type>
- static std::shared_ptr<class_value> serialize(std::vector<_Type> values) {
- std::shared_ptr<class_value> result(new class_value);
- rttr::type type = rttr::type::get<_Type>();
- std::string className(type.get_name());
- result->class_name = className;
- result->is_list = true;
- for (auto it : values) {
- std::map<std::string, std::string> elem;
- web_reflect::get_object_value(it, elem);
- result->class_value.push_back(elem);
- }
- return result;
- }
- template<typename _Type>
- static std::shared_ptr<class_value> serialize(std::shared_ptr<_Type> value) {
- return serialize(*value);
- }
- template<typename _Type>
- static std::shared_ptr<class_value> serialize(_Type* value) {
- return serialize(*value);
- }
- template<typename _Type>
- static std::shared_ptr<class_value> serialize(_Type value) {
- std::shared_ptr<class_value> result(new class_value);
- rttr::type type = rttr::type::get<_Type>();
- std::string className(type.get_name());
- result->class_name = className;
- result->is_list = false;
- std::map<std::string, std::string> elem = web_reflect::get_object_value(value);
- result->class_value.push_back(elem);
- return result;
- }
- };
- struct pseudo_extract_label_value {
- /*
- * 伪代码结构
- * 可嵌套 避开关键字 [' }]
- * ${model name='test_info.userName' value='['${model name='test_info.id' value='[#value]'/}':'启用','false':'禁用'/}
- *
- * switch case 中不能存在 #value 属性值 default可以有默认值 可以有固定值
- * ${switch name='test_info.id'}{case value='1'}<h1>值1</h1>{/case}...{default}<h1>#value</h1>{/default}{/switch}
- *
- * if 运算符 == != >= <=
- * ${if name='test_info.id' value=='100'}<p>判断正确</p>{else}<p>判断错误</p>{/if}
- *
- * for for-index 从1开始
- * ${for item='item' list='test_info'} <td>{item name='item.for-index' value='[#value]'/}</td><td>{item name='item.enable' value='['true':'启用','default':'#value']'/}</td>{/for}
- *
- * file path 可以固定 可以嵌套 model设置html路径
- * ${file path='C:/Users/86158/Desktop/404.html'/}
- */
- static std::vector<std::shared_ptr<ipseudo_label>> analysis(std::string const& html) {
- std::vector<std::shared_ptr<ipseudo_label>> result;
- std::pair<std::string, std::string> type = { "${mask","{/mask}" };
- for (size_t i = 0; i < html.size(); ++i) {
- if (html.size() > i + type.first.size() &&
- html[i] == type.first[0] &&
- html.substr(i, type.first.size()) == type.first) {
- std::string retHtml = nounanalysis(html.substr(i, html.size() - i), result);
- result[result.size() - 1]->html_code;
- i += retHtml.size();
- }
- }
- for (auto it : result) {
- it->analysis_baseinfo();
- }
- return result;
- }
- private:
- static std::string nounanalysis(std::string const& html, std::vector<std::shared_ptr<ipseudo_label>>& childs, pseudo_type type = pseudo_type::MASK) {
- static std::map<pseudo_type, std::pair<std::string, std::string>> g_pseudoLabel = {
- {
- pseudo_type::MASK,
- {"${mask","{/mask}"}
- },
- {
- pseudo_type::MODEL,
- {"${model","/}"}
- },
- {
- pseudo_type::SWITCH,
- {"${switch","{/switch}"}
- },
- {
- pseudo_type::IF,
- {"${if","{/if}"}
- },
- {
- pseudo_type::FOR,
- {"${for","{/for}"}
- },
- {
- pseudo_type::FILE,
- {"${file","/}"}
- }
- };
- if (!(html.size() > g_pseudoLabel[type].first.size() &&
- html.substr(0, g_pseudoLabel[type].first.size()) == g_pseudoLabel[type].first)) {
- return "";
- }
- if (type == pseudo_type::MASK)
- childs.push_back(std::make_shared<pseudo_mask_label>(*g_pseudoLabel.find(type)));
- else if (type == pseudo_type::MODEL)
- childs.push_back(std::make_shared<pseudo_model_label>(*g_pseudoLabel.find(type)));
- else if (type == pseudo_type::FOR)
- childs.push_back(std::make_shared<pseudo_for_label>(*g_pseudoLabel.find(type)));
- else if (type == pseudo_type::IF)
- childs.push_back(std::make_shared<pseudo_if_label>(*g_pseudoLabel.find(type)));
- else if (type == pseudo_type::SWITCH)
- childs.push_back(std::make_shared<pseudo_switch_label>(*g_pseudoLabel.find(type)));
- else if (type == pseudo_type::FILE)
- childs.push_back(std::make_shared<pseudo_file_label>(*g_pseudoLabel.find(type)));
- for (std::string::size_type i = 0; i < html.size(); ++i) {
- for (auto pseudo : g_pseudoLabel) {
- if (html.size() > i + pseudo.second.first.size() &&
- html[i] == pseudo.second.first[0] &&
- html.substr(i, pseudo.second.first.size()) == pseudo.second.first) {
- if (i == 0) {
- break;
- }
- else {
- std::string retHtml = nounanalysis(html.substr(i, html.size() - i), childs[childs.size() - 1]->childs, pseudo.first);
- childs[childs.size() - 1]->html_code += retHtml;
- i += retHtml.size();
- }
- }
- }
- if (type != pseudo_type::NON) {
- childs[childs.size() - 1]->html_code += html[i];
- }
- if (childs[childs.size() - 1]->html_code.size() > g_pseudoLabel[type].second.size() &&
- childs[childs.size() - 1]->html_code.substr(childs[childs.size() - 1]->html_code.size() - g_pseudoLabel[type].second.size(), g_pseudoLabel[type].second.size()) == g_pseudoLabel[type].second) {
- return childs[childs.size() - 1]->html_code;
- }
- }
- return "";
- }
- };
- enum class from_storage_type {
- /**
- * @brief body
- */
- BODY = 0,
- /**
- * @brief url
- */
- QUERY,
- /**
- * @brief header
- */
- HEADER,
- /**
- * @brief url
- */
- URL
- };
- enum class argument_type {
- Json = 0,
- Multipart,
- Int,
- Int64,
- Float,
- Double,
- Long,
- Bool_,
- String,
- DateTime,
- Binary,
- VecJson,
- VecInt,
- VecInt64,
- VecFloat,
- VecDouble,
- VecLong,
- VecBool,
- VecString,
- VecDateTime
- };
- enum class http_method {
- /**
- * @brief get
- */
- GET = 0,
- /**
- * @brief post
- */
- POST = 1
- };
- struct multipart {
- std::string content_disposition;
- std::string name;
- std::vector<std::uint8_t> data;
- std::string value;
- std::string content_type;
- std::string filename;
- std::string content_transfer_encoding;
- };
- struct multipart_value {
- std::vector<multipart> data;
- template<typename _Type>
- _Type value() {
- _Type result;
- std::map<std::string, std::string> elem;
- for (auto value : data) {
- elem[value.name] = value.value;
- }
- web_reflect::set_object_value(result, elem);
- return result;
- }
- };
- struct action_argument {
- void parameter(http::web_request& request, const rttr::parameter_info& type) {
- parameter_value_.clear();
- switch (from_storage_type_) {
- case from_storage_type::HEADER: analysis_header(request, type); return;
- case from_storage_type::QUERY: analysis_query(request, type); return;
- case from_storage_type::BODY: analysis_body(request, type); return;
- case from_storage_type::URL: analysis_url(request, type); return;
- }
- throw std::runtime_error("FormStorageType:错误!");
- }
- /**
- * @brief 参数名称
- */
- std::string parameter_name_;
- /**
- * @brief 参数
- */
- rttr::variant parameter_value_;
- /**
- * @brief 数据类型
- */
- argument_type argument_type_ = argument_type::Binary;
- /**
- * @brief 表单存储类型
- */
- from_storage_type from_storage_type_ = from_storage_type::QUERY;
- private:
- /**
- * @brief 解析协议头
- * @param request
- * @param type
- */
- void analysis_header(http::web_request& request, const rttr::parameter_info& type) {
- std::map<std::string, std::string> headers;
- for (auto& it : request) {
- std::string name(it.name_string().begin(), it.name_string().end());
- std::string value(it.value().begin(), it.value().end());
- headers[name] = value;
- }
- if (headers.find(parameter_name_) == headers.end())
- throw std::runtime_error("解析协议头参数错误!");
- convert(headers[parameter_name_], type);
- }
- /**
- * @brief 解析url参数
- * @param request
- * @param type
- */
- void analysis_query(http::web_request& request, const rttr::parameter_info& type) {
- std::string query(request.query().begin(), request.query().end());
- std::map<std::string, std::string> querys = v3::utils::split_http_form(query);
- if (querys.find(parameter_name_) == querys.end())
- throw std::runtime_error("解析Query参数错误!");
- convert(querys[parameter_name_], type);
- }
- /**
- * @brief 解析BODY
- * @param request
- * @param type
- */
- void analysis_body(http::web_request& request, const rttr::parameter_info& type) {
- if (type.get_type() == rttr::type::get<multipart_value>()) {
- multipart_value parameter;
- auto multipartValue = request.get_multipart();
- for (auto it = multipartValue.begin(); it != multipartValue.end(); ++it) {
- multipart item;
- item.content_disposition = it->content_disposition();
- item.name = it->name();
- auto valueTmp = it->value();
- item.data.insert(item.data.end(), valueTmp.begin(), valueTmp.end());
- if (it->filename().empty()) {
- try {
- item.value = it->value();
- }
- catch (...) {}
- }
- item.content_type = it->content_type();
- item.filename = it->filename();
- item.content_transfer_encoding = it->content_transfer_encoding();
- parameter.data.push_back(item);
- }
- parameter_value_ = parameter;
- }
- else if (parameter_name_.empty()) {
- convert(std::string(request.body().begin(), request.body().end()), type);
- }
- else {
- std::string body(request.body().begin(), request.body().end());
- std::map<std::string, std::string> bodys = v3::utils::split_http_form(body);
- if (bodys.find(parameter_name_) == bodys.end())
- throw std::runtime_error("解析Body参数错误!");
- convert(bodys[parameter_name_], type);
- }
- }
- /**
- * @brief url
- * @param request
- * @param type
- */
- void analysis_url(http::web_request& request, const rttr::parameter_info& type) {
- std::string query(request.find("http_route_parameter")->value());
- std::map<std::string, std::string> querys = v3::utils::split_http_form(query);
- if (querys.find(parameter_name_) == querys.end())
- throw std::runtime_error("解析Query参数错误!");
- convert(querys[parameter_name_], type);
- }
- /**
- * @brief 数据转换
- * @param data
- * @param type
- */
- void convert(std::string_view data, const rttr::parameter_info& type) {
- try {
- switch (argument_type_) {
- case argument_type::Json: {
- parameter_value_ = type.get_type().create();
- v3::json_convert::deserialize(std::string(data.begin(), data.end()), parameter_value_);
- return;
- }
- case argument_type::Multipart: {
- return;
- }
- case argument_type::Int: {
- parameter_value_ = std::atoi(std::string(data.begin(), data.end()).c_str());
- return;
- }
- case argument_type::Int64: {
- parameter_value_ = std::atoll(std::string(data.begin(), data.end()).c_str());
- return;
- }
- case argument_type::Float: {
- parameter_value_ = std::atof(std::string(data.begin(), data.end()).c_str());
- return;
- }
- case argument_type::Double: {
- parameter_value_ = std::atof(std::string(data.begin(), data.end()).c_str());
- return;
- }
- case argument_type::Long: {
- parameter_value_ = std::atol(std::string(data.begin(), data.end()).c_str());
- return;
- }
- case argument_type::Bool_: {
- std::string tmpValue(data.begin(), data.end());
- parameter_value_ = tmpValue == "1" || tmpValue == "true" || tmpValue == "TRUE" || tmpValue == "True";
- return;
- }
- case argument_type::String: {
- parameter_value_ = std::string(data.begin(), data.end());
- return;
- }
- case argument_type::DateTime: {
- parameter_value_ = datetime(std::string(data.begin(), data.end()));
- return;
- }
- case argument_type::Binary: {
- parameter_value_ = std::vector<std::uint8_t>(data.begin(), data.end());
- return;
- }
- case argument_type::VecInt: {
- std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
- std::vector<int> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(std::atoi(vecIt.c_str()));
- }
- parameter_value_ = vecValue;
- return;
- }
- case argument_type::VecInt64: {
- std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
- std::vector<std::int64_t> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(std::atoll(vecIt.c_str()));
- }
- parameter_value_ = vecValue;
- return;
- }
- case argument_type::VecFloat: {
- std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
- std::vector<float> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(std::atof(vecIt.c_str()));
- }
- parameter_value_ = vecValue;
- return;
- }
- case argument_type::VecDouble: {
- std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
- std::vector<double> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(std::atof(vecIt.c_str()));
- }
- parameter_value_ = vecValue;
- return;
- }
- case argument_type::VecLong: {
- std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
- std::vector<long> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(std::atol(vecIt.c_str()));
- }
- parameter_value_ = vecValue;
- return;
- }
- case argument_type::VecBool: {
- std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
- std::vector<bool> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(vecIt == "1" || vecIt == "true" || vecIt == "TRUE" || vecIt == "True");
- }
- parameter_value_ = vecValue;
- return;
- }
- case argument_type::VecString: {
- std::vector<std::string> vecValue = v3::utils::split(std::string(data.begin(), data.end()), ",");
- parameter_value_ = vecValue;
- return;
- }
- case argument_type::VecDateTime: {
- std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
- std::vector<datetime> vecValue;
- for (auto vecIt : vec) {
- vecValue.push_back(datetime(vecIt));
- }
- parameter_value_ = vecValue;
- return;
- }
- }
- }
- catch (...) {
- throw std::runtime_error("解析参数错误");
- }
- }
- };
- struct controller;
- struct controller_action {
- /**
- * @brief 执行动作
- * @param request
- */
- rttr::variant invoke(http::web_request& request, rttr::variant& variant, rttr::type const& controller_type) {
- auto http_current_ptr = http_context::current();
- //判断contentType
- std::string content_type = "application/x-www-form-urlencoded";
- if (request.find(http::field::content_type) != request.end()) {
- content_type = std::string(request.find(http::field::content_type)->value().begin(), request.find(http::field::content_type)->value().end());
- }
- if (content_type.find(content_type) == std::string::npos) {
- throw std::runtime_error("Content-Type:错误!");
- }
- //判断method
- if (!((method == http_method::GET && request.method() == http::verb::get) || (method == http_method::POST && request.method() == http::verb::post))) {
- throw std::runtime_error("Method:错误!");
- }
- std::vector<rttr::method> find_method;
- for (auto& it : controller_type.get_methods()) {
- if (it.get_name() == action_name && it.get_parameter_infos().size() == arguments.size()) {
- find_method.push_back(it);
- break;
- }
- }
- if (find_method.empty())
- throw std::runtime_error("Action:错误!");
- std::vector<rttr::argument> parameters;
- std::vector<rttr::variant> variantParameters;
- {
- std::lock_guard<std::mutex> locker(mux);
- for (auto& it : find_method[0].get_parameter_infos()) {
- arguments[it.get_index()]->parameter(request, it);
- }
- for (auto& it : arguments) {
- variantParameters.push_back(it->parameter_value_);
- }
- }
- for (auto& it : variantParameters) {
- parameters.push_back(it);
- }
- return controller_type.invoke(action_name, variant, parameters);
- }
- /**
- * @brief 身份验证
- */
- bool authen = true;
- /**
- * @brief 未登录跳转
- */
- std::string authen_jump;
- /**
- * @brief 方法名称
- */
- std::string action_name;
- /**
- * @brief 方式
- */
- http_method method = http_method::GET;
- /**
- * @brief 数据类型
- */
- std::string content_type = "application/x-www-form-urlencoded";
- /**
- * @brief 动作类型
- */
- std::string action_type;
- /**
- * @brief 文件映射
- */
- std::string file_mapping;
- /**
- * @brief 参数
- */
- std::vector<std::shared_ptr<action_argument>> arguments;
- /**
- * @brief 控制器
- */
- std::shared_ptr<controller> parent;
- private:
- /**
- * @brief 锁
- */
- std::mutex mux;
- };
- struct controller {
- rttr::variant invoke(http::web_request& request) {
- std::string key(request.find("http_route_key")->value());
- if (!actions.contains(key))
- throw std::runtime_error("Action:不存在!");
- rttr::type type = rttr::type::get_by_name(controller_name);
- if (!variant.is_valid())
- variant = type.create();
- return actions[key]->invoke(request, variant, type);
- }
- /**
- * @brief 控制器名称
- */
- std::string controller_name;
- /**
- * @brief 动作列表 路由 动作
- */
- std::map<std::string, std::shared_ptr<controller_action>> actions;
- private:
- /**
- * @brief 对象
- */
- rttr::variant variant;
- };
- struct mvc_route {
- bool contains(http::web_request& req) {
- std::string key;
- std::string route(req.find("http_route")->value());
- if (contains(route, key)) {
- std::size_t index = key.find('<');
- std::vector<std::string> params;
- if (std::string::npos != index) {
- auto keys = v3::utils::split(key.substr(index), "/");
- auto values = v3::utils::split(route.substr(index), "/");
- for (int i = 0; i < keys.size() && i < values.size(); ++i) {
- params.push_back(keys[i].substr(1, keys[i].size() - 2) + "=" + values[i]);
- }
- }
- req.insert("http_route_key",key);
- req.insert("http_route_parameter", v3::utils::join(params, "&"));
- return true;
- }
- return false;
- }
- bool contains(std::string const&route) {
- std::string key;
- return contains(route, key);
- }
- void add(std::string const& route, std::shared_ptr<controller> value) {
- routes_[route] = value;
- }
- std::shared_ptr<controller>& operator[](std::string const& route) {
- std::string key;
- if (contains(route, key)) {
- return routes_[key];
- }
- throw std::runtime_error("key does not exist");
- }
- std::shared_ptr<controller>& operator[](http::web_request& req) {
- return this->operator[](std::string(req.find("http_route_key")->value()));
- }
- private:
- bool contains(std::string const& route, std::string& result) {
- if (routes_.contains(route)) {
- result = route;
- return true;
- }
- else {
- int slash_count = std::count(route.begin(), route.end(), '/');
- for (auto& [first, second] : routes_) {
- std::size_t index = first.find('<');
- if (std::count(first.begin(), first.end(), '/') == slash_count && index != std::string::npos) {
- if (first.substr(0, index) == route.substr(0, index)) {
- result = first;
- return true;
- }
- }
- }
- return false;
- }
- }
- private:
- std::map<std::string, std::shared_ptr<controller>> routes_;
- };
- struct ico_controller {
- /**
- * @brief 注册
- */
- static void attach(std::shared_ptr<controller> controller) {
- for (auto& [first, second] : controller->actions) {
- controllers_.add(first, controller);
- }
- }
- /**
- * @brief
- * @param url
- * @return
- */
- static std::shared_ptr<controller> resolve(http::web_request& req) {
- if (controllers_.contains(req)) {
- return controllers_[req];
- }
- return nullptr;
- }
- private:
- /**
- * @brief
- */
- static mvc_route controllers_;
- };
- mvc_route ico_controller::controllers_;
- struct web_base_response {
- void set_header(std::string_view name, std::string_view value) {
- auto& response = http_context::current()->response;
- response.set(name, value);
- }
- void set_header(http::field field, std::string_view value) {
- auto& response = http_context::current()->response;
- response.set(field, value);
- }
- void set_value(std::string_view value) {
- auto& response = http_context::current()->response;
- response.body().file().close();
- response.body().text() = std::move(value);
- auto const size = response.body().size();
- response.content_length(size);
- }
- void set_value(std::vector<std::uint8_t> const& value) {
- auto& response = http_context::current()->response;
- response.body().file().close();
- response.body().text() = std::string((char*)&value[0], value.size());
- auto const size = response.body().size();
- response.content_length(size);
- }
- void set_status(http::status status = http::status::ok) {
- auto& response = http_context::current()->response;
- response.result(status);
- }
- std::filesystem::path get_root_directory() {
- auto& response = http_context::current()->response;
- return response.get_root_directory();
- }
- http::status get_status() {
- auto& response = http_context::current()->response;
- return response.result();
- }
- std::string get_value() {
- auto& response = http_context::current()->response;
- return response.body().text();
- }
- void prepare_payload() {
- auto& response = http_context::current()->response;
- response.prepare_payload();
- }
- void chunked(bool value) {
- auto& response = http_context::current()->response;
- response.chunked(value);
- }
- void set_server(std::string_view value = BEAST_VERSION_STRING) {
- auto& response = http_context::current()->response;
- response.set(http::field::server, value);
- }
- void set_version(int ver = 11) {
- auto& response = http_context::current()->response;
- response.version(ver);
- }
- void fill_file(std::filesystem::path const& path, http::status status = http::status::ok) {
- auto& response = http_context::current()->response;
- if (path.c_str()[0] == '/' || path.c_str()[0] == '\\') {
- response.fill_file(path, status);
- }
- else {
- response.fill_file("/" + path.string(), status);
- }
- }
- void fill_html(std::string const& html, http::status status = http::status::ok) {
- auto& response = http_context::current()->response;
- response.fill_html(html, status);
- }
- void fill_json(std::string const& json, http::status status = http::status::ok) {
- auto& response = http_context::current()->response;
- response.fill_json(json, status);
- }
- void fill_page(std::string const& value, http::status status = http::status::ok) {
- auto& response = http_context::current()->response;
- response.fill_page(status, value);
- }
- void fill_text(std::string const& text, http::status status = http::status::ok) {
- auto& response = http_context::current()->response;
- response.fill_text(text, status);
- }
- void fill_jump(std::string const& url) {
- set_header(http::field::content_type, http::extension_to_mimetype("html"));
- set_header(http::field::location, url);
- set_status(http::status::found);
- }
- void fill_stream(std::vector<std::uint8_t> const& data, std::string const& extension, http::status status = http::status::ok) {
- set_header("Content-Type", http::extension_to_mimetype(extension));
- set_value(data);
- set_status(status);
- }
- void fill_download(std::filesystem::path const& path, http::status status = http::status::ok) {
- set_header(http::field::content_type, "application/octet-stream");
- set_header(http::field::content_disposition, v3::utils::format("attachment; filename={}", path.filename().string()));
- }
- void fill_download(std::filesystem::path const& path, std::string const& filename, http::status status = http::status::ok) {
- set_header(http::field::content_type, "application/octet-stream");
- set_header(http::field::content_disposition, v3::utils::format("attachment; filename={}", filename));
- }
- void fill_view(http::status status = http::status::ok) {
- fill_file(get_filename(), status);
- }
- std::filesystem::path get_filename() {
- return mvc::http_context::current()->get_controller_action()->file_mapping;
- }
- };
- struct web_result_response : public web_base_response {};
- struct unknown_response : public web_base_response {
- unknown_response(std::string const& text) {
- set_value(text);
- set_status(http::status::unknown);
- }
- virtual ~unknown_response() {
- }
- operator web_result_response() {
- return {};
- }
- };
- struct jump_response : public web_base_response {
- jump_response(std::string const& url) {
- if (!url.empty()) {
- if (url[0] != '/')
- fill_jump("/" + url);
- }
- else {
- fill_jump(url);
- }
- }
- virtual ~jump_response() {
- }
- operator web_result_response() {
- return {};
- }
- };
- struct text_response : public web_base_response {
- text_response(std::string const& text, http::status status = http::status::ok) {
- fill_text(text, status);
- }
- virtual ~text_response() {
- }
- operator web_result_response() {
- return {};
- }
- };
- struct html_response : public web_base_response {
- html_response(std::string const& html, http::status status = http::status::ok) {
- fill_html(html, status);
- }
- virtual ~html_response() {
- }
- operator web_result_response() {
- return {};
- }
- };
- struct file_response : public web_base_response {
- file_response() {
- fill_file(get_filename());
- }
- file_response(http::status status = http::status::ok) {
- fill_file(get_filename(), status);
- }
- file_response(std::filesystem::path const& path, http::status status = http::status::ok) {
- fill_file(path, status);
- }
- virtual ~file_response() {
- }
- operator web_result_response() {
- return {};
- }
- };
- struct json_response : public web_base_response {
- json_response(std::string const& json) {
- fill_json(json);
- }
- json_response(char* json) :
- json_response(std::string(json)) {
- }
- json_response(const char* json) :
- json_response(std::string(json)) {
- }
- template<typename _Type>
- json_response(_Type const& value) {
- fill_json(v3::json_convert::serialize(value));
- }
- virtual~json_response() {
- }
- operator web_result_response() {
- return {};
- }
- };
- struct stream_response : public web_base_response {
- stream_response(std::vector<std::uint8_t> const& data, std::string const& extension, http::status status = http::status::ok) {
- fill_stream(data, extension, status);
- }
- virtual~stream_response() {
- }
- operator web_result_response() {
- return {};
- }
- };
- struct download_response : public web_base_response {
- download_response(std::filesystem::path const& path, http::status status = http::status::ok) {
- fill_download(path, status);
- }
- download_response(std::filesystem::path const& path, std::string const& filename, http::status status = http::status::ok) {
- fill_download(path, filename, status);
- }
- virtual~download_response() {
- }
- operator web_result_response() {
- return {};
- }
- };
- struct view : public web_base_response {
- virtual ~view() {
- }
- view() :
- web_base_response() {
- fill_view();
- }
- view(std::string const& path) :
- web_base_response() {
- fill_file(path);
- }
- template<typename ..._Args>
- view(_Args&& ...args) {
- std::filesystem::path path = get_filename();
- std::filesystem::path filepath;
- filepath = http_context::current()->response.get_root_directory();
- filepath.make_preferred();
- filepath /= path.make_preferred().relative_path();
- std::vector<std::uint8_t> value;
- std::ifstream file(filepath, std::ios::in | std::ios::binary);
- if (file.is_open()) {
- file.seekg(0, std::ios::end);
- int file_size = file.tellg();
- file.seekg(0, std::ios::beg);
- value.resize(file_size);
- file.read((char*)&value[0], file_size);
- file.close();
- }
- std::string html(value.begin(), value.end());
- auto label_value_list = pseudo_extract_label_value::analysis(html);
- if (!label_value_list.empty()) {
- auto classValueList = pseudo_extract_class_value::get_class_value(std::forward<_Args>(args)...);
- label_value_list[0]->set_class_value(classValueList);
- html = label_value_list[0]->analysis();
- fill_html(html);
- }
- }
- operator web_result_response() {
- return {};
- }
- };
- template<int _Width = 100, int _Height = 38, int _Length = 4, int _Line = 2, int _Spot = 200>
- struct captcha_response : public v3::mvc::web_base_response {
- captcha_response(std::string const& session_key = "code") :
- session_key_(session_key) {
- }
- virtual ~captcha_response() {
- }
- operator v3::mvc::web_result_response() {
- //验证码
- std::string captcha_code = generate_captcha_digits();
- http_context::current()->add_session(session_key_, captcha_code);
- std::vector<std::uint8_t> img_vec = generate_captcha_image(captcha_code);
- return v3::mvc::stream_response(img_vec, "bmp");
- }
- private:
- class CImage : public cimg_library::CImg<unsigned char> {
- public:
- CImage(const cimg_library::CImg<unsigned char>& img) :
- cimg_library::CImg<unsigned char>(img) {}
- cimg_library::CImg<unsigned char>& save_memory_bmp(std::vector<std::uint8_t>& result) {
- cimg_library::CImg<ucharT> header(54, 1, 1, 1, 0);
- unsigned char align_buf[4] = {};
- const unsigned int
- align = (4 - (3 * _width) % 4) % 4,
- buf_size = (3 * _width + align) * height(),
- file_size = 54 + buf_size;
- header[0] = 'B'; header[1] = 'M';
- header[0x02] = file_size & 0xFF;
- header[0x03] = (file_size >> 8) & 0xFF;
- header[0x04] = (file_size >> 16) & 0xFF;
- header[0x05] = (file_size >> 24) & 0xFF;
- header[0x0A] = 0x36;
- header[0x0E] = 0x28;
- header[0x12] = _width & 0xFF;
- header[0x13] = (_width >> 8) & 0xFF;
- header[0x14] = (_width >> 16) & 0xFF;
- header[0x15] = (_width >> 24) & 0xFF;
- header[0x16] = _height & 0xFF;
- header[0x17] = (_height >> 8) & 0xFF;
- header[0x18] = (_height >> 16) & 0xFF;
- header[0x19] = (_height >> 24) & 0xFF;
- header[0x1A] = 1;
- header[0x1B] = 0;
- header[0x1C] = 24;
- header[0x1D] = 0;
- header[0x22] = buf_size & 0xFF;
- header[0x23] = (buf_size >> 8) & 0xFF;
- header[0x24] = (buf_size >> 16) & 0xFF;
- header[0x25] = (buf_size >> 24) & 0xFF;
- header[0x27] = 0x1;
- header[0x2B] = 0x1;
- result.insert(result.end(), reinterpret_cast<std::uint8_t*>(header._data), reinterpret_cast<std::uint8_t*>(header._data) + 64);
- const unsigned char
- * ptr_r = data(0, _height - 1, 0, 0),
- * ptr_g = (_spectrum >= 2) ? data(0, _height - 1, 0, 1) : 0,
- * ptr_b = (_spectrum >= 3) ? data(0, _height - 1, 0, 2) : 0;
- switch (_spectrum) {
- case 1: {
- cimg_forY(*this, y) {
- cimg_forX(*this, x) {
- const unsigned char val = (unsigned char)*(ptr_r++);
- result.push_back(val); result.push_back(val); result.push_back(val);
- }
- result.insert(result.end(), reinterpret_cast<std::uint8_t*>(align_buf), reinterpret_cast<std::uint8_t*>(align_buf) + align);
- ptr_r -= 2 * _width;
- }
- } break;
- case 2: {
- cimg_forY(*this, y) {
- cimg_forX(*this, x) {
- result.push_back(0);
- result.push_back((unsigned char)(*(ptr_g++)));
- result.push_back((unsigned char)(*(ptr_r++)));
- }
- result.insert(result.end(), reinterpret_cast<std::uint8_t*>(align_buf), reinterpret_cast<std::uint8_t*>(align_buf) + align);
- ptr_r -= 2 * _width; ptr_g -= 2 * _width;
- }
- } break;
- default: {
- cimg_forY(*this, y) {
- cimg_forX(*this, x) {
- result.push_back((unsigned char)(*(ptr_b++)));
- result.push_back((unsigned char)(*(ptr_g++)));
- result.push_back((unsigned char)(*(ptr_r++)));
- }
- result.insert(result.end(), reinterpret_cast<std::uint8_t*>(align_buf), reinterpret_cast<std::uint8_t*>(align_buf) + align);
- ptr_r -= 2 * _width; ptr_g -= 2 * _width; ptr_b -= 2 * _width;
- }
- }
- }
- return *this;
- }
- };
- private:
- //获取验证码
- std::string generate_captcha_digits() {
- static const char data_character[] = "23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ\0";
- int min = 0;
- int max = std::strlen(data_character) - 1;
- std::string result;
- for (int i = 0; i < _Length; ++i) {
- result += data_character[v3::utils::random(min, max)];
- }
- return result;
- }
- //生成随机颜色
- unsigned char* generate_random_color() {
- static unsigned char colors[][3] = {
- {47,79,79},
- {100,149,237},
- {0,0,205},
- {0,191,255},
- {30,144,255},
- {70,130,180},
- {0,206,209},
- {0,255,255},
- {0,100,0},
- {85,107,47},
- {46,139,87},
- {107,142,35},
- {184,134,11},
- {218,165,32},
- {139,69,19},
- {165,42,42},
- {255,127,80},
- {255,69,0},
- {176,48,96},
- {160,32,240},
- {139,137,137},
- {58,95,205},
- {16,78,139},
- {0,154,205},
- {159,182,205},
- {0,197,205},
- {121,205,205},
- {69,139,116},
- {67,205,128},
- {0,205,102},
- {205,155,29},
- {205,85,85},
- {205,133,63},
- {205,38,38},
- {205,133,0},
- {205,91,69},
- {205,79,57},
- {205,55,0},
- {205,145,158},
- {139,28,98},
- {180,82,205},
- {125,38,205},
- {139,123,139},
- {0,0,139},
- {0,139,139},
- {139,0,139},
- {139,0,0} };
- return colors[v3::utils::random(0, sizeof(colors) / sizeof(colors[0]) - 1)];
- }
- //生成字体大小,位置
- std::vector<std::tuple<int, int, int>> generate_font_size() {
- std::vector<std::tuple<int, int, int>> result;
- int s_width = _Width / _Length;
- int s_height = _Height;
- for (int i = 0; i < _Length; ++i) {
- int x = 0, y = 0, s = 0;
- double font_centre_pos = 0.0;
- if (s_width > s_height) {
- s = v3::utils::random(double(s_height) - double(s_height) * 0.2, double(s_height) * 1.2);
- }
- else {
- s = v3::utils::random(double(s_width) - double(s_width) * 0.2, double(s_width) * 1.2);
- }
- font_centre_pos = double(s) * 0.8;
- x = v3::utils::random(0, double(s_width) - font_centre_pos);
- y = v3::utils::random(0, double(s_height) - font_centre_pos);
- result.push_back(std::make_tuple(s, x, y));
- }
- return result;
- }
- //验证码图片
- std::vector<std::uint8_t> generate_captcha_image(std::string const& code) {
- std::vector<std::uint8_t> result;
- cimg_library::CImg<unsigned char> image(_Width, _Height, 1, 3, 255); // 创建一个白色背景的图像
- int s_width = _Width / _Length;
- int s_height = _Height;
- std::vector<std::tuple<int, int, int>> font_info = generate_font_size();
- char c[2] = { 0 };
- //绘制验证码
- for (int i = 0; i < _Length; ++i) {
- c[0] = code[i];
- image.draw_text(i * s_width + std::get<1>(font_info[i]), std::get<2>(font_info[i]), c, generate_random_color(), 0, 1, std::get<0>(font_info[i])).width();
- }
- //绘制干扰线
- for (int i = 0; i < _Line; ++i) {
- int x1 = std::rand() % _Width;
- int y1 = std::rand() % _Height;
- int x2 = std::rand() % _Width;
- int y2 = std::rand() % _Height;
- // 生成随机颜色
- image.draw_line(x1, y1, x2, y2, generate_random_color());
- }
- //绘制干扰点
- for (int i = 0; i < _Spot; ++i) {
- int x = std::rand() % _Width;
- int y = std::rand() % _Height;
- // 生成随机颜色
- image.draw_point(x, y, generate_random_color());
- }
- //扭曲图像
- cimg_library::CImg<unsigned char> distorted_image(_Width, _Height, 1, 3, 255);
- cimg_forXY(image, xx, yy) {
- int new_xx = xx + static_cast<int>(1.32 * sin(2 * 3.14 * yy * 0.045));
- int new_yy = yy + static_cast<int>(1.42 * sin(2 * 3.14 * xx * 0.062));
- if (new_xx >= 0 && new_xx < _Width && new_yy >= 0 && new_yy < _Height) {
- distorted_image(xx, yy, 0, 0) = image(new_xx, new_yy, 0, 0);
- distorted_image(xx, yy, 0, 1) = image(new_xx, new_yy, 0, 1);
- distorted_image(xx, yy, 0, 2) = image(new_xx, new_yy, 0, 2);
- }
- }
- CImage(distorted_image).save_memory_bmp(result);
- return result;
- }
- private:
- std::string session_key_;
- };
- class http_server_t {
- public:
- http_server_t() {
- server_.bind<http::verb::post, http::verb::get>(std::string("/*"), &http_server_t::on_base_request, this);
- }
- bool start(std::string const& ip, int port) {
- return server_.start(ip, port);
- }
- void stop() {
- server_.stop();
- }
- void set_root_directory(std::filesystem::path const& path) {
- server_.set_root_directory(path);
- }
- protected:
- virtual void on_request(http::web_request& req, http::web_response& rep) = 0;
- private:
- void on_base_request(std::shared_ptr<asio2::http_session>& session_ptr, http::web_request& req, http::web_response& rep) {
- on_request(req, rep);
- }
- private:
- asio2::http_server server_;
- };
- class https_server_t {
- public:
- https_server_t() {
- server_.bind<http::verb::post, http::verb::get>("/*", &https_server_t::on_base_request, this);
- }
- bool start(std::string const& ip, int port) {
- return server_.start(ip, port);
- }
- void stop() {
- server_.stop();
- }
- void set_root_directory(std::filesystem::path const& path) {
- server_.set_root_directory(path);
- }
- void set_cert_file(std::string const& ca_cert_file, std::string const& private_cert_file, std::string const& private_key_file, std::string const& private_password) {
- server_.set_cert_file(ca_cert_file, private_cert_file, private_key_file, private_password);
- }
- protected:
- virtual void on_request(http::web_request& req, http::web_response& rep) = 0;
- private:
- void on_base_request(std::shared_ptr<asio2::https_session>& session_ptr, http::web_request& req, http::web_response& rep) {
- on_request(req, rep);
- }
- private:
- asio2::https_server server_;
- };
- template<typename _Before, typename _Err, typename _After, typename _TypeBase>
- class http_server_base : public _TypeBase {
- public:
- http_server_base() :
- _TypeBase() {
- }
- private:
- virtual void on_request(http::web_request& req, http::web_response& rep)override {
- http_context_gc http_context(req, rep);
- try {
- req.insert("http_route",std::string(req.path()).substr(1));
- std::shared_ptr<controller> controller = v3::mvc::ico_controller::resolve(req);
- std::string key(req.find("http_route_key")->value());
- http_context::current()->set_controller_action((bool)controller ? controller->actions[key] : nullptr);
- if (before_.before((bool)controller ? controller->actions[key] : nullptr, req, rep)) {
- rttr::variant variant = controller->invoke(req);
- if (variant.is_valid()) {
- auto response = variant.get_value<web_base_response>();
- response.set_version();
- response.set_server();
- response.chunked(true);
- response.prepare_payload();
- }
- }
- //文件
- else {
- rep.fill_file(req.path());
- rep.set(http::field::cache_control, "max-age=31536000");
- rep.chunked(true);
- }
- }
- catch (unknown_response const&) {
- }
- catch (jump_response const&) {
- }
- catch (text_response const&) {
- }
- catch (html_response const&) {
- }
- catch (file_response const&) {
- }
- catch (json_response const&) {
- }
- catch (std::exception const& ec) {
- err_.error(ec.what(), req, rep);
- }
- catch (...) {
- err_.error("未知异常", req, rep);
- }
- after_.after(req, rep);
- }
- private:
- _Before before_;
- _Err err_;
- _After after_;
- };
- template<typename _Before, typename _Err, typename _After>
- using http_server = http_server_base<_Before, _Err, _After, http_server_t>;
- template<typename _Before, typename _Err, typename _After>
- using https_server = http_server_base<_Before, _Err, _After, https_server_t>;
- }
- }
- }
|