Add options for 'Server' header and 'Date' header (#202)

This commit is contained in:
An Tao 2019-07-31 19:44:32 +08:00 committed by GitHub
parent 4f942602ce
commit ba7d788184
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 103 additions and 37 deletions

View File

@ -142,9 +142,15 @@
//idle_connection_timeout: Defaults to 60 seconds, the lifetime
//of the connection without read or write
"idle_connection_timeout": 60,
//server_header_field: Set the 'server' header field in each response sent by drogon,
//empty string by default with which the 'server' header field is set to "Server: drogon/version string\r\n"
//server_header_field: Set the 'Server' header field in each response sent by drogon,
//empty string by default with which the 'Server' header field is set to "Server: drogon/version string\r\n"
"server_header_field": "",
//enable_server_header: Set true to force drogon to add a 'Server' header to each HTTP response. The default
//value is true.
"enable_server_header": true,
//enable_date_header: Set true to force drogon to add a 'Date' header to each HTTP response. The default
//value is true.
"enable_date_header": true,
//keepalive_requests: Set the maximum number of requests that can be served through one keep-alive connection.
//After the maximum number of requests are made, the connection is closed.
//The default value of 0 means no limit.
@ -179,7 +185,6 @@
"config": {
"heartbeat_interval": 2
}
}],
//custom_config: custom configuration for users. This object can be get by the app().getCustomConfig() method.
"custom_config": {}

View File

@ -142,9 +142,15 @@
//idle_connection_timeout: Defaults to 60 seconds, the lifetime
//of the connection without read or write
"idle_connection_timeout": 60,
//server_header_field: Set the 'server' header field in each response sent by drogon,
//empty string by default with which the 'server' header field is set to "Server: drogon/version string\r\n"
//server_header_field: Set the 'Server' header field in each response sent by drogon,
//empty string by default with which the 'Server' header field is set to "Server: drogon/version string\r\n"
"server_header_field": "",
//enable_server_header: Set true to force drogon to add a 'Server' header to each HTTP response. The default
//value is true.
"enable_server_header": true,
//enable_date_header: Set true to force drogon to add a 'Date' header to each HTTP response. The default
//value is true.
"enable_date_header": true,
//keepalive_requests: Set the maximum number of requests that can be served through one keep-alive connection.
//After the maximum number of requests are made, the connection is closed.
//The default value of 0 means no limit.
@ -179,7 +185,6 @@
"config": {
"heartbeat_interval": 2
}
}],
//custom_config: custom configuration for users. This object can be get by the app().getCustomConfig() method.
"custom_config": {}

4
examples/simple_example/TimeFilter.cc Executable file → Normal file
View File

@ -11,7 +11,7 @@ void TimeFilter::doFilter(const HttpRequestPtr &req,
trantor::Date now = trantor::Date::date();
if (!req->session())
{
//no session support by framework,pls enable session
// no session support by framework,pls enable session
auto resp = HttpResponse::newNotFoundResponse();
cb(resp);
return;
@ -24,7 +24,7 @@ void TimeFilter::doFilter(const HttpRequestPtr &req,
LOG_TRACE << "update visitDate";
if (now > lastDate.after(10))
{
//10 sec later can visit again;
// 10 sec later can visit again;
ccb();
return;
}

View File

@ -714,6 +714,16 @@ class HttpAppFramework : public trantor::NonCopyable
*/
virtual void setServerHeaderField(const std::string &server) = 0;
/// Control if the 'Server' header or the 'Date' header is added to each
/// HTTP response.
/**
* NOTE:
* These operations can be performed by options in the configuration file.
* The headers are sent to clients by default.
*/
virtual void enableServerHeader(bool flag) = 0;
virtual void enableDateHeader(bool flag) = 0;
/// Set the maximum number of requests that can be served through one
/// keep-alive connection.
/**

View File

@ -301,6 +301,10 @@ static void loadApp(const Json::Value &app)
auto server = app.get("server_header_field", "").asString();
if (!server.empty())
drogon::app().setServerHeaderField(server);
auto sendServerHeader = app.get("enable_server_header", true).asBool();
drogon::app().enableServerHeader(sendServerHeader);
auto sendDateHeader = app.get("enable_date_header", true).asBool();
drogon::app().enableDateHeader(sendDateHeader);
auto keepaliveReqs = app.get("keepalive_requests", 0).asUInt64();
drogon::app().setKeepaliveRequestsNumber(keepaliveReqs);
auto pipeliningReqs = app.get("pipelining_requests", 0).asUInt64();

View File

@ -338,6 +338,22 @@ class HttpAppFrameworkImpl : public HttpAppFramework
_serverHeader = "Server: " + server + "\r\n";
}
virtual void enableServerHeader(bool flag) override
{
_enableServerHeader = flag;
}
virtual void enableDateHeader(bool flag) override
{
_enableDateHeader = flag;
}
bool sendServerHeader() const
{
return _enableServerHeader;
}
bool sendDateHeader() const
{
return _enableDateHeader;
}
const std::string &getServerHeaderString() const
{
return _serverHeader;
@ -460,6 +476,8 @@ class HttpAppFrameworkImpl : public HttpAppFramework
HttpResponsePtr _custom404;
orm::DbClientManager _dbClientManager;
static InitBeforeMainFunction _initFirst;
bool _enableServerHeader = true;
bool _enableDateHeader = true;
std::vector<std::function<bool(const trantor::InetAddress &,
const trantor::InetAddress &)>>
_newConnectionAdvices;

View File

@ -191,34 +191,46 @@ void HttpResponseImpl::makeHeaderString(
headerStringPtr->append(it->second);
headerStringPtr->append("\r\n");
}
headerStringPtr->append(
HttpAppFrameworkImpl::instance().getServerHeaderString());
if (HttpAppFrameworkImpl::instance().sendServerHeader())
{
headerStringPtr->append(
HttpAppFrameworkImpl::instance().getServerHeaderString());
}
}
std::shared_ptr<std::string> HttpResponseImpl::renderToString() const
{
if (_expriedTime >= 0)
{
if (_datePos != std::string::npos)
if (drogon::HttpAppFrameworkImpl::instance().sendDateHeader())
{
auto now = trantor::Date::now();
bool isDateChanged = ((now.microSecondsSinceEpoch() /
MICRO_SECONDS_PRE_SEC) != _httpStringDate);
assert(_httpString);
if (isDateChanged)
if (_datePos != std::string::npos)
{
_httpStringDate =
now.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC;
auto newDate = utils::getHttpFullDate(now);
auto now = trantor::Date::now();
bool isDateChanged =
((now.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC) !=
_httpStringDate);
assert(_httpString);
if (isDateChanged)
{
_httpStringDate =
now.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC;
auto newDate = utils::getHttpFullDate(now);
_httpString = std::make_shared<std::string>(*_httpString);
memcpy((void *)&(*_httpString)[_datePos],
newDate,
strlen(newDate));
return _httpString;
}
_httpString = std::make_shared<std::string>(*_httpString);
memcpy((void *)&(*_httpString)[_datePos],
newDate,
strlen(newDate));
return _httpString;
}
return _httpString;
}
else
{
if (_httpString)
return _httpString;
}
}
auto httpString = std::make_shared<std::string>();
@ -242,16 +254,23 @@ std::shared_ptr<std::string> HttpResponseImpl::renderToString() const
}
// output Date header
httpString->append("Date: ");
auto datePos = httpString->length();
httpString->append(utils::getHttpFullDate(trantor::Date::date()));
httpString->append("\r\n\r\n");
if (drogon::HttpAppFrameworkImpl::instance().sendDateHeader())
{
httpString->append("Date: ");
auto datePos = httpString->length();
httpString->append(utils::getHttpFullDate(trantor::Date::date()));
httpString->append("\r\n\r\n");
_datePos = datePos;
}
else
{
httpString->append("\r\n");
}
LOG_TRACE << "reponse(no body):" << httpString->c_str();
httpString->append(*_bodyPtr);
if (_expriedTime >= 0)
{
_datePos = datePos;
_httpString = httpString;
}
return httpString;
@ -280,9 +299,16 @@ std::shared_ptr<std::string> HttpResponseImpl::renderHeaderForHeadMethod() const
}
// output Date header
httpString->append("Date: ");
httpString->append(utils::getHttpFullDate(trantor::Date::date()));
httpString->append("\r\n\r\n");
if (drogon::HttpAppFrameworkImpl::instance().sendDateHeader())
{
httpString->append("Date: ");
httpString->append(utils::getHttpFullDate(trantor::Date::date()));
httpString->append("\r\n\r\n");
}
else
{
httpString->append("\r\n");
}
return httpString;
}

View File

@ -47,8 +47,7 @@ int MultiPartParser::parse(const HttpRequestPtr &req)
if (req->method() != Post)
return -1;
const std::string &contentType =
static_cast<HttpRequestImpl *>(req.get())->getHeaderBy(
"content-type");
static_cast<HttpRequestImpl *>(req.get())->getHeaderBy("content-type");
if (contentType.empty())
{
return -1;

View File

@ -124,8 +124,7 @@ void StaticFileRouter::route(
{
// make a copy
auto newCachedResp = std::make_shared<HttpResponseImpl>(
*static_cast<HttpResponseImpl *>(
cachedResp.get()));
*static_cast<HttpResponseImpl *>(cachedResp.get()));
newCachedResp->addCookie("JSESSIONID", sessionId);
newCachedResp->setExpiredTime(-1);
callback(newCachedResp);