mirror of
https://github.com/drogonframework/drogon.git
synced 2025-07-18 00:00:46 -04:00
Compare commits
2 Commits
e1163234cc
...
b37cf6ff97
Author | SHA1 | Date | |
---|---|---|---|
|
b37cf6ff97 | ||
|
171f895975 |
@ -22,11 +22,35 @@ namespace drogon
|
|||||||
{
|
{
|
||||||
namespace plugin
|
namespace plugin
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @brief The RedirectorHandler is a function object that can be registered to
|
||||||
|
* the Redirector plugin. It is used to redirect requests to proper URLs. Users
|
||||||
|
* can modify the protocol, host and path of the request. If a false value is
|
||||||
|
* returned, the request will be considered as invalid and a 404 response will
|
||||||
|
* be sent to the client.
|
||||||
|
*/
|
||||||
using RedirectorHandler =
|
using RedirectorHandler =
|
||||||
std::function<bool(const drogon::HttpRequestPtr &,
|
std::function<bool(const drogon::HttpRequestPtr &,
|
||||||
std::string &, //"http://" or "https://"
|
std::string &, //"http://" or "https://"
|
||||||
std::string &, // host
|
std::string &, // host
|
||||||
bool &)>; // path changed or not
|
bool &)>; // path changed or not
|
||||||
|
/**
|
||||||
|
* @brief The PathRewriteHandler is a function object that can be registered to
|
||||||
|
* the Redirector plugin. It is used to rewrite the path of the request. The
|
||||||
|
* Redirector plugin will call all registered PathRewriteHandlers in the order
|
||||||
|
* of registration. If one or more handlers return true, the request will be
|
||||||
|
* redirected to the new path.
|
||||||
|
*/
|
||||||
|
using PathRewriteHandler = std::function<bool(const drogon::HttpRequestPtr &)>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The ForwardHandler is a function object that can be registered to the
|
||||||
|
* Redirector plugin. It is used to forward the request to next processing steps
|
||||||
|
* in the framework. The Redirector plugin will call all registered
|
||||||
|
* ForwardHandlers in the order of registration. Users can use this handler to
|
||||||
|
* change the request path or any other part of the request.
|
||||||
|
*/
|
||||||
|
using ForwardHandler = std::function<void(const drogon::HttpRequestPtr &)>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This plugin is used to redirect requests to proper URLs. It is a
|
* @brief This plugin is used to redirect requests to proper URLs. It is a
|
||||||
@ -56,18 +80,40 @@ class DROGON_EXPORT Redirector : public drogon::Plugin<Redirector>,
|
|||||||
void initAndStart(const Json::Value &config) override;
|
void initAndStart(const Json::Value &config) override;
|
||||||
void shutdown() override;
|
void shutdown() override;
|
||||||
|
|
||||||
void registerHandler(RedirectorHandler &&handler)
|
void registerRedirectHandler(RedirectorHandler &&handler)
|
||||||
{
|
{
|
||||||
handlers_.emplace_back(std::move(handler));
|
handlers_.emplace_back(std::move(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerHandler(const RedirectorHandler &handler)
|
void registerRedirectHandler(const RedirectorHandler &handler)
|
||||||
{
|
{
|
||||||
handlers_.emplace_back(handler);
|
handlers_.emplace_back(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void registerPathRewriteHandler(PathRewriteHandler &&handler)
|
||||||
|
{
|
||||||
|
pathRewriteHandlers_.emplace_back(std::move(handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerPathRewriteHandler(const PathRewriteHandler &handler)
|
||||||
|
{
|
||||||
|
pathRewriteHandlers_.emplace_back(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerForwardHandler(ForwardHandler &&handler)
|
||||||
|
{
|
||||||
|
forwardHandlers_.emplace_back(std::move(handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerForwardHandler(const ForwardHandler &handler)
|
||||||
|
{
|
||||||
|
forwardHandlers_.emplace_back(handler);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<RedirectorHandler> handlers_;
|
std::vector<RedirectorHandler> handlers_;
|
||||||
|
std::vector<PathRewriteHandler> pathRewriteHandlers_;
|
||||||
|
std::vector<ForwardHandler> forwardHandlers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace plugin
|
} // namespace plugin
|
||||||
|
@ -66,12 +66,10 @@ class DROGON_EXPORT SecureSSLRedirector
|
|||||||
private:
|
private:
|
||||||
bool redirectingAdvice(const HttpRequestPtr &,
|
bool redirectingAdvice(const HttpRequestPtr &,
|
||||||
std::string &,
|
std::string &,
|
||||||
std::string &,
|
std::string &) const;
|
||||||
bool &) const;
|
|
||||||
bool redirectToSSL(const HttpRequestPtr &,
|
bool redirectToSSL(const HttpRequestPtr &,
|
||||||
std::string &,
|
std::string &,
|
||||||
std::string &,
|
std::string &) const;
|
||||||
bool &) const;
|
|
||||||
|
|
||||||
std::regex exemptPegex_;
|
std::regex exemptPegex_;
|
||||||
bool regexFlag_{false};
|
bool regexFlag_{false};
|
||||||
|
@ -37,6 +37,10 @@ void Redirector::initAndStart(const Json::Value &config)
|
|||||||
return HttpResponse::newNotFoundResponse();
|
return HttpResponse::newNotFoundResponse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (auto &handler : thisPtr->pathRewriteHandlers_)
|
||||||
|
{
|
||||||
|
pathChanged |= handler(req);
|
||||||
|
}
|
||||||
if (!protocol.empty() || !host.empty() || pathChanged)
|
if (!protocol.empty() || !host.empty() || pathChanged)
|
||||||
{
|
{
|
||||||
std::string url;
|
std::string url;
|
||||||
@ -48,10 +52,6 @@ void Redirector::initAndStart(const Json::Value &config)
|
|||||||
: "http://";
|
: "http://";
|
||||||
url.append(host);
|
url.append(host);
|
||||||
}
|
}
|
||||||
if (pathChanged)
|
|
||||||
{
|
|
||||||
url.append(req->path());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -64,11 +64,8 @@ void Redirector::initAndStart(const Json::Value &config)
|
|||||||
{
|
{
|
||||||
url.append(req->getHeader("host"));
|
url.append(req->getHeader("host"));
|
||||||
}
|
}
|
||||||
if (pathChanged)
|
|
||||||
{
|
|
||||||
url.append(req->path());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
url.append(req->path());
|
||||||
auto &query = req->query();
|
auto &query = req->query();
|
||||||
if (!query.empty())
|
if (!query.empty())
|
||||||
{
|
{
|
||||||
@ -76,6 +73,10 @@ void Redirector::initAndStart(const Json::Value &config)
|
|||||||
}
|
}
|
||||||
return HttpResponse::newRedirectionResponse(url);
|
return HttpResponse::newRedirectionResponse(url);
|
||||||
}
|
}
|
||||||
|
for (auto &handler : thisPtr->forwardHandlers_)
|
||||||
|
{
|
||||||
|
handler(req);
|
||||||
|
}
|
||||||
return HttpResponsePtr{};
|
return HttpResponsePtr{};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -49,17 +49,18 @@ void SecureSSLRedirector::initAndStart(const Json::Value &config)
|
|||||||
LOG_ERROR << "Redirector plugin is not found!";
|
LOG_ERROR << "Redirector plugin is not found!";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
redirector->registerHandler([weakPtr](const drogon::HttpRequestPtr &req,
|
redirector->registerRedirectHandler(
|
||||||
std::string &protocol,
|
[weakPtr](const drogon::HttpRequestPtr &req,
|
||||||
std::string &host,
|
std::string &protocol,
|
||||||
bool &pathChanged) -> bool {
|
std::string &host,
|
||||||
auto thisPtr = weakPtr.lock();
|
bool &) -> bool {
|
||||||
if (!thisPtr)
|
auto thisPtr = weakPtr.lock();
|
||||||
{
|
if (!thisPtr)
|
||||||
return false;
|
{
|
||||||
}
|
return false;
|
||||||
return thisPtr->redirectingAdvice(req, protocol, host, pathChanged);
|
}
|
||||||
});
|
return thisPtr->redirectingAdvice(req, protocol, host);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecureSSLRedirector::shutdown()
|
void SecureSSLRedirector::shutdown()
|
||||||
@ -69,8 +70,7 @@ void SecureSSLRedirector::shutdown()
|
|||||||
|
|
||||||
bool SecureSSLRedirector::redirectingAdvice(const HttpRequestPtr &req,
|
bool SecureSSLRedirector::redirectingAdvice(const HttpRequestPtr &req,
|
||||||
std::string &protocol,
|
std::string &protocol,
|
||||||
std::string &host,
|
std::string &host) const
|
||||||
bool &pathChanged) const
|
|
||||||
{
|
{
|
||||||
if (req->isOnSecureConnection() || protocol == "https://")
|
if (req->isOnSecureConnection() || protocol == "https://")
|
||||||
{
|
{
|
||||||
@ -85,21 +85,19 @@ bool SecureSSLRedirector::redirectingAdvice(const HttpRequestPtr &req,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return redirectToSSL(req, protocol, host, pathChanged);
|
return redirectToSSL(req, protocol, host);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return redirectToSSL(req, protocol, host, pathChanged);
|
return redirectToSSL(req, protocol, host);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SecureSSLRedirector::redirectToSSL(const HttpRequestPtr &req,
|
bool SecureSSLRedirector::redirectToSSL(const HttpRequestPtr &req,
|
||||||
std::string &protocol,
|
std::string &protocol,
|
||||||
std::string &host,
|
std::string &host) const
|
||||||
bool &pathChanged) const
|
|
||||||
{
|
{
|
||||||
(void)pathChanged;
|
|
||||||
if (!secureHost_.empty())
|
if (!secureHost_.empty())
|
||||||
{
|
{
|
||||||
host = secureHost_;
|
host = secureHost_;
|
||||||
|
@ -66,6 +66,31 @@ static inline void removeExcessiveSlashes(string& url)
|
|||||||
removeDuplicateSlashes(url);
|
removeDuplicateSlashes(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool handleReq(const drogon::HttpRequestPtr& req, int removeMode)
|
||||||
|
{
|
||||||
|
static const std::regex regex(regexes[removeMode - 1]);
|
||||||
|
if (std::regex_match(req->path(), regex))
|
||||||
|
{
|
||||||
|
string newPath = req->path();
|
||||||
|
switch (removeMode)
|
||||||
|
{
|
||||||
|
case trailing:
|
||||||
|
removeTrailingSlashes(newPath);
|
||||||
|
break;
|
||||||
|
case duplicate:
|
||||||
|
removeDuplicateSlashes(newPath);
|
||||||
|
break;
|
||||||
|
case both:
|
||||||
|
default:
|
||||||
|
removeExcessiveSlashes(newPath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
req->setPath(std::move(newPath));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void SlashRemover::initAndStart(const Json::Value& config)
|
void SlashRemover::initAndStart(const Json::Value& config)
|
||||||
{
|
{
|
||||||
trailingSlashes_ = config.get("remove_trailing_slashes", true).asBool();
|
trailingSlashes_ = config.get("remove_trailing_slashes", true).asBool();
|
||||||
@ -81,36 +106,17 @@ void SlashRemover::initAndStart(const Json::Value& config)
|
|||||||
LOG_ERROR << "Redirector plugin is not found!";
|
LOG_ERROR << "Redirector plugin is not found!";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
redirector->registerHandler(
|
auto func = [removeMode](const HttpRequestPtr& req) -> bool {
|
||||||
[removeMode, redirect = redirect_](const HttpRequestPtr& req,
|
return handleReq(req, removeMode);
|
||||||
std::string& protocol,
|
};
|
||||||
std::string& host,
|
if (redirect_)
|
||||||
bool& pathChanged) -> bool {
|
{
|
||||||
static const std::regex regex(regexes[removeMode - 1]);
|
redirector->registerPathRewriteHandler(std::move(func));
|
||||||
if (std::regex_match(req->path(), regex))
|
}
|
||||||
{
|
else
|
||||||
string newPath = req->path();
|
{
|
||||||
switch (removeMode)
|
redirector->registerForwardHandler(std::move(func));
|
||||||
{
|
}
|
||||||
case trailing:
|
|
||||||
removeTrailingSlashes(newPath);
|
|
||||||
break;
|
|
||||||
case duplicate:
|
|
||||||
removeDuplicateSlashes(newPath);
|
|
||||||
break;
|
|
||||||
case both:
|
|
||||||
default:
|
|
||||||
removeExcessiveSlashes(newPath);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
req->setPath(std::move(newPath));
|
|
||||||
if (redirect)
|
|
||||||
{
|
|
||||||
pathChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SlashRemover::shutdown()
|
void SlashRemover::shutdown()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user