Add support for simple web server

Update Docker README.
This commit is contained in:
Tindy X
2020-08-19 01:23:44 +08:00
parent 6befb9db14
commit 1b30e89f80
6 changed files with 87 additions and 2 deletions

View File

@@ -7,7 +7,7 @@ For running this docker, simply use the following commands:
# run the container detached, forward internal port 25500 to host port 25500
docker run -d --restart=always -p 25500:25500 tindy2013/subconverter:latest
# then check its status
curl http://localhost:25500
curl http://localhost:25500/version
# if you see `subconverter vx.x.x backend` then the container is up and running
```
@@ -37,6 +37,6 @@ docker build -t subconverter-custom:latest .
# run the docker detached, forward internal port 25500 to host port 25500
docker run -d --restart=always -p 25500:25500 subconverter-custom:latest
# then check its status
curl http://localhost:25500
curl http://localhost:25500/version
# if you see `subconverter vx.x.x backend` then the container is up and running
```

View File

@@ -126,6 +126,7 @@ aliases:
server:
listen: 0.0.0.0
port: 25500
serve_file_root: ""
advanced:
log_level: info

View File

@@ -251,6 +251,9 @@ listen=0.0.0.0
;Port to bind on for Web Server
port=25500
;Root folder for web server, keep empty to disable
serve_file_root=
[advanced]
log_level=info
print_debug_info=false

View File

@@ -37,6 +37,9 @@ extern int gLogLevel;
extern long gMaxAllowedDownloadSize;
string_map gAliases;
extern bool gServeFile;
extern std::string gServeFileRoot;
//global variables for template
std::string gTemplatePath = "templates";
string_map gTemplateVars;
@@ -837,6 +840,8 @@ void readYAMLConf(YAML::Node &node)
{
node["server"]["listen"] >> gListenAddress;
node["server"]["port"] >> gListenPort;
node["server"]["serve_file_root"] >>= gServeFileRoot;
gServeFile = !gServeFileRoot.empty();
}
if(node["advanced"].IsDefined())
@@ -1088,6 +1093,8 @@ void readConf()
ini.EnterSection("server");
ini.GetIfExist("listen", gListenAddress);
ini.GetIntIfExist("port", gListenPort);
gServeFileRoot = ini.Get("serve_file_root");
gServeFile = !gServeFileRoot.empty();
ini.EnterSection("advanced");
std::string log_level;

View File

@@ -143,10 +143,12 @@ int main(int argc, char *argv[])
if(gGeneratorMode)
return simpleGenerator();
/*
append_response("GET", "/", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string
{
return "subconverter " VERSION " backend\n";
});
*/
append_response("GET", "/version", "text/plain", [](RESPONSE_CALLBACK_ARGS) -> std::string
{

View File

@@ -21,6 +21,72 @@
extern std::string user_agent_str;
std::atomic_bool SERVER_EXIT_FLAG(false);
// file server
bool gServeFile = false;
std::string gServeFileRoot;
struct MIME_type
{
std::string extension;
std::string mimetype;
};
MIME_type mime_types[] = {{"html htm shtml","text/html"},
{"css", "text/css"},
{"jpeg jpg", "image/jpeg"},
{"js", "application/javascript"},
{"txt", "text/plain"},
{"png", "image/png"},
{"ico", "image/x-icon"},
{"svg svgz", "image/svg+xml"},
{"woff", "application/font-woff"},
{"json", "application/json"}};
bool matchSpaceSeparatedList(const std::string& source, const std::string &target)
{
string_size pos_begin = 0, pos_end, total = source.size();
while(pos_begin < total)
{
pos_end = source.find(' ', pos_begin);
if(pos_end == source.npos)
pos_end = total;
if(source.compare(pos_begin, pos_end - pos_begin, target) == 0)
return true;
pos_begin = pos_end + 1;
}
return false;
}
std::string checkMIMEType(const std::string filename)
{
string_size name_begin = 0, name_end = 0;
name_begin = filename.rfind('/');
if(name_begin == filename.npos)
name_begin = 0;
name_end = filename.rfind('.');
if(name_end == filename.npos || name_end < name_begin || name_end == filename.size() - 1)
return "application/octet-stream";
std::string extension = filename.substr(name_end + 1);
for(MIME_type &x : mime_types)
if(matchSpaceSeparatedList(x.extension, extension))
return x.mimetype;
return "application/octet-stream";
}
int serveFile(const std::string &filename, std::string &content_type, std::string &return_data)
{
std::string realname = gServeFileRoot + filename;
if(filename.compare("/") == 0)
realname += "index.html";
if(!fileExist(realname))
return 1;
return_data = fileGet(realname, false);
content_type = checkMIMEType(realname);
writeLog(0, "file-server: serving '" + filename + "' type '" + content_type + "'", LOG_LEVEL_INFO);
return 0;
}
struct responseRoute
{
std::string method;
@@ -83,6 +149,12 @@ static inline int process_request(Request &request, Response &response, std::str
return 0;
}
if(gServeFile)
{
if(request.method.compare("GET") == 0 && serveFile(request.url, response.content_type, return_data) == 0)
return 0;
}
return -1;
}