Enhancements

Add more HTTP status code with detailed error info.
Improve error handling with broken links.
Add basic support for extra response headers.
This commit is contained in:
Tindy X committed 2020-01-20 00:22:41 +08:00
1 parent d13788e1d1
commit 0c76741a25
6 files changed
+61 -32

No files matched your search

+32 -13
View File
@@ -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 '"<<x<<"'."<<std::endl;
addNodes(x, nodes, groupID, proxy, exclude_remarks, include_remarks);
if(addNodes(x, nodes, groupID, proxy, exclude_remarks, include_remarks) == -1)
{
*status_code = 400;
return std::string("The following link doesn't contain any valid node info: " + x);
}
groupID++;
}
//exit if found nothing
if(!nodes.size())
{
*status_code = 400;
return "No nodes were found!";
}
std::cerr<<"Generate target: ";
if(target == "clash" || target == "clashr")
@@ -651,9 +661,15 @@ std::string simpleToClashR(RESPONSE_CALLBACK_ARGS)
if(!url.size())
url = default_url;
if(!url.size() || argument.substr(0, 8) != "sublink=")
{
*status_code = 400;
return "Invalid request!";
}
if(url == "sublink")
{
*status_code = 400;
return "Please insert your subscription link instead of clicking the default link.";
}
if(!api_mode || cfw_child_process)
readConf();
@@ -680,7 +696,10 @@ std::string simpleToClashR(RESPONSE_CALLBACK_ARGS)
addNodes(url, nodes, 0, proxy, exclude_remarks, include_remarks);
if(!nodes.size())
{
*status_code = 400;
return "No nodes were found!";
}
std::cerr<<"Generate target: ClashR\n";
@@ -781,62 +800,62 @@ int main(int argc, char *argv[])
append_response("GET", "/clash", "text/plain;charset=utf-8", [](RESPONSE_CALLBACK_ARGS) -> 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)
+13 -10
View File
@@ -22,7 +22,7 @@ void copyNodes(std::vector<nodeInfo> &source, std::vector<nodeInfo> &dest)
}
}
void addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std::string proxy, string_array &exclude_remarks, string_array &include_remarks)
int addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std::string proxy, string_array &exclude_remarks, string_array &include_remarks)
{
int linkType = -1;
std::vector<nodeInfo> nodes;
@@ -70,7 +70,11 @@ void addNodes(std::string link, std::vector<nodeInfo> &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<nodeInfo> &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);
}
break;
default:
if(linkType > 0)
@@ -101,19 +104,19 @@ void addNodes(std::string link, std::vector<nodeInfo> &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);
}
}
else
{
writeLog(LOG_TYPE_ERROR, "No valid link found.");
return -1;
}
}
return 0;
}
+1 -1
View File
@@ -6,6 +6,6 @@
#include "nodeinfo.h"
void addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std::string proxy, string_array &exclude_remarks, string_array &include_remarks);
int addNodes(std::string link, std::vector<nodeInfo> &allNodes, int groupID, std::string proxy, string_array &exclude_remarks, string_array &include_remarks);
#endif // NODEMANIP_H_INCLUDED
+2 -1
View File
@@ -1442,11 +1442,12 @@ 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;
}
iter = nodes.begin();
while(iter != nodes.end())
+2 -2
View File
@@ -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<std::string, std::string>&); //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<std::string, std::string> &extra_headers
struct listener_args
{
+11 -5
View File
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
#include <map>
#include <string.h>
#include <pthread.h>
@@ -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<std::string, std::string> &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<std::string, std::string> 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.";