Add the GlobalFilters plugin (#1555)
This commit is contained in:
parent
d133b21804
commit
c7912f246b
|
@ -287,6 +287,7 @@ set(DROGON_SOURCES
|
|||
lib/src/PluginsManager.cc
|
||||
lib/src/RangeParser.cc
|
||||
lib/src/SecureSSLRedirector.cc
|
||||
lib/src/GlobalFilters.cc
|
||||
lib/src/AccessLogger.cc
|
||||
lib/src/RealIpResolver.cc
|
||||
lib/src/SessionManager.cc
|
||||
|
@ -729,7 +730,9 @@ set(DROGON_PLUGIN_HEADERS
|
|||
lib/inc/drogon/plugins/SecureSSLRedirector.h
|
||||
lib/inc/drogon/plugins/AccessLogger.h
|
||||
lib/inc/drogon/plugins/RealIpResolver.h
|
||||
lib/inc/drogon/plugins/Hodor.h)
|
||||
lib/inc/drogon/plugins/Hodor.h
|
||||
lib/inc/drogon/plugins/GlobalFilters.h)
|
||||
|
||||
install(FILES ${DROGON_PLUGIN_HEADERS}
|
||||
DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/plugins)
|
||||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
|
||||
#include <drogon/plugins/Plugin.h>
|
||||
#include <regex>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <drogon/HttpFilter.h>
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
namespace plugin
|
||||
{
|
||||
/**
|
||||
* @brif This plugin is used to add global filters to all HTTP requests.
|
||||
* The json configuration is as follows:
|
||||
*
|
||||
* @code
|
||||
{
|
||||
"name": "drogon::plugin::GlobalFilters",
|
||||
"dependencies": [],
|
||||
"config": {
|
||||
// filters: the list of global filter names.
|
||||
"filters": [
|
||||
"FilterName1", "FilterName2",...
|
||||
],
|
||||
// exempt: exempt must be a string or string array, regular
|
||||
expressions for
|
||||
// URLs that don't have to be filtered.
|
||||
"exempt": [
|
||||
"^/static/.*\\.css", "^/images/.*",...
|
||||
]
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
*
|
||||
*/
|
||||
class GlobalFilters : public drogon::Plugin<GlobalFilters>,
|
||||
public std::enable_shared_from_this<GlobalFilters>
|
||||
{
|
||||
public:
|
||||
GlobalFilters() = default;
|
||||
void initAndStart(const Json::Value &config) override;
|
||||
void shutdown() override;
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<drogon::HttpFilterBase>> filters_;
|
||||
std::regex exemptPegex_;
|
||||
bool regexFlag_{false};
|
||||
};
|
||||
} // namespace plugin
|
||||
} // namespace drogon
|
|
@ -9,6 +9,7 @@
|
|||
#include <drogon/drogon_callbacks.h>
|
||||
#include <drogon/plugins/Plugin.h>
|
||||
#include <regex>
|
||||
#include <memory>
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
|
@ -32,8 +33,12 @@ namespace plugin
|
|||
}
|
||||
@endcode
|
||||
*
|
||||
* ssl_redirect_exempt: a regular expression (for matching the path of a
|
||||
* request) list for URLs that don't have to be redirected.
|
||||
* ssl_redirect_exempt: must be a string or a string array, present a regular
|
||||
expression
|
||||
* (for matching the path of a request) or a regular expression list for URLs
|
||||
that don't
|
||||
* have to be redirected.
|
||||
*
|
||||
* secure_ssl_host: If this string is not empty, all SSL redirects
|
||||
* will be directed to this host rather than the originally-requested host.
|
||||
*
|
||||
|
@ -42,7 +47,8 @@ namespace plugin
|
|||
*
|
||||
*/
|
||||
class DROGON_EXPORT SecureSSLRedirector
|
||||
: public drogon::Plugin<SecureSSLRedirector>
|
||||
: public drogon::Plugin<SecureSSLRedirector>,
|
||||
public std::enable_shared_from_this<SecureSSLRedirector>
|
||||
{
|
||||
public:
|
||||
SecureSSLRedirector()
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
#include <drogon/plugins/GlobalFilters.h>
|
||||
#include <drogon/DrClassMap.h>
|
||||
#include <drogon/HttpAppFramework.h>
|
||||
#include "FiltersFunction.h"
|
||||
#include "HttpRequestImpl.h"
|
||||
|
||||
using namespace drogon::plugin;
|
||||
|
||||
void GlobalFilters::initAndStart(const Json::Value &config)
|
||||
{
|
||||
if (config.isMember("filters") && config["filters"].isArray())
|
||||
{
|
||||
auto &filters = config["filters"];
|
||||
|
||||
for (auto const &filter : filters)
|
||||
{
|
||||
if (filter.isString())
|
||||
{
|
||||
auto filterPtr = std::dynamic_pointer_cast<HttpFilterBase>(
|
||||
drogon::DrClassMap::getSingleInstance(filter.asString()));
|
||||
if (filterPtr)
|
||||
{
|
||||
filters_.push_back(filterPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR << "Filter " << filter.asString()
|
||||
<< " not found!";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (config.isMember("exempt"))
|
||||
{
|
||||
auto exempt = config["exempt"];
|
||||
if (exempt.isArray())
|
||||
{
|
||||
std::string regexStr;
|
||||
for (auto const &ex : exempt)
|
||||
{
|
||||
if (ex.isString())
|
||||
{
|
||||
regexStr.append("(").append(exempt.asString()).append(")|");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR << "exempt must be a string array!";
|
||||
}
|
||||
}
|
||||
if (!regexStr.empty())
|
||||
{
|
||||
regexStr.pop_back();
|
||||
exemptPegex_ = std::regex(regexStr);
|
||||
regexFlag_ = true;
|
||||
}
|
||||
}
|
||||
else if (exempt.isString())
|
||||
{
|
||||
exemptPegex_ = std::regex(exempt.asString());
|
||||
regexFlag_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR << "exempt must be a string or string array!";
|
||||
}
|
||||
}
|
||||
std::weak_ptr<GlobalFilters> weakPtr = shared_from_this();
|
||||
drogon::app().registerPreRoutingAdvice(
|
||||
[weakPtr](const drogon::HttpRequestPtr &req,
|
||||
drogon::AdviceCallback &&acb,
|
||||
drogon::AdviceChainCallback &&accb) {
|
||||
auto thisPtr = weakPtr.lock();
|
||||
if (!thisPtr)
|
||||
{
|
||||
accb();
|
||||
return;
|
||||
}
|
||||
if (thisPtr->regexFlag_)
|
||||
{
|
||||
if (std::regex_match(req->path(), thisPtr->exemptPegex_))
|
||||
{
|
||||
accb();
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto callbackPtr =
|
||||
std::make_shared<std::function<void(const HttpResponsePtr &)>>(
|
||||
std::move(acb));
|
||||
drogon::filters_function::doFilters(
|
||||
thisPtr->filters_,
|
||||
std::static_pointer_cast<HttpRequestImpl>(req),
|
||||
callbackPtr,
|
||||
std::move(accb));
|
||||
});
|
||||
}
|
||||
void GlobalFilters::shutdown()
|
||||
{
|
||||
filters_.clear();
|
||||
}
|
|
@ -12,8 +12,9 @@ using namespace drogon::plugin;
|
|||
|
||||
void SecureSSLRedirector::initAndStart(const Json::Value &config)
|
||||
{
|
||||
if (config.isMember("ssl_redirect_exempt") &&
|
||||
config["ssl_redirect_exempt"].isArray())
|
||||
if (config.isMember("ssl_redirect_exempt"))
|
||||
{
|
||||
if (config["ssl_redirect_exempt"].isArray())
|
||||
{
|
||||
std::string regexString;
|
||||
for (auto &exempt : config["ssl_redirect_exempt"])
|
||||
|
@ -28,9 +29,26 @@ void SecureSSLRedirector::initAndStart(const Json::Value &config)
|
|||
regexFlag_ = true;
|
||||
}
|
||||
}
|
||||
else if (config["ssl_redirect_exempt"].isString())
|
||||
{
|
||||
exemptPegex_ = std::regex(config["ssl_redirect_exempt"].asString());
|
||||
regexFlag_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR
|
||||
<< "ssl_redirect_exempt must be a string or string array!";
|
||||
}
|
||||
}
|
||||
secureHost_ = config.get("secure_ssl_host", "").asString();
|
||||
app().registerSyncAdvice([this](const HttpRequestPtr &req) {
|
||||
return this->redirectingAdvice(req);
|
||||
std::weak_ptr<SecureSSLRedirector> weakPtr = shared_from_this();
|
||||
app().registerSyncAdvice([weakPtr](const HttpRequestPtr &req) {
|
||||
auto thisPtr = weakPtr.lock();
|
||||
if (!thisPtr)
|
||||
{
|
||||
return HttpResponsePtr{};
|
||||
}
|
||||
return thisPtr->redirectingAdvice(req);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue