From 0c76741a25ce151e519d086eebf182f4f185f4d7 Mon Sep 17 00:00:00 2001 From: Tindy X <49061470+tindy2013@users.noreply.github.com> Date: Mon, 20 Jan 2020 00:22:41 +0800 Subject: [PATCH] Enhancements Add more HTTP status code with detailed error info. Improve error handling with broken links. Add basic support for extra response headers. --- src/main.cpp | 45 +++++++++++++++++++++++++++----------- src/nodemanip.cpp | 33 +++++++++++++++------------- src/nodemanip.h | 2 +- src/speedtestutil.cpp | 9 ++++---- src/webserver.h | 4 ++-- src/webserver_libevent.cpp | 16 +++++++++----- 6 files changed, 69 insertions(+), 40 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e654d60..793e77a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -365,7 +365,10 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) if(!url.size()) url = default_url; if(!url.size() || !target.size()) + { + *status_code = 400; return "Invalid request!"; + } //check if we need to read configuration if(!api_mode || cfw_child_process) @@ -498,12 +501,19 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) { x = trim(x); std::cerr<<"Fetching node data from url '"< std::string { - return subconverter(argument + "&target=clash", postdata); + return subconverter(argument + "&target=clash", postdata, status_code, extra_headers); }); append_response("GET", "/clashr", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { - return subconverter(argument + "&target=clashr", postdata); + return subconverter(argument + "&target=clashr", postdata, status_code, extra_headers); }); append_response("GET", "/surge", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { - return subconverter(argument + "&target=surge", postdata); + return subconverter(argument + "&target=surge", postdata, status_code, extra_headers); }); append_response("GET", "/surfboard", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { - return subconverter(argument + "&target=surfboard", postdata); + return subconverter(argument + "&target=surfboard", postdata, status_code, extra_headers); }); append_response("GET", "/mellow", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { - return subconverter(argument + "&target=mellow", postdata); + return subconverter(argument + "&target=mellow", postdata, status_code, extra_headers); }); append_response("GET", "/ss", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { - return subconverter(argument + "&target=ss", postdata); + return subconverter(argument + "&target=ss", postdata, status_code, extra_headers); }); append_response("GET", "/sssub", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { - return subconverter(argument + "&target=sssub", postdata); + return subconverter(argument + "&target=sssub", postdata, status_code, extra_headers); }); append_response("GET", "/ssr", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { - return subconverter(argument + "&target=ssr", postdata); + return subconverter(argument + "&target=ssr", postdata, status_code, extra_headers); }); append_response("GET", "/v2ray", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { - return subconverter(argument + "&target=v2ray", postdata); + return subconverter(argument + "&target=v2ray", postdata, status_code, extra_headers); }); append_response("GET", "/quan", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { - return subconverter(argument + "&target=quan", postdata); + return subconverter(argument + "&target=quan", postdata, status_code, extra_headers); }); append_response("GET", "/quanx", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> std::string { - return subconverter(argument + "&target=quanx", postdata); + return subconverter(argument + "&target=quanx", postdata, status_code, extra_headers); }); append_response("GET", "/ssd", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string { - return subconverter(argument + "&target=ssd", postdata); + return subconverter(argument + "&target=ssd", postdata, status_code, extra_headers); }); if(!api_mode) diff --git a/src/nodemanip.cpp b/src/nodemanip.cpp index ea03238..bb5f3a4 100644 --- a/src/nodemanip.cpp +++ b/src/nodemanip.cpp @@ -22,7 +22,7 @@ void copyNodes(std::vector &source, std::vector &dest) } } -void addNodes(std::string link, std::vector &allNodes, int groupID, std::string proxy, string_array &exclude_remarks, string_array &include_remarks) +int addNodes(std::string link, std::vector &allNodes, int groupID, std::string proxy, string_array &exclude_remarks, string_array &include_remarks) { int linkType = -1; std::vector nodes; @@ -70,7 +70,11 @@ void addNodes(std::string link, std::vector &allNodes, int groupID, st if(strSub.size()) { writeLog(LOG_TYPE_INFO, "Parsing subscription data..."); - explodeConfContent(strSub, override_conf_port, socksport, ss_libev, ssr_libev, nodes, exclude_remarks, include_remarks); + if(explodeConfContent(strSub, override_conf_port, socksport, ss_libev, ssr_libev, nodes, exclude_remarks, include_remarks) == SPEEDTEST_ERROR_UNRECOGFILE) + { + writeLog(LOG_TYPE_ERROR, "Invalid subscription!"); + return -1; + } for(nodeInfo &x : nodes) x.groupID = groupID; copyNodes(nodes, allNodes); @@ -78,22 +82,21 @@ void addNodes(std::string link, std::vector &allNodes, int groupID, st else { writeLog(LOG_TYPE_ERROR, "Cannot download subscription data."); + return -1; } break; case SPEEDTEST_MESSAGE_FOUNDLOCAL: if(api_mode) - break; + return -1; writeLog(LOG_TYPE_INFO, "Parsing configuration file data..."); if(explodeConf(link, override_conf_port, socksport, ss_libev, ssr_libev, nodes, exclude_remarks, include_remarks) == SPEEDTEST_ERROR_UNRECOGFILE) { writeLog(LOG_TYPE_ERROR, "Invalid configuration file!"); + return -1; } - else - { - for(nodeInfo &x : nodes) - x.groupID = groupID; - copyNodes(nodes, allNodes); - } + for(nodeInfo &x : nodes) + x.groupID = groupID; + copyNodes(nodes, allNodes); break; default: if(linkType > 0) @@ -101,19 +104,19 @@ void addNodes(std::string link, std::vector &allNodes, int groupID, st explode(link, ss_libev, ssr_libev, override_conf_port, socksport, node); if(custom_group.size() != 0) node.group = custom_group; - if(node.server == "") + if(node.linkType == -1) { writeLog(LOG_TYPE_ERROR, "No valid link found."); + return -1; } - else - { - node.groupID = groupID; - allNodes.push_back(node); - } + node.groupID = groupID; + allNodes.push_back(node); } else { writeLog(LOG_TYPE_ERROR, "No valid link found."); + return -1; } } + return 0; } diff --git a/src/nodemanip.h b/src/nodemanip.h index 9767b85..6d7f5ad 100644 --- a/src/nodemanip.h +++ b/src/nodemanip.h @@ -6,6 +6,6 @@ #include "nodeinfo.h" -void addNodes(std::string link, std::vector &allNodes, int groupID, std::string proxy, string_array &exclude_remarks, string_array &include_remarks); +int addNodes(std::string link, std::vector &allNodes, int groupID, std::string proxy, string_array &exclude_remarks, string_array &include_remarks); #endif // NODEMANIP_H_INCLUDED diff --git a/src/speedtestutil.cpp b/src/speedtestutil.cpp index 6557a8c..c6713f4 100644 --- a/src/speedtestutil.cpp +++ b/src/speedtestutil.cpp @@ -1442,12 +1442,13 @@ int explodeConfContent(std::string content, std::string custom_port, int local_p default: //try to parse as a local subscription explodeSub(content, sslibev, ssrlibev, custom_port, local_port, nodes, exclude_remarks, include_remarks); - if(nodes.size() == 0) - return SPEEDTEST_ERROR_UNRECOGFILE; - else - return SPEEDTEST_ERROR_NONE; } + if(nodes.size() == 0) + return SPEEDTEST_ERROR_UNRECOGFILE; + else + return SPEEDTEST_ERROR_NONE; + iter = nodes.begin(); while(iter != nodes.end()) { diff --git a/src/webserver.h b/src/webserver.h index 07b70da..50a3547 100644 --- a/src/webserver.h +++ b/src/webserver.h @@ -1,9 +1,9 @@ #ifndef WEBSERVER_H_INCLUDED #define WEBSERVER_H_INCLUDED -typedef std::string (*response_callback)(std::string, std::string); //process arguments and POST data and return served-content +typedef std::string (*response_callback)(std::string, std::string, int*, std::map&); //process arguments and POST data and return served-content -#define RESPONSE_CALLBACK_ARGS std::string argument, std::string postdata +#define RESPONSE_CALLBACK_ARGS std::string argument, std::string postdata, int *status_code, std::map &extra_headers struct listener_args { diff --git a/src/webserver_libevent.cpp b/src/webserver_libevent.cpp index a3f92fe..353b80e 100644 --- a/src/webserver_libevent.cpp +++ b/src/webserver_libevent.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -33,7 +34,7 @@ static inline void buffer_cleanup(struct evbuffer *eb) #endif // MALLOC_TRIM } -static inline int process_request(const char *method_str, std::string uri, std::string &postdata, std::string &content_type, std::string &return_data) +static inline int process_request(const char *method_str, std::string uri, std::string &postdata, std::string &content_type, std::string &return_data, int *status_code, std::map &extra_headers) { std::string path, arguments; std::cerr << "handle_cmd: " << method_str << std::endl << "handle_uri: " << uri << std::endl; @@ -55,7 +56,7 @@ static inline int process_request(const char *method_str, std::string uri, std:: else if(x.method.compare(method_str) == 0 && x.path == path) { response_callback &rc = x.rc; - return_data = rc(arguments, postdata); + return_data = rc(arguments, postdata, status_code, extra_headers); content_type = x.content_type; return 0; } @@ -86,19 +87,24 @@ void OnReq(evhttp_request *req, void *args) postdata.assign(req_ac_method); } - retVal = process_request(req_method, uri, postdata, content_type, return_data); + int status_code = 200; + std::map extra_headers; + retVal = process_request(req_method, uri, postdata, content_type, return_data, &status_code, extra_headers); //auto *OutBuf = evhttp_request_get_output_buffer(req); struct evbuffer *OutBuf = evbuffer_new(); if (!OutBuf) return; + for(auto &x : extra_headers) + evhttp_add_header(req->output_headers, x.first.data(), x.second.data()); + switch(retVal) { case 1: //found OPTIONS evhttp_add_header(req->output_headers, "Access-Control-Allow-Origin", "*"); evhttp_add_header(req->output_headers, "Access-Control-Allow-Headers", "*"); - evhttp_send_reply(req, HTTP_OK, "", NULL); + evhttp_send_reply(req, status_code, "", NULL); break; case 0: //found normal if(content_type.size()) @@ -116,7 +122,7 @@ void OnReq(evhttp_request *req, void *args) evhttp_add_header(req->output_headers, "Access-Control-Allow-Origin", "*"); evhttp_add_header(req->output_headers, "Connection", "close"); evbuffer_add(OutBuf, return_data.data(), return_data.size()); - evhttp_send_reply(req, HTTP_OK, "", OutBuf); + evhttp_send_reply(req, status_code, "", OutBuf); break; case -1: //not found return_data = "File not found.";