mistserver/src/output/output_http_minimalserver.cpp
2021-10-19 22:29:40 +02:00

82 lines
2.8 KiB
C++

#include "output_http_minimalserver.h"
#include <fstream>
namespace Mist{
OutHTTPMinimalServer::OutHTTPMinimalServer(Socket::Connection &conn) : HTTPOutput(conn){
// resolve symlinks etc to a real path
char *rp = realpath(config->getString("webroot").c_str(), 0);
if (rp){
resolved_path = rp;
resolved_path += "/";
free(rp);
}
}
OutHTTPMinimalServer::~OutHTTPMinimalServer(){}
void OutHTTPMinimalServer::init(Util::Config *cfg){
HTTPOutput::init(cfg);
capa["name"] = "HTTPMinimalServer";
capa["friendly"] = "Utility: Static HTTP file server";
capa["desc"] = "Serves static files over HTTP from a set folder";
capa["url_rel"] = "/static/";
capa["url_prefix"] = "/static/";
cfg->addOption("webroot", JSON::fromString("{\"arg\":\"string\", "
"\"short\":\"w\",\"long\":\"webroot\",\"help\":"
"\"Root directory for static files to serve.\"}"));
capa["required"]["webroot"]["name"] = "Web root directory";
capa["required"]["webroot"]["help"] = "Main directory where files are served from.";
capa["required"]["webroot"]["type"] = "str";
capa["required"]["webroot"]["option"] = "--webroot";
}
void OutHTTPMinimalServer::onHTTP(){
std::string method = H.method;
// determine actual file path for the request
std::string path = resolved_path + H.url.substr(8);
// convert this to a real path with resolved symlinks etc
char *rp = realpath(path.c_str(), 0);
if (rp){
path = rp;
free(rp);
}
if (!rp || path.substr(0, resolved_path.size()) != resolved_path){
if (!rp){
WARN_MSG("URL %s does not exist: %s", H.url.c_str(), path.c_str());
}else{
WARN_MSG("URL %s is not inside webroot %s: %s", H.url.c_str(), resolved_path.c_str(), path.c_str());
}
H.Clean();
H.SetHeader("Server", "mistserver/" PACKAGE_VERSION);
H.setCORSHeaders();
if (method == "OPTIONS" || method == "HEAD"){
H.SendResponse("200", "OK", myConn);
return;
}
H.SetBody("File not found");
H.SendResponse("404", "OK", myConn);
return;
}
char buffer[4096];
std::ifstream inFile(path.c_str());
inFile.seekg(0, std::ios_base::end);
unsigned long long filesize = inFile.tellg();
inFile.seekg(0, std::ios_base::beg);
H.Clean();
H.SetHeader("Server", "mistserver/" PACKAGE_VERSION);
H.SetHeader("Content-Length", filesize);
H.setCORSHeaders();
if (method == "OPTIONS" || method == "HEAD"){
H.SendResponse("200", "OK", myConn);
H.Clean();
return;
}
H.SendResponse("200", "OK", myConn);
while (inFile.good()){
inFile.read(buffer, 4096);
myConn.SendNow(buffer, inFile.gcount());
}
}
}// namespace Mist