forked from drogonframework/drogon
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add the SecureSSLRedirector plugin (drogonframework#306)
- Loading branch information
Showing
11 changed files
with
194 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/** | ||
* | ||
* drogon_plugin_SecureSSLRedirector.h | ||
* | ||
*/ | ||
|
||
#pragma once | ||
#include <drogon/drogon_callbacks.h> | ||
#include <drogon/plugins/Plugin.h> | ||
#include <regex> | ||
|
||
namespace drogon | ||
{ | ||
namespace plugin | ||
{ | ||
/** | ||
* @brief This plugin is used to redirect all non-HTTPS requests to HTTPS | ||
* (except for those URLs matching a regular expression listed in | ||
* the 'ssl_redirect_exempt' list). | ||
* | ||
* The json configuration is as follows: | ||
* | ||
* @code | ||
{ | ||
"name": "drogon::plugin::SecureSSLRedirector", | ||
"dependencies": [], | ||
"config": { | ||
"ssl_redirect_exempt": ["^/.*\\.jpg", ...], | ||
"secure_ssl_host": "localhost:8849" | ||
} | ||
} | ||
@endcode | ||
* | ||
* ssl_redirect_exempt: a regular expression (for matching the path of a | ||
* request) 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. | ||
* | ||
* Enable the plugin by adding the configuration to the list of plugins in the | ||
* configuration file. | ||
* | ||
*/ | ||
class SecureSSLRedirector : public drogon::Plugin<SecureSSLRedirector> | ||
{ | ||
public: | ||
SecureSSLRedirector() | ||
{ | ||
} | ||
/// This method must be called by drogon to initialize and start the plugin. | ||
/// It must be implemented by the user. | ||
virtual void initAndStart(const Json::Value &config) override; | ||
|
||
/// This method must be called by drogon to shutdown the plugin. | ||
/// It must be implemented by the user. | ||
virtual void shutdown() override; | ||
|
||
private: | ||
HttpResponsePtr redirectingAdvice(const HttpRequestPtr &) const; | ||
HttpResponsePtr redirectToSSL(const HttpRequestPtr &) const; | ||
|
||
std::regex exemptPegex_; | ||
bool regexFlag_{false}; | ||
std::string secureHost_; | ||
}; | ||
|
||
} // namespace plugin | ||
} // namespace drogon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/** | ||
* | ||
* drogon_plugin_SecureSSLRedirector.cc | ||
* | ||
*/ | ||
#include <drogon/drogon.h> | ||
#include <drogon/plugins/SecureSSLRedirector.h> | ||
#include <string> | ||
|
||
using namespace drogon; | ||
using namespace drogon::plugin; | ||
|
||
void SecureSSLRedirector::initAndStart(const Json::Value &config) | ||
{ | ||
if (config.isMember("ssl_redirect_exempt") && | ||
config["ssl_redirect_exempt"].isArray()) | ||
{ | ||
std::string regexString; | ||
for (auto &exempt : config["ssl_redirect_exempt"]) | ||
{ | ||
assert(exempt.isString()); | ||
regexString.append("(").append(exempt.asString()).append(")|"); | ||
} | ||
if (!regexString.empty()) | ||
{ | ||
regexString.resize(regexString.length() - 1); | ||
exemptPegex_ = std::regex(regexString); | ||
regexFlag_ = true; | ||
} | ||
} | ||
secureHost_ = config.get("secure_ssl_host", "").asString(); | ||
app().registerSyncAdvice([this](const HttpRequestPtr &req) { | ||
return this->redirectingAdvice(req); | ||
}); | ||
} | ||
|
||
void SecureSSLRedirector::shutdown() | ||
{ | ||
/// Shutdown the plugin | ||
} | ||
|
||
HttpResponsePtr SecureSSLRedirector::redirectingAdvice( | ||
const HttpRequestPtr &req) const | ||
{ | ||
if (req->isOnSecureConnection()) | ||
{ | ||
return HttpResponsePtr{}; | ||
} | ||
else if (regexFlag_) | ||
{ | ||
std::smatch regexResult; | ||
if (std::regex_match(req->path(), regexResult, exemptPegex_)) | ||
{ | ||
return HttpResponsePtr{}; | ||
} | ||
else | ||
{ | ||
return redirectToSSL(req); | ||
} | ||
} | ||
else | ||
{ | ||
return redirectToSSL(req); | ||
} | ||
} | ||
|
||
HttpResponsePtr SecureSSLRedirector::redirectToSSL( | ||
const HttpRequestPtr &req) const | ||
{ | ||
if (!secureHost_.empty()) | ||
{ | ||
static std::string urlPrefix{"https://" + secureHost_}; | ||
std::string query{urlPrefix + req->path()}; | ||
if (!req->query().empty()) | ||
{ | ||
query += "?" + req->query(); | ||
} | ||
return HttpResponse::newRedirectionResponse(query); | ||
} | ||
else | ||
{ | ||
const auto &host = req->getHeader("host"); | ||
if (!host.empty()) | ||
{ | ||
std::string query{"https://" + host}; | ||
query += req->path(); | ||
if (!req->query().empty()) | ||
{ | ||
query += "?" + req->query(); | ||
} | ||
return HttpResponse::newRedirectionResponse(query); | ||
} | ||
else | ||
{ | ||
return HttpResponse::newNotFoundResponse(); | ||
} | ||
} | ||
} |
Submodule trantor
updated
2 files
+5 −0 | trantor/net/TcpConnection.h | |
+4 −0 | trantor/net/ssl/SSLConnection.h |