1.Add gzip option in config file;

2.rename config example file's name
This commit is contained in:
antao 2018-10-14 11:53:05 +08:00
parent f6c50f2370
commit 93a07ed17a
7 changed files with 357 additions and 326 deletions

View File

@ -2,6 +2,7 @@
*/
{
//ssl:the global ssl files setting
/*
"ssl": {
"cert": "../../trantor/trantor/tests/server.pem",
"key": "../../trantor/trantor/tests/server.pem"
@ -24,7 +25,7 @@
"cert": "",
"key": ""
}
],
],*/
"app": {
//threads_num:num of threads,1 by default
"threads_num": 16,
@ -32,17 +33,30 @@
"enable_session": false,
"session_timeout": 0,
//document_root:Root path of HTTP document,defaut path is ./
"document_root":"./",
"document_root": "./",
/* file_types:
* HTTP download file types,The file types supported by drogon
* by default are "html", "js", "css", "xml", "xsl", "txt", "svg",
* "ttf", "otf", "woff2", "woff" , "eot", "png", "jpg", "jpeg",
* "gif", "bmp", "ico", "icns", etc. */
"file_types":["gif","png","jpg","js","css","html","ico","swf","xap","apk","cur","xml"],
"file_types": [
"gif",
"png",
"jpg",
"js",
"css",
"html",
"ico",
"swf",
"xap",
"apk",
"cur",
"xml"
],
//max_connections:max connections number,100000 by default
"max_connections":100000,
"max_connections": 100000,
//max_connections_per_ip:max connections number per clinet,0 by default which means no limit
"max_connections_per_ip":0,
"max_connections_per_ip": 0,
//Load_dynamic_views: false by default, when set to true, drogon will
//compile and load dynamically "CSP View Files" in directories defined
//by "dynamic_views_path"
@ -51,25 +65,27 @@
//it will be relative path of document_root path
//"dynamic_views_path":["./views"],
//log:set log output,drogon output logs to stdout by default
"log":{
"log": {
//log_path:log file path,empty by default,in which case,log will output to the stdout
"log_path":"./",
"log_path": "./",
//logfile_base_name:log file base name,empty by default which means drogon will name logfile as
//drogon.log ...
"logfile_base_name":"",
"logfile_base_name": "",
//log_size_limit:100000000 bytes by default,
//When the log file size reaches "log_size_limit", the log file will be switched.
"log_size_limit":100000000,
"log_size_limit": 100000000,
//log_level:"DEBUG" by default,options:"TRACE","DEBUG","INFO","WARN"
//The TRACE level is only valid when built in DEBUG mode.
"log_level":"DEBUG"
"log_level": "DEBUG"
},
//run_as_daemon:false by default
"run_as_daemon":false,
"run_as_daemon": false,
//relaunch_on_error:false by default,if true,the program will be restart by parent after exit;
"relaunch_on_error":false,
"relaunch_on_error": false,
//use_sendfile:true by default,if ture,the program will
//use sendfile() system-call to send static file to client;
"use_sendfile":true
"use_sendfile": true,
//use_gzip:true by default,use gzip to compress the response body's content;
"use_gzip": true
}
}

View File

@ -204,7 +204,7 @@ static void newConfigFile(std::ofstream &configFile)
"*/\n"
"{\n"
" //ssl:the global ssl files setting\n"
" \"ssl\": {\n"
" /*\"ssl\": {\n"
" \"cert\": \"../../trantor/trantor/tests/server.pem\",\n"
" \"key\": \"../../trantor/trantor/tests/server.pem\"\n"
" },\n"
@ -226,7 +226,7 @@ static void newConfigFile(std::ofstream &configFile)
" \"cert\": \"\",\n"
" \"key\": \"\"\n"
" }\n"
" ],\n"
" ],*/\n"
" \"app\": {\n"
" //threads_num:num of threads,1 by default\n"
" \"threads_num\": 16,\n"
@ -234,40 +234,45 @@ static void newConfigFile(std::ofstream &configFile)
" \"enable_session\": false,\n"
" \"session_timeout\": 0,\n"
" //document_root:Root path of HTTP document,defaut path is ./\n"
" \"document_root\":\"./\",\n"
" \"document_root\": \"./\",\n"
" /* file_types:\n"
" * HTTP download file types,The file types supported by drogon\n"
" * by default are \"html\", \"js\", \"css\", \"xml\", \"xsl\", \"txt\", \"svg\",\n"
" * \"ttf\", \"otf\", \"woff2\", \"woff\" , \"eot\", \"png\", \"jpg\", \"jpeg\",\n"
" * \"gif\", \"bmp\", \"ico\", \"icns\", etc. */\n"
" \"file_types\":[\"gif\",\"png\",\"jpg\",\"js\",\"css\",\"html\",\"ico\",\"swf\",\"xap\",\"apk\",\"cur\",\"xml\"],\n"
" \"file_types\": [\"gif\",\"png\",\"jpg\",\"js\",\"css\",\"html\",\"ico\",\"swf\",\"xap\",\"apk\",\"cur\",\"xml\"],\n"
" //max_connections:max connections number,100000 by default\n"
" \"max_connections\":100000,\n"
" \"max_connections\": 100000,\n"
" //Load_dynamic_views: false by default, when set to true, drogon will\n"
" //compile and load dynamically \"CSP View Files\" in directories defined\n"
" //by \"dynamic_views_path\"\n"
" \"load_dynamic_views\":true,\n"
" \"load_dynamic_views\": true,\n"
" //dynamic_views_path: if the path isn't prefixed with / or ./,\n"
" //it will be relative path of document_root path\n"
" \"dynamic_views_path\":[\"./views\"],\n"
" \"dynamic_views_path\": [\"./views\"],\n"
" //log:set log output,drogon output logs to stdout by default\n"
" \"log\":{\n"
" \"log\": {\n"
" //log_path:log file path,empty by default,in which case,log will output to the stdout\n"
" \"log_path\":\"./\",\n"
" //logfile_base_name:log file base name,empty by default which means drogon will name logfile as\n"
" \"log_path\": \"./\",\n"
" //logfile_base_name:log file base name,empty by default which means 'drogon' will name logfile as\n"
" //drogon.log ...\n"
" \"logfile_base_name\":\"\",\n"
" \"logfile_base_name\": \"\",\n"
" //log_size_limit:100000000 bytes by default,\n"
" //When the log file size reaches \"log_size_limit\", the log file is switched.\n"
" \"log_size_limit\":100000000\n"
" \"log_size_limit\": 100000000,\n"
" //log_level:\"DEBUG\" by default,options:\"TRACE\",\"DEBUG\",\"INFO\",\"WARN\"\n"
" //The TRACE level is only valid when built in DEBUG mode.\n"
" \"log_level\": \"DEBUG\"\n"
" },\n"
" //run_as_daemon:false by default\n"
" \"run_as_daemon\":false,\n"
" \"run_as_daemon\": false,\n"
" //relaunch_on_error:false by default,if true,the program will be restart by parent after exit;\n"
" \"relaunch_on_error\":false,\n"
" \"relaunch_on_error\": false,\n"
" //use_sendfile:true by default,if ture,the program will\n"
" //use sendfile() system-call to send static file to client;\n"
" \"use_sendfile\":true\n"
" \"use_sendfile\": true,\n"
" //use_gzip:true by default,use gzip to compress the response body's content;\n"
" \"use_gzip\": true\n"
" }\n"
"}\n";
}

View File

@ -140,6 +140,6 @@ int main()
drogon::HttpAppFramework::instance().enableSession(60);
//start app framework
//drogon::HttpAppFramework::instance().enableDynamicViewsLoading({"/tmp/views"});
// drogon::HttpAppFramework::instance().loadConfigFile("../../config.json.example");
drogon::HttpAppFramework::instance().loadConfigFile("../../config.json.example");
drogon::HttpAppFramework::instance().run();
}

View File

@ -39,80 +39,80 @@
#include <vector>
namespace drogon
{
//the drogon banner
const char banner[]= " _ \n"
" __| |_ __ ___ __ _ ___ _ __ \n"
" / _` | '__/ _ \\ / _` |/ _ \\| '_ \\ \n"
"| (_| | | | (_) | (_| | (_) | | | |\n"
" \\__,_|_| \\___/ \\__, |\\___/|_| |_|\n"
" |___/ \n";
inline std::string getVersion()
{
return VERSION;
}
inline std::string getGitCommit()
{
return VERSION_MD5;
}
class HttpAppFramework:public trantor::NonCopyable
{
public:
static HttpAppFramework &instance();
virtual void setThreadNum(size_t threadNum)=0;
virtual void setSSLFiles(const std::string &certPath,
const std::string &keyPath)=0;
virtual void addListener(const std::string &ip,
uint16_t port,
bool useSSL=false,
const std::string & certFile="",
const std::string & keyFile="")=0;
virtual void run()=0;
virtual ~HttpAppFramework();
virtual void registerWebSocketController(const std::string &pathName,
const std::string &crtlName,
const std::vector<std::string> &filters=
std::vector<std::string>())=0;
virtual void registerHttpSimpleController(const std::string &pathName,
const std::string &crtlName,
const std::vector<std::string> &filters=std::vector<std::string>())=0;
template <typename FUNCTION>
static void registerHttpApiMethod(const std::string &pathPattern,
FUNCTION && function,
const std::vector<std::string> &filters=std::vector<std::string>())
{
LOG_TRACE<<"pathPattern:"<<pathPattern;
HttpApiBinderBasePtr binder;
binder=std::make_shared<
HttpApiBinder<FUNCTION>
>(std::forward<FUNCTION>(function));
instance().registerHttpApiController(pathPattern,binder,filters);
}
virtual void enableSession(const size_t timeout=0)=0;
virtual void disableSession()=0;
virtual const std::string & getDocumentRoot() const =0;
virtual void setDocumentRoot(const std::string &rootPath)=0;
virtual void setFileTypes(const std::vector<std::string> &types)=0;
virtual void enableDynamicViewsLoading(const std::vector<std::string> &libPaths)=0;
virtual void setMaxConnectionNum(size_t maxConnections)=0;
virtual void setMaxConnectionNumPerIP(size_t maxConnectionsPerIP)=0;
virtual void loadConfigFile(const std::string &fileName)=0;
virtual void enableRunAsDaemon()=0;
virtual void enableRelaunchOnError()=0;
virtual void setLogPath(const std::string &logPath,
const std::string &logfileBaseName="",
size_t logSize=100000000)=0;
virtual void enableSendfile(bool sendFile)=0;
private:
virtual void registerHttpApiController(const std::string &pathPattern,
const HttpApiBinderBasePtr &binder,
const std::vector<std::string> &filters=std::vector<std::string>())=0;
};
//the drogon banner
const char banner[] = " _ \n"
" __| |_ __ ___ __ _ ___ _ __ \n"
" / _` | '__/ _ \\ / _` |/ _ \\| '_ \\ \n"
"| (_| | | | (_) | (_| | (_) | | | |\n"
" \\__,_|_| \\___/ \\__, |\\___/|_| |_|\n"
" |___/ \n";
inline std::string getVersion()
{
return VERSION;
}
inline std::string getGitCommit()
{
return VERSION_MD5;
}
class HttpAppFramework : public trantor::NonCopyable
{
public:
static HttpAppFramework &instance();
virtual void setThreadNum(size_t threadNum) = 0;
virtual void setSSLFiles(const std::string &certPath,
const std::string &keyPath) = 0;
virtual void addListener(const std::string &ip,
uint16_t port,
bool useSSL = false,
const std::string &certFile = "",
const std::string &keyFile = "") = 0;
virtual void run() = 0;
virtual ~HttpAppFramework();
virtual void registerWebSocketController(const std::string &pathName,
const std::string &crtlName,
const std::vector<std::string> &filters =
std::vector<std::string>()) = 0;
virtual void registerHttpSimpleController(const std::string &pathName,
const std::string &crtlName,
const std::vector<std::string> &filters = std::vector<std::string>()) = 0;
template <typename FUNCTION>
static void registerHttpApiMethod(const std::string &pathPattern,
FUNCTION &&function,
const std::vector<std::string> &filters = std::vector<std::string>())
{
LOG_TRACE << "pathPattern:" << pathPattern;
HttpApiBinderBasePtr binder;
binder = std::make_shared<
HttpApiBinder<FUNCTION>>(std::forward<FUNCTION>(function));
instance().registerHttpApiController(pathPattern, binder, filters);
}
virtual void enableSession(const size_t timeout = 0) = 0;
virtual void disableSession() = 0;
virtual const std::string &getDocumentRoot() const = 0;
virtual void setDocumentRoot(const std::string &rootPath) = 0;
virtual void setFileTypes(const std::vector<std::string> &types) = 0;
virtual void enableDynamicViewsLoading(const std::vector<std::string> &libPaths) = 0;
virtual void setMaxConnectionNum(size_t maxConnections) = 0;
virtual void setMaxConnectionNumPerIP(size_t maxConnectionsPerIP) = 0;
virtual void loadConfigFile(const std::string &fileName) = 0;
virtual void enableRunAsDaemon() = 0;
virtual void enableRelaunchOnError() = 0;
virtual void setLogPath(const std::string &logPath,
const std::string &logfileBaseName = "",
size_t logSize = 100000000) = 0;
virtual void enableSendfile(bool sendFile) = 0;
virtual void enableGzip(bool useGzip) = 0;
virtual bool useGzip() const = 0;
private:
virtual void registerHttpApiController(const std::string &pathPattern,
const HttpApiBinderBasePtr &binder,
const std::vector<std::string> &filters = std::vector<std::string>()) = 0;
};
} // namespace drogon

View File

@ -21,123 +21,123 @@
#include <unistd.h>
using namespace drogon;
ConfigLoader::ConfigLoader(const std::string &configFile) {
if(access(configFile.c_str(),0)!=0)
ConfigLoader::ConfigLoader(const std::string &configFile)
{
if (access(configFile.c_str(), 0) != 0)
{
std::cerr<<"Config file "<<configFile<<" not found!"<<std::endl;
std::cerr << "Config file " << configFile << " not found!" << std::endl;
exit(1);
}
if(access(configFile.c_str(),R_OK)!=0)
if (access(configFile.c_str(), R_OK) != 0)
{
std::cerr<<"No permission to read config file "<<configFile<<std::endl;
std::cerr << "No permission to read config file " << configFile << std::endl;
exit(1);
}
_configFile=configFile;
std::ifstream infile(configFile.c_str(),std::ifstream::in);
if(infile)
_configFile = configFile;
std::ifstream infile(configFile.c_str(), std::ifstream::in);
if (infile)
{
try {
infile>>_configJsonRoot;
try
{
infile >> _configJsonRoot;
}
catch (const std::exception &exception)
{
std::cerr<<"Configuration file format error! in "<<configFile<<":"<<std::endl;
std::cerr<<exception.what()<<std::endl;
std::cerr << "Configuration file format error! in " << configFile << ":" << std::endl;
std::cerr << exception.what() << std::endl;
exit(1);
}
}
}
ConfigLoader::~ConfigLoader() {
ConfigLoader::~ConfigLoader()
{
}
static void loadLogSetting(const Json::Value &log)
{
if(!log)
if (!log)
return;
auto logPath=log.get("log_path","").asString();
if(logPath!="")
auto logPath = log.get("log_path", "").asString();
if (logPath != "")
{
auto baseName=log.get("logfile_base_name","").asString();
auto logSize=log.get("log_size_limit",100000000).asUInt64();
HttpAppFramework::instance().setLogPath(logPath,baseName,logSize);
auto baseName = log.get("logfile_base_name", "").asString();
auto logSize = log.get("log_size_limit", 100000000).asUInt64();
HttpAppFramework::instance().setLogPath(logPath, baseName, logSize);
}
auto logLevel=log.get("log_level","DEBUG").asString();
if(logLevel=="TRACE")
auto logLevel = log.get("log_level", "DEBUG").asString();
if (logLevel == "TRACE")
{
trantor::Logger::setLogLevel(trantor::Logger::TRACE);
}
else if(logLevel=="DEBUG")
else if (logLevel == "DEBUG")
{
trantor::Logger::setLogLevel(trantor::Logger::DEBUG);
}
else if(logLevel=="INFO")
else if (logLevel == "INFO")
{
trantor::Logger::setLogLevel(trantor::Logger::INFO);
}
else if(logLevel=="WARN")
else if (logLevel == "WARN")
{
trantor::Logger::setLogLevel(trantor::Logger::WARN);
}
}
static void loadApp(const Json::Value &app)
{
if(!app)
if (!app)
return;
//threads number
auto threadsNum=app.get("threads_num",1).asUInt64();
auto threadsNum = app.get("threads_num", 1).asUInt64();
HttpAppFramework::instance().setThreadNum(threadsNum);
//session
auto enableSession=app.get("enable_session",false).asBool();
auto timeout=app.get("session_timeout",0).asUInt64();
if(enableSession)
auto enableSession = app.get("enable_session", false).asBool();
auto timeout = app.get("session_timeout", 0).asUInt64();
if (enableSession)
HttpAppFramework::instance().enableSession(timeout);
else
HttpAppFramework::instance().disableSession();
//document root
auto documentRoot=app.get("document_root","").asString();
if(documentRoot!="")
auto documentRoot = app.get("document_root", "").asString();
if (documentRoot != "")
{
HttpAppFramework::instance().setDocumentRoot(documentRoot);
}
//file types
auto fileTypes=app["file_types"];
if(fileTypes.isArray()&&!fileTypes.empty())
auto fileTypes = app["file_types"];
if (fileTypes.isArray() && !fileTypes.empty())
{
std::vector<std::string> types;
for(auto fileType:fileTypes)
for (auto fileType : fileTypes)
{
types.push_back(fileType.asString());
LOG_TRACE<<"file type:"<<types.back();
LOG_TRACE << "file type:" << types.back();
}
HttpAppFramework::instance().setFileTypes(types);
}
//max connections
auto maxConns=app.get("max_connections",0).asUInt64();
if(maxConns>0)
auto maxConns = app.get("max_connections", 0).asUInt64();
if (maxConns > 0)
{
HttpAppFramework::instance().setMaxConnectionNum(maxConns);
}
//max connections per IP
auto maxConnsPerIP=app.get("max_connections_per_ip",0).asUInt64();
if(maxConnsPerIP>0)
auto maxConnsPerIP = app.get("max_connections_per_ip", 0).asUInt64();
if (maxConnsPerIP > 0)
{
HttpAppFramework::instance().setMaxConnectionNumPerIP(maxConnsPerIP);
}
//dynamic views
auto enableDynamicViews=app.get("load_dynamic_views",false).asBool();
if(enableDynamicViews)
auto enableDynamicViews = app.get("load_dynamic_views", false).asBool();
if (enableDynamicViews)
{
auto viewsPaths=app["dynamic_views_path"];
if(viewsPaths.isArray()&&viewsPaths.size()>0)
auto viewsPaths = app["dynamic_views_path"];
if (viewsPaths.isArray() && viewsPaths.size() > 0)
{
std::vector<std::string> paths;
for(auto viewsPath:viewsPaths)
for (auto viewsPath : viewsPaths)
{
paths.push_back(viewsPath.asString());
LOG_TRACE<<"views path:"<<paths.back();
LOG_TRACE << "views path:" << paths.back();
}
HttpAppFramework::instance().enableDynamicViewsLoading(paths);
}
@ -145,45 +145,48 @@ static void loadApp(const Json::Value &app)
//log
loadLogSetting(app["log"]);
//run as daemon
auto runAsDaemon=app.get("run_as_daemon",false).asBool();
if(runAsDaemon)
auto runAsDaemon = app.get("run_as_daemon", false).asBool();
if (runAsDaemon)
{
HttpAppFramework::instance().enableRunAsDaemon();
}
//relaunch
auto relaunch=app.get("relaunch_on_error",false).asBool();
if(relaunch)
auto relaunch = app.get("relaunch_on_error", false).asBool();
if (relaunch)
{
HttpAppFramework::instance().enableRelaunchOnError();
}
auto useSendfile=app.get("use_sendfile",true).asBool();
auto useSendfile = app.get("use_sendfile", true).asBool();
HttpAppFramework::instance().enableSendfile(useSendfile);
auto useGzip = app.get("use_gzip", true).asBool();
HttpAppFramework::instance().enableGzip(useGzip);
}
static void loadListeners(const Json::Value &listeners)
{
if(!listeners)
if (!listeners)
return;
LOG_TRACE<<"Has "<<listeners.size()<<" listeners";
for(auto listener:listeners)
LOG_TRACE << "Has " << listeners.size() << " listeners";
for (auto listener : listeners)
{
auto addr=listener.get("address","0.0.0.0").asString();
auto port=(uint16_t)listener.get("port",0).asUInt();
auto useSSL=listener.get("https",false).asBool();
auto cert=listener.get("cert","").asString();
auto key=listener.get("key","").asString();
LOG_TRACE<<"Add listener:"<<addr<<":"<<port;
HttpAppFramework::instance().addListener(addr,port,useSSL,cert,key);
auto addr = listener.get("address", "0.0.0.0").asString();
auto port = (uint16_t)listener.get("port", 0).asUInt();
auto useSSL = listener.get("https", false).asBool();
auto cert = listener.get("cert", "").asString();
auto key = listener.get("key", "").asString();
LOG_TRACE << "Add listener:" << addr << ":" << port;
HttpAppFramework::instance().addListener(addr, port, useSSL, cert, key);
}
}
static void loadSSL(const Json::Value &sslFiles)
{
if(!sslFiles)
if (!sslFiles)
return;
auto key=sslFiles.get("key","").asString();
auto cert=sslFiles.get("cert","").asString();
HttpAppFramework::instance().setSSLFiles(cert,key);
auto key = sslFiles.get("key", "").asString();
auto cert = sslFiles.get("cert", "").asString();
HttpAppFramework::instance().setSSLFiles(cert, key);
}
void ConfigLoader::load() {
void ConfigLoader::load()
{
//std::cout<<_configJsonRoot<<std::endl;
loadApp(_configJsonRoot["app"]);
loadSSL(_configJsonRoot["ssl"]);

View File

@ -29,160 +29,166 @@
namespace drogon
{
class HttpAppFrameworkImpl:public HttpAppFramework
class HttpAppFrameworkImpl : public HttpAppFramework
{
public:
HttpAppFrameworkImpl() : _connectionNum(0)
{
public:
HttpAppFrameworkImpl():
_connectionNum(0)
{
}
virtual void addListener(const std::string &ip,
uint16_t port,
bool useSSL=false,
const std::string & certFile="",
const std::string & keyFile="") override;
virtual void setThreadNum(size_t threadNum) override;
virtual void setSSLFiles(const std::string &certPath,
const std::string &keyPath) override;
virtual void run() override ;
virtual void registerWebSocketController(const std::string &pathName,
const std::string &crtlName,
const std::vector<std::string> &filters=
std::vector<std::string>())override ;
virtual void registerHttpSimpleController(const std::string &pathName,
const std::string &crtlName,
const std::vector<std::string> &filters=
std::vector<std::string>())override ;
virtual void enableSession(const size_t timeout=0) override { _useSession=true;_sessionTimeout=timeout;}
virtual void disableSession() override { _useSession=false;}
virtual const std::string & getDocumentRoot() const override {return _rootPath;}
virtual void setDocumentRoot(const std::string &rootPath) override {_rootPath=rootPath;}
virtual void setFileTypes(const std::vector<std::string> &types) override;
virtual void enableDynamicViewsLoading(const std::vector<std::string> &libPaths) override;
virtual void setMaxConnectionNum(size_t maxConnections) override;
virtual void setMaxConnectionNumPerIP(size_t maxConnectionsPerIP) override;
virtual void loadConfigFile(const std::string &fileName) override;
virtual void enableRunAsDaemon() override {_runAsDaemon=true;}
virtual void enableRelaunchOnError() override {_relaunchOnError=true;}
virtual void setLogPath(const std::string &logPath,
const std::string &logfileBaseName="",
size_t logfileSize=100000000) override;
virtual void enableSendfile(bool sendFile) override {_useSendfile=sendFile;}
~HttpAppFrameworkImpl(){
//Destroy the following objects before _loop destruction
_sharedLibManagerPtr.reset();
_sessionMapPtr.reset();
}
}
virtual void addListener(const std::string &ip,
uint16_t port,
bool useSSL = false,
const std::string &certFile = "",
const std::string &keyFile = "") override;
virtual void setThreadNum(size_t threadNum) override;
virtual void setSSLFiles(const std::string &certPath,
const std::string &keyPath) override;
virtual void run() override;
virtual void registerWebSocketController(const std::string &pathName,
const std::string &crtlName,
const std::vector<std::string> &filters =
std::vector<std::string>()) override;
virtual void registerHttpSimpleController(const std::string &pathName,
const std::string &crtlName,
const std::vector<std::string> &filters =
std::vector<std::string>()) override;
virtual void enableSession(const size_t timeout = 0) override
{
_useSession = true;
_sessionTimeout = timeout;
}
virtual void disableSession() override { _useSession = false; }
virtual const std::string &getDocumentRoot() const override { return _rootPath; }
virtual void setDocumentRoot(const std::string &rootPath) override { _rootPath = rootPath; }
virtual void setFileTypes(const std::vector<std::string> &types) override;
virtual void enableDynamicViewsLoading(const std::vector<std::string> &libPaths) override;
virtual void setMaxConnectionNum(size_t maxConnections) override;
virtual void setMaxConnectionNumPerIP(size_t maxConnectionsPerIP) override;
virtual void loadConfigFile(const std::string &fileName) override;
virtual void enableRunAsDaemon() override { _runAsDaemon = true; }
virtual void enableRelaunchOnError() override { _relaunchOnError = true; }
virtual void setLogPath(const std::string &logPath,
const std::string &logfileBaseName = "",
size_t logfileSize = 100000000) override;
virtual void enableSendfile(bool sendFile) override { _useSendfile = sendFile; }
virtual void enableGzip(bool useGzip) override { _useGzip = useGzip; }
virtual bool useGzip() const override { return _useGzip; }
~HttpAppFrameworkImpl()
{
//Destroy the following objects before _loop destruction
_sharedLibManagerPtr.reset();
_sessionMapPtr.reset();
}
trantor::EventLoop *loop();
private:
virtual void registerHttpApiController(const std::string &pathPattern,
const HttpApiBinderBasePtr &binder,
const std::vector<std::string> &filters=std::vector<std::string>()) override ;
trantor::EventLoop *loop();
std::vector<std::tuple<std::string,uint16_t,bool,std::string,std::string>> _listeners;
void onAsyncRequest(const HttpRequestPtr& req,const std::function<void (const HttpResponsePtr &)> & callback);
void onNewWebsockRequest(const HttpRequestPtr& req,
const std::function<void (const HttpResponsePtr &)> & callback,
const WebSocketConnectionPtr &wsConnPtr);
void onWebsockMessage(const WebSocketConnectionPtr &wsConnPtr,trantor::MsgBuffer *buffer);
void onWebsockDisconnect(const WebSocketConnectionPtr &wsConnPtr);
void onConnection(const TcpConnectionPtr &conn);
void readSendFile(const std::string& filePath,const HttpRequestPtr& req,const HttpResponsePtr resp);
void addApiPath(const std::string &path,
const HttpApiBinderBasePtr &binder,
const std::vector<std::string> &filters);
void initRegex();
//if uuid package found,we can use a uuid string as session id;
//set _sessionTimeout=0 to make location session valid forever based on cookies;
size_t _sessionTimeout= 0;
bool _useSession= false;
typedef std::shared_ptr<Session> SessionPtr;
std::unique_ptr<CacheMap<std::string,SessionPtr>> _sessionMapPtr;
private:
virtual void registerHttpApiController(const std::string &pathPattern,
const HttpApiBinderBasePtr &binder,
const std::vector<std::string> &filters = std::vector<std::string>()) override;
std::unique_ptr<CacheMap<std::string,HttpResponsePtr>> _responseCacheMap;
std::vector<std::tuple<std::string, uint16_t, bool, std::string, std::string>> _listeners;
void onAsyncRequest(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback);
void onNewWebsockRequest(const HttpRequestPtr &req,
const std::function<void(const HttpResponsePtr &)> &callback,
const WebSocketConnectionPtr &wsConnPtr);
void onWebsockMessage(const WebSocketConnectionPtr &wsConnPtr, trantor::MsgBuffer *buffer);
void onWebsockDisconnect(const WebSocketConnectionPtr &wsConnPtr);
void onConnection(const TcpConnectionPtr &conn);
void readSendFile(const std::string &filePath, const HttpRequestPtr &req, const HttpResponsePtr resp);
void addApiPath(const std::string &path,
const HttpApiBinderBasePtr &binder,
const std::vector<std::string> &filters);
void initRegex();
//if uuid package found,we can use a uuid string as session id;
//set _sessionTimeout=0 to make location session valid forever based on cookies;
size_t _sessionTimeout = 0;
bool _useSession = false;
typedef std::shared_ptr<Session> SessionPtr;
std::unique_ptr<CacheMap<std::string, SessionPtr>> _sessionMapPtr;
void doFilters(const std::vector<std::string> &filters,
const HttpRequestPtr& req,
const std::function<void (const HttpResponsePtr &)> & callback,
std::unique_ptr<CacheMap<std::string, HttpResponsePtr>> _responseCacheMap;
void doFilters(const std::vector<std::string> &filters,
const HttpRequestPtr &req,
const std::function<void(const HttpResponsePtr &)> &callback,
bool needSetJsessionid,
const std::string &session_id,
const std::function<void()> &missCallback);
void doFilterChain(const std::shared_ptr<std::queue<std::shared_ptr<HttpFilterBase>>> &chain,
const HttpRequestPtr &req,
const std::function<void(const HttpResponsePtr &)> &callback,
bool needSetJsessionid,
const std::string &session_id,
const std::function<void ()> &missCallback);
void doFilterChain(const std::shared_ptr<std::queue<std::shared_ptr<HttpFilterBase>>> &chain,
const HttpRequestPtr& req,
const std::function<void (const HttpResponsePtr &)> & callback,
bool needSetJsessionid,
const std::string &session_id,
const std::function<void ()> &missCallback);
//
struct ControllerAndFiltersName
{
std::string controllerName;
std::vector<std::string> filtersName;
std::shared_ptr<HttpSimpleControllerBase> controller;
std::weak_ptr<HttpResponse> responsePtr;
std::mutex _mutex;
};
std::unordered_map<std::string,ControllerAndFiltersName>_simpCtrlMap;
std::mutex _simpCtrlMutex;
struct WSCtrlAndFiltersName
{
WebSocketControllerBasePtr controller;
std::vector<std::string> filtersName;
};
std::unordered_map<std::string,WSCtrlAndFiltersName> _websockCtrlMap;
std::mutex _websockCtrlMutex;
struct ApiBinder
{
std::string pathParameterPattern;
std::vector<size_t> parameterPlaces;
std::map<std::string,size_t> queryParametersPlaces;
HttpApiBinderBasePtr binderPtr;
std::vector<std::string> filtersName;
std::unique_ptr <std::mutex> binderMtx=std::unique_ptr<std::mutex>(new std::mutex);
std::weak_ptr<HttpResponse> responsePtr;
};
//std::unordered_map<std::string,ApiBinder>_apiCtrlMap;
std::vector<ApiBinder>_apiCtrlVector;
std::mutex _apiCtrlMutex;
std::regex _apiRegex;
bool _enableLastModify=true;
std::set<std::string> _fileTypeSet={"html","js","css","xml","xsl","txt","svg","ttf",
"otf","woff2","woff","eot","png","jpg","jpeg",
"gif","bmp","ico","icns"};
std::string _rootPath="./";
std::atomic_bool _running;
//tool funcs
size_t _threadNum=1;
std::vector<std::string> _libFilePaths;
std::unique_ptr<SharedLibManager>_sharedLibManagerPtr;
trantor::EventLoop _loop;
std::string _sslCertPath;
std::string _sslKeyPath;
size_t _maxConnectionNum=100000;
size_t _maxConnectionNumPerIP=0;
std::atomic<uint64_t> _connectionNum;
std::unordered_map<std::string,size_t> _connectionsNumMap;
std::mutex _connectionsNumMapMutex;
bool _runAsDaemon=false;
bool _relaunchOnError=false;
std::string _logPath="";
std::string _logfileBaseName="";
size_t _logfileSize=100000000;
bool _useSendfile=true;
const std::function<void()> &missCallback);
//
struct ControllerAndFiltersName
{
std::string controllerName;
std::vector<std::string> filtersName;
std::shared_ptr<HttpSimpleControllerBase> controller;
std::weak_ptr<HttpResponse> responsePtr;
std::mutex _mutex;
};
}
std::unordered_map<std::string, ControllerAndFiltersName> _simpCtrlMap;
std::mutex _simpCtrlMutex;
struct WSCtrlAndFiltersName
{
WebSocketControllerBasePtr controller;
std::vector<std::string> filtersName;
};
std::unordered_map<std::string, WSCtrlAndFiltersName> _websockCtrlMap;
std::mutex _websockCtrlMutex;
struct ApiBinder
{
std::string pathParameterPattern;
std::vector<size_t> parameterPlaces;
std::map<std::string, size_t> queryParametersPlaces;
HttpApiBinderBasePtr binderPtr;
std::vector<std::string> filtersName;
std::unique_ptr<std::mutex> binderMtx = std::unique_ptr<std::mutex>(new std::mutex);
std::weak_ptr<HttpResponse> responsePtr;
};
//std::unordered_map<std::string,ApiBinder>_apiCtrlMap;
std::vector<ApiBinder> _apiCtrlVector;
std::mutex _apiCtrlMutex;
std::regex _apiRegex;
bool _enableLastModify = true;
std::set<std::string> _fileTypeSet = {"html", "js", "css", "xml", "xsl", "txt", "svg", "ttf",
"otf", "woff2", "woff", "eot", "png", "jpg", "jpeg",
"gif", "bmp", "ico", "icns"};
std::string _rootPath = "./";
std::atomic_bool _running;
//tool funcs
size_t _threadNum = 1;
std::vector<std::string> _libFilePaths;
std::unique_ptr<SharedLibManager> _sharedLibManagerPtr;
trantor::EventLoop _loop;
std::string _sslCertPath;
std::string _sslKeyPath;
size_t _maxConnectionNum = 100000;
size_t _maxConnectionNumPerIP = 0;
std::atomic<uint64_t> _connectionNum;
std::unordered_map<std::string, size_t> _connectionsNumMap;
std::mutex _connectionsNumMapMutex;
bool _runAsDaemon = false;
bool _relaunchOnError = false;
std::string _logPath = "";
std::string _logfileBaseName = "";
size_t _logfileSize = 100000000;
bool _useSendfile = true;
bool _useGzip = true;
};
} // namespace drogon

View File

@ -179,11 +179,12 @@ void HttpServer::onRequest(const TcpConnectionPtr &conn, const HttpRequestPtr &r
response->setBody(std::string());
auto &sendfileName = std::dynamic_pointer_cast<HttpResponseImpl>(response)->sendfileName();
auto newResp = response;
if (sendfileName.empty() &&
response->getContentTypeCode() < CT_APPLICATION_OCTET_STREAM &&
response->getBody().length() > 1024 &&
if (HttpAppFramework::instance().useGzip() &&
sendfileName.empty() &&
req->getHeader("Accept-Encoding").find("gzip") != std::string::npos &&
response->getHeader("Content-Encoding") == "")
response->getHeader("Content-Encoding") == "" &&
response->getContentTypeCode() < CT_APPLICATION_OCTET_STREAM &&
response->getBody().length() > 1024)
{
//use gzip
LOG_TRACE << "Use gzip to compress the body";