Removed the templating engine and most of the routing and controller logic from drogon.

This commit is contained in:
Relintai 2021-06-20 15:04:18 +02:00
parent 1dfd747b41
commit d2b0ff2e22
35 changed files with 109 additions and 2750 deletions

View File

@ -1,130 +0,0 @@
/**
*
* @file DrClassMap.h
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include <drogon/exports.h>
#include <trantor/utils/Logger.h>
#include <cstdlib>
#include <functional>
#include <memory>
#include <mutex>
#include <thread>
#include <type_traits>
#include <unordered_map>
#include <vector>
#ifndef _MSC_VER
#include <cxxabi.h>
#endif
#include <stdio.h>
namespace drogon {
class DrObjectBase;
using DrAllocFunc = std::function<DrObjectBase *()>;
/**
* @brief A map class which can create DrObjects from names.
*/
class DROGON_EXPORT DrClassMap {
public:
/**
* @brief Register a class into the map
*
* @param className The name of the class
* @param func The function which can create a new instance of the class.
*/
static void registerClass(const std::string &className,
const DrAllocFunc &func);
/**
* @brief Create a new instance of the class named by className
*
* @param className The name of the class
* @return DrObjectBase* The pointer to the newly created instance.
*/
static DrObjectBase *newObject(const std::string &className);
/**
* @brief Get the singleton object of the class named by className
*
* @param className The name of the class
* @return const std::shared_ptr<DrObjectBase>& The smart pointer to the
* instance.
*/
static const std::shared_ptr<DrObjectBase> &getSingleInstance(
const std::string &className);
/**
* @brief Get the singleton T type object
*
* @tparam T The type of the class
* @return std::shared_ptr<T> The smart pointer to the instance.
* @note The T must be a subclass of the DrObjectBase class.
*/
template <typename T>
static std::shared_ptr<T> getSingleInstance() {
static_assert(std::is_base_of<DrObjectBase, T>::value,
"T must be a sub-class of DrObjectBase");
static auto const singleton =
std::dynamic_pointer_cast<T>(getSingleInstance(T::classTypeName()));
assert(singleton);
return singleton;
}
/**
* @brief Set a singleton object into the map.
*
* @param ins The smart pointer to the instance.
*/
static void setSingleInstance(const std::shared_ptr<DrObjectBase> &ins);
/**
* @brief Get all names of classes registered in the map.
*
* @return std::vector<std::string> the vector of class names.
*/
static std::vector<std::string> getAllClassName();
/**
* @brief demangle the type name which is returned by typeid(T).name().
*
* @param mangled_name The type name which is returned by typeid(T).name().
* @return std::string The human readable type name.
*/
static std::string demangle(const char *mangled_name) {
#ifndef _MSC_VER
std::size_t len = 0;
int status = 0;
std::unique_ptr<char, decltype(&std::free)> ptr(
__cxxabiv1::__cxa_demangle(mangled_name, nullptr, &len, &status),
&std::free);
if (status == 0) {
return std::string(ptr.get());
}
LOG_ERROR << "Demangle error!";
return "";
#else
auto pos = strstr(mangled_name, " ");
if (pos == nullptr)
return std::string{ mangled_name };
else
return std::string{ pos + 1 };
#endif
}
protected:
static std::unordered_map<std::string, DrAllocFunc> &getMap();
};
} // namespace drogon

View File

@ -1,108 +0,0 @@
/**
*
* @file DrObject.h
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include <drogon/DrClassMap.h>
#include <drogon/exports.h>
#include <string>
#include <type_traits>
#ifdef _MSC_VER
#pragma warning(disable : 4250)
#endif
namespace drogon {
/**
* @brief The base class for all drogon reflection classes.
*
*/
class DROGON_EXPORT DrObjectBase {
public:
/**
* @brief Get the class name
*
* @return const std::string& the class name
*/
virtual const std::string &className() const {
static const std::string name{ "DrObjectBase" };
return name;
}
/**
* @brief Return true if the class name is 'class_name'
*/
virtual bool isClass(const std::string &class_name) const {
return (className() == class_name);
}
virtual ~DrObjectBase() {
}
};
/**
* a class template to
* implement the reflection function of creating the class object by class name
*/
template <typename T>
class DrObject : public virtual DrObjectBase {
public:
virtual const std::string &className() const override {
return alloc_.className();
}
static const std::string &classTypeName() {
return alloc_.className();
}
virtual bool isClass(const std::string &class_name) const override {
return (className() == class_name);
}
protected:
// protect constructor to make this class only inheritable
DrObject() = default;
~DrObject() override = default;
private:
class DrAllocator {
public:
DrAllocator() {
registerClass<T>();
}
const std::string &className() const {
static std::string className =
DrClassMap::demangle(typeid(T).name());
return className;
}
template <typename D>
typename std::enable_if<std::is_default_constructible<D>::value,
void>::type
registerClass() {
DrClassMap::registerClass(className(),
[]() -> DrObjectBase * { return new T; });
}
template <typename D>
typename std::enable_if<!std::is_default_constructible<D>::value,
void>::type
registerClass() {
}
};
// use static val to register allocator function for class T;
static DrAllocator alloc_;
};
template <typename T>
typename DrObject<T>::DrAllocator DrObject<T>::alloc_;
} // namespace drogon

View File

@ -1,27 +0,0 @@
/**
*
* DrTemplate.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include <drogon/DrObject.h>
#include <drogon/DrTemplateBase.h>
namespace drogon {
template <typename T>
class DrTemplate : public DrObject<T>, public DrTemplateBase {
protected:
DrTemplate() {
}
};
} // namespace drogon

View File

@ -1,56 +0,0 @@
/**
*
* @file DrTemplateBase.h
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include <drogon/DrObject.h>
#include <drogon/HttpViewData.h>
#include <drogon/exports.h>
#include <memory>
#include <string>
namespace drogon {
using DrTemplateData = HttpViewData;
/// The templating engine class
/**
* This class can generate a text string from the template file and template
* data.
* For more details on the template file, see the wiki site (the 'View' section)
*/
class DROGON_EXPORT DrTemplateBase : public virtual DrObjectBase {
public:
/// Create an object of the implementation class
/**
* @param templateName represents the name of the template file. A template
* file is a description file with a special format. Its extension is
* usually .csp. The user should preprocess the template file with the
* drogon_ctl tool to create c++ source files.
*/
static std::shared_ptr<DrTemplateBase> newTemplate(
const std::string &templateName);
/// Generate the text string
/**
* @param data represents data rendered in the string in a format
* according to the template file.
*/
virtual std::string genText(
const DrTemplateData &data = DrTemplateData()) = 0;
virtual ~DrTemplateBase(){};
DrTemplateBase(){};
};
} // namespace drogon

View File

@ -15,14 +15,11 @@
#pragma once
#include <drogon/CacheMap.h>
#include <drogon/DrObject.h>
#include <drogon/HttpBinder.h>
#include <drogon/HttpRequest.h>
#include <drogon/HttpResponse.h>
#include <drogon/IntranetIpFilter.h>
#include <drogon/LocalHostFilter.h>
#include <drogon/MultiPart.h>
#include <drogon/NotFound.h>
#include <drogon/drogon_callbacks.h>
#include <drogon/exports.h>
#include <drogon/plugins/Plugin.h>
@ -431,6 +428,8 @@ public:
std::vector<internal::HttpConstraint>{},
const std::string &handlerName = "") {
LOG_TRACE << "pathPattern:" << pathPattern;
/*
auto binder = std::make_shared<internal::HttpBinder<FUNCTION> >(
std::forward<FUNCTION>(function));
@ -449,8 +448,10 @@ public:
exit(1);
}
}
registerHttpController(
pathPattern, binder, validMethods, filters, handlerName);
*/
//registerHttpController(
// pathPattern, binder, validMethods, filters, handlerName);
return *this;
}
/**
@ -476,11 +477,13 @@ public:
std::vector<internal::HttpConstraint>{},
const std::string &handlerName = "") {
LOG_TRACE << "regex:" << regExp;
/*
internal::HttpBinderBasePtr binder;
binder = std::make_shared<internal::HttpBinder<FUNCTION> >(
std::forward<FUNCTION>(function));
*/
std::vector<HttpMethod> validMethods;
std::vector<std::string> filters;
for (auto const &filterOrMethod : filtersAndMethods) {
@ -494,8 +497,8 @@ public:
exit(1);
}
}
registerHttpControllerViaRegex(
regExp, binder, validMethods, filters, handlerName);
// registerHttpControllerViaRegex(
// regExp, binder, validMethods, filters, handlerName);
return *this;
}
@ -548,8 +551,11 @@ public:
"Controllers created and initialized "
"automatically by drogon cannot be "
"registered here");
DrClassMap::setSingleInstance(ctrlPtr);
//DrClassMap::setSingleInstance(ctrlPtr);
T::initPathRouting();
return *this;
}
@ -565,7 +571,7 @@ public:
"Filters created and initialized "
"automatically by drogon cannot be "
"registered here");
DrClassMap::setSingleInstance(filterPtr);
//DrClassMap::setSingleInstance(filterPtr);
return *this;
}
@ -1230,6 +1236,7 @@ public:
virtual const ExceptionHandler &getExceptionHandler() const = 0;
private:
/*
virtual void registerHttpController(
const std::string &pathPattern,
const internal::HttpBinderBasePtr &binder,
@ -1241,7 +1248,7 @@ private:
const internal::HttpBinderBasePtr &binder,
const std::vector<HttpMethod> &validMethods,
const std::vector<std::string> &filters,
const std::string &handlerName) = 0;
const std::string &handlerName) = 0;*/
};
/// A wrapper of the instance() method

View File

@ -1,381 +0,0 @@
/**
*
* @file HttpBinder.h
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
/// The classes in the file are internal tool classes. Do not include this
/// file directly and use any of these classes directly.
#pragma once
#include <drogon/DrClassMap.h>
#include <drogon/DrObject.h>
#include <drogon/HttpRequest.h>
#include <drogon/exports.h>
#include <drogon/utils/FunctionTraits.h>
#include <deque>
#include <memory>
#include <sstream>
#include <string>
namespace drogon {
namespace internal {
// we only accept value type or const lreference type or right reference type as
// the handle method parameters type
template <typename T>
struct BinderArgTypeTraits {
static const bool isValid = true;
};
template <typename T>
struct BinderArgTypeTraits<T *> {
static const bool isValid = false;
};
template <typename T>
struct BinderArgTypeTraits<T &> {
static const bool isValid = false;
};
template <typename T>
struct BinderArgTypeTraits<T &&> {
static const bool isValid = true;
};
template <typename T>
struct BinderArgTypeTraits<const T &&> {
static const bool isValid = false;
};
template <typename T>
struct BinderArgTypeTraits<const T &> {
static const bool isValid = true;
};
class HttpBinderBase {
public:
virtual void handleHttpRequest(
std::deque<std::string> &pathArguments,
const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback) = 0;
virtual size_t paramCount() = 0;
virtual const std::string &handlerName() const = 0;
virtual ~HttpBinderBase() {
}
};
template <typename T>
T &getControllerObj() {
// Initialization of function-local statics is guaranteed to occur only once
// even when
// called from multiple threads, and may be more efficient than the
// equivalent code using std::call_once.
static T obj;
return obj;
}
DROGON_EXPORT void handleException(
const std::exception &,
const HttpRequestPtr &,
std::function<void(const HttpResponsePtr &)> &&);
using HttpBinderBasePtr = std::shared_ptr<HttpBinderBase>;
template <typename FUNCTION>
class HttpBinder : public HttpBinderBase {
public:
using traits = FunctionTraits<FUNCTION>;
using FunctionType = FUNCTION;
void handleHttpRequest(
std::deque<std::string> &pathArguments,
const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback) override {
run(pathArguments, req, std::move(callback));
}
size_t paramCount() override {
return traits::arity;
}
HttpBinder(FUNCTION &&func) :
func_(std::forward<FUNCTION>(func)) {
static_assert(traits::isHTTPFunction,
"Your API handler function interface is wrong!");
handlerName_ = DrClassMap::demangle(typeid(FUNCTION).name());
}
void test() {
std::cout << "argument_count=" << argument_count << " "
<< traits::isHTTPFunction << std::endl;
}
const std::string &handlerName() const override {
return handlerName_;
}
template <bool isClassFunction = traits::isClassFunction,
bool isDrObjectClass = traits::isDrObjectClass>
typename std::enable_if<isDrObjectClass && isClassFunction, void>::type
createHandlerInstance() {
auto objPtr =
DrClassMap::getSingleInstance<typename traits::class_type>();
LOG_TRACE << "create handler class object: " << objPtr.get();
}
template <bool isClassFunction = traits::isClassFunction,
bool isDrObjectClass = traits::isDrObjectClass>
typename std::enable_if<!isDrObjectClass && isClassFunction, void>::type
createHandlerInstance() {
auto &obj = getControllerObj<typename traits::class_type>();
LOG_TRACE << "create handler class object: " << &obj;
}
template <bool isClassFunction = traits::isClassFunction>
typename std::enable_if<!isClassFunction, void>::type
createHandlerInstance() {
}
private:
FUNCTION func_;
template <std::size_t Index>
using nth_argument_type = typename traits::template argument<Index>;
static const size_t argument_count = traits::arity;
std::string handlerName_;
template <typename T>
struct CanConvertFromStringStream {
private:
using yes = std::true_type;
using no = std::false_type;
template <typename U>
static auto test(U *p, std::stringstream &&ss)
-> decltype((ss >> *p), yes());
template <typename>
static no test(...);
public:
static constexpr bool value =
std::is_same<decltype(test<T>(nullptr, std::stringstream())),
yes>::value;
};
template <typename T>
typename std::enable_if<CanConvertFromStringStream<T>::value, void>::type
getHandlerArgumentValue(T &value, std::string &&p) {
if (!p.empty()) {
std::stringstream ss(std::move(p));
ss >> value;
}
}
template <typename T>
typename std::enable_if<!(CanConvertFromStringStream<T>::value), void>::type
getHandlerArgumentValue(T &value, std::string &&p) {
}
void getHandlerArgumentValue(std::string &value, std::string &&p) {
value = std::move(p);
}
void getHandlerArgumentValue(int &value, std::string &&p) {
value = std::stoi(p);
}
void getHandlerArgumentValue(long &value, std::string &&p) {
value = std::stol(p);
}
void getHandlerArgumentValue(long long &value, std::string &&p) {
value = std::stoll(p);
}
void getHandlerArgumentValue(unsigned long &value, std::string &&p) {
value = std::stoul(p);
}
void getHandlerArgumentValue(unsigned long long &value, std::string &&p) {
value = std::stoull(p);
}
void getHandlerArgumentValue(float &value, std::string &&p) {
value = std::stof(p);
}
void getHandlerArgumentValue(double &value, std::string &&p) {
value = std::stod(p);
}
void getHandlerArgumentValue(long double &value, std::string &&p) {
value = std::stold(p);
}
template <typename... Values, std::size_t Boundary = argument_count>
typename std::enable_if<(sizeof...(Values) < Boundary), void>::type run(
std::deque<std::string> &pathArguments,
const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
Values &&...values) {
// Call this function recursively until parameter's count equals to the
// count of target function parameters
static_assert(
BinderArgTypeTraits<nth_argument_type<sizeof...(Values)> >::isValid,
"your handler argument type must be value type or const left "
"reference type or right reference type");
using ValueType =
typename std::remove_cv<typename std::remove_reference<
nth_argument_type<sizeof...(Values)> >::type>::type;
ValueType value = ValueType();
if (!pathArguments.empty()) {
std::string v = std::move(pathArguments.front());
pathArguments.pop_front();
try {
if (v.empty() == false)
getHandlerArgumentValue(value, std::move(v));
} catch (const std::exception &e) {
handleException(e, req, std::move(callback));
return;
}
} else {
try {
value = req->as<ValueType>();
} catch (const std::exception &e) {
handleException(e, req, std::move(callback));
return;
} catch (...) {
LOG_ERROR << "Exception not derived from std::exception";
return;
}
}
run(pathArguments,
req,
std::move(callback),
std::forward<Values>(values)...,
std::move(value));
}
template <typename... Values,
std::size_t Boundary = argument_count,
bool isCoroutine = traits::isCoroutine>
typename std::enable_if<(sizeof...(Values) == Boundary) && !isCoroutine,
void>::type
run(std::deque<std::string> &,
const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
Values &&...values) {
try {
// Explcit copy because `callFunction` moves it
auto cb = callback;
callFunction(req, cb, std::move(values)...);
} catch (const std::exception &except) {
handleException(except, req, std::move(callback));
} catch (...) {
LOG_ERROR << "Exception not derived from std::exception";
return;
}
}
#ifdef __cpp_impl_coroutine
template <typename... Values,
std::size_t Boundary = argument_count,
bool isCoroutine = traits::isCoroutine>
typename std::enable_if<(sizeof...(Values) == Boundary) && isCoroutine,
void>::type
run(std::deque<std::string> &,
const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
Values &&...values) {
[this](HttpRequestPtr req,
std::function<void(const HttpResponsePtr &)> callback,
Values &&...values) -> AsyncTask {
try {
if constexpr (std::is_same_v<AsyncTask,
typename traits::return_type>) {
// Explcit copy because `callFunction` moves it
auto cb = callback;
callFunction(req, cb, std::move(values)...);
} else if constexpr (std::is_same_v<Task<>,
typename traits::return_type>) {
// Explcit copy because `callFunction` moves it
auto cb = callback;
co_await callFunction(req, cb, std::move(values)...);
} else if constexpr (std::is_same_v<Task<HttpResponsePtr>,
typename traits::return_type>) {
auto resp =
co_await callFunction(req, std::move(values)...);
callback(std::move(resp));
}
} catch (const std::exception &except) {
handleException(except, req, std::move(callback));
} catch (...) {
LOG_ERROR << "Exception not derived from std::exception";
}
}(req, std::move(callback), std::move(values)...);
}
#endif
template <typename... Values,
bool isClassFunction = traits::isClassFunction,
bool isDrObjectClass = traits::isDrObjectClass,
bool isNormal = std::is_same<typename traits::first_param_type,
HttpRequestPtr>::value>
typename std::enable_if<isClassFunction && !isDrObjectClass && isNormal,
typename traits::return_type>::type
callFunction(const HttpRequestPtr &req, Values &&...values) {
static auto &obj = getControllerObj<typename traits::class_type>();
return (obj.*func_)(req, std::move(values)...);
}
template <typename... Values,
bool isClassFunction = traits::isClassFunction,
bool isDrObjectClass = traits::isDrObjectClass,
bool isNormal = std::is_same<typename traits::first_param_type,
HttpRequestPtr>::value>
typename std::enable_if<isClassFunction && isDrObjectClass && isNormal,
typename traits::return_type>::type
callFunction(const HttpRequestPtr &req, Values &&...values) {
static auto objPtr =
DrClassMap::getSingleInstance<typename traits::class_type>();
return (*objPtr.*func_)(req, std::move(values)...);
}
template <typename... Values,
bool isClassFunction = traits::isClassFunction,
bool isNormal = std::is_same<typename traits::first_param_type,
HttpRequestPtr>::value>
typename std::enable_if<!isClassFunction && isNormal,
typename traits::return_type>::type
callFunction(const HttpRequestPtr &req, Values &&...values) {
return func_(req, std::move(values)...);
}
template <typename... Values,
bool isClassFunction = traits::isClassFunction,
bool isDrObjectClass = traits::isDrObjectClass,
bool isNormal = std::is_same<typename traits::first_param_type,
HttpRequestPtr>::value>
typename std::enable_if<isClassFunction && !isDrObjectClass && !isNormal,
typename traits::return_type>::type
callFunction(const HttpRequestPtr &req, Values &&...values) {
static auto &obj = getControllerObj<typename traits::class_type>();
return (obj.*func_)((*req), std::move(values)...);
}
template <typename... Values,
bool isClassFunction = traits::isClassFunction,
bool isDrObjectClass = traits::isDrObjectClass,
bool isNormal = std::is_same<typename traits::first_param_type,
HttpRequestPtr>::value>
typename std::enable_if<isClassFunction && isDrObjectClass && !isNormal,
typename traits::return_type>::type
callFunction(const HttpRequestPtr &req, Values &&...values) {
static auto objPtr =
DrClassMap::getSingleInstance<typename traits::class_type>();
return (*objPtr.*func_)((*req), std::move(values)...);
}
template <typename... Values,
bool isClassFunction = traits::isClassFunction,
bool isNormal = std::is_same<typename traits::first_param_type,
HttpRequestPtr>::value>
typename std::enable_if<!isClassFunction && !isNormal,
typename traits::return_type>::type
callFunction(const HttpRequestPtr &req, Values &&...values) {
return func_((*req), std::move(values)...);
}
};
} // namespace internal
} // namespace drogon

View File

@ -14,7 +14,6 @@
*/
#pragma once
#include "drogon/HttpBinder.h"
#include <drogon/HttpRequest.h>
#include <drogon/HttpResponse.h>
#include <drogon/HttpTypes.h>

View File

@ -1,132 +0,0 @@
/**
*
* HttpController.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include <drogon/DrObject.h>
#include <drogon/HttpAppFramework.h>
#include <drogon/utils/HttpConstraint.h>
#include <trantor/utils/Logger.h>
#include <iostream>
#include <string>
#include <vector>
/// For more details on the class, see the wiki site (the 'HttpController'
/// section)
#define METHOD_LIST_BEGIN \
static void initPathRouting() {
#define METHOD_ADD(method, pattern, ...) \
registerMethod(&method, pattern, { __VA_ARGS__ }, true, #method)
#define ADD_METHOD_TO(method, path_pattern, ...) \
registerMethod(&method, path_pattern, { __VA_ARGS__ }, false, #method)
#define ADD_METHOD_VIA_REGEX(method, regex, ...) \
registerMethodViaRegex(&method, regex, { __VA_ARGS__ }, #method)
#define METHOD_LIST_END \
return; \
}
namespace drogon {
/**
* @brief The base class for HTTP controllers.
*
*/
class HttpControllerBase {
};
/**
* @brief The reflection base class template for HTTP controllers
*
* @tparam T the type of the implementation class
* @tparam AutoCreation The flag for automatically creating, user can set this
* flag to false for classes that have nondefault constructors.
*/
template <typename T, bool AutoCreation = true>
class HttpController : public DrObject<T>, public HttpControllerBase {
public:
static const bool isAutoCreation = AutoCreation;
protected:
template <typename FUNCTION>
static void registerMethod(
FUNCTION &&function,
const std::string &pattern,
const std::vector<internal::HttpConstraint> &filtersAndMethods =
std::vector<internal::HttpConstraint>{},
bool classNameInPath = true,
const std::string &handlerName = "") {
if (classNameInPath) {
std::string path = "/";
path.append(HttpController<T>::classTypeName());
LOG_TRACE << "classname:" << HttpController<T>::classTypeName();
// transform(path.begin(), path.end(), path.begin(), tolower);
std::string::size_type pos;
while ((pos = path.find("::")) != std::string::npos) {
path.replace(pos, 2, "/");
}
if (pattern.empty() || pattern[0] == '/')
app().registerHandler(path + pattern,
std::forward<FUNCTION>(function),
filtersAndMethods,
handlerName);
else
app().registerHandler(path + "/" + pattern,
std::forward<FUNCTION>(function),
filtersAndMethods,
handlerName);
} else {
std::string path = pattern;
if (path.empty() || path[0] != '/') {
path = "/" + path;
}
app().registerHandler(path,
std::forward<FUNCTION>(function),
filtersAndMethods,
handlerName);
}
}
template <typename FUNCTION>
static void registerMethodViaRegex(
FUNCTION &&function,
const std::string &regExp,
const std::vector<internal::HttpConstraint> &filtersAndMethods =
std::vector<internal::HttpConstraint>{},
const std::string &handlerName = "") {
app().registerHandlerViaRegex(regExp,
std::forward<FUNCTION>(function),
filtersAndMethods,
handlerName);
}
private:
class methodRegistrator {
public:
methodRegistrator() {
if (AutoCreation)
T::initPathRouting();
}
};
// use static value to register controller method in framework before
// main();
static methodRegistrator registrator_;
virtual void *touch() {
return &registrator_;
}
};
template <typename T, bool AutoCreation>
typename HttpController<T, AutoCreation>::methodRegistrator
HttpController<T, AutoCreation>::registrator_;
} // namespace drogon

View File

@ -14,7 +14,6 @@
#pragma once
#include <drogon/DrObject.h>
#include <drogon/HttpRequest.h>
#include <drogon/HttpResponse.h>
#include <drogon/drogon_callbacks.h>
@ -25,7 +24,7 @@ namespace drogon {
* @brief The abstract base class for filters
* For more details on the class, see the wiki site (the 'Filter' section)
*/
class DROGON_EXPORT HttpFilterBase : public virtual DrObjectBase {
class DROGON_EXPORT HttpFilterBase {
public:
/// This virtual function should be overrided in subclasses.
/**
@ -53,7 +52,7 @@ public:
* flag to false for classes that have nondefault constructors.
*/
template <typename T, bool AutoCreation = true>
class HttpFilter : public DrObject<T>, public HttpFilterBase {
class HttpFilter : public HttpFilterBase {
public:
static constexpr bool isAutoCreation{ AutoCreation };
virtual ~HttpFilter() {

View File

@ -15,7 +15,6 @@
#pragma once
#include <drogon/Attribute.h>
#include <drogon/DrClassMap.h>
#include <drogon/HttpTypes.h>
#include <drogon/Session.h>
#include <drogon/UploadFile.h>
@ -38,8 +37,8 @@ using HttpRequestPtr = std::shared_ptr<HttpRequest>;
*/
template <typename T>
T fromRequest(const HttpRequest &req) {
LOG_ERROR << "You must specialize the fromRequest template for the type of "
<< DrClassMap::demangle(typeid(T).name());
LOG_ERROR << "You must specialize the fromRequest template for the type of ";
// << DrClassMap::demangle(typeid(T).name());
exit(1);
}
@ -50,8 +49,8 @@ T fromRequest(const HttpRequest &req) {
*/
template <typename T>
HttpRequestPtr toRequest(T &&) {
LOG_ERROR << "You must specialize the toRequest template for the type of "
<< DrClassMap::demangle(typeid(T).name());
LOG_ERROR << "You must specialize the toRequest template for the type of ";
// << DrClassMap::demangle(typeid(T).name());
exit(1);
}

View File

@ -14,7 +14,6 @@
#pragma once
#include <drogon/Cookie.h>
#include <drogon/DrClassMap.h>
#include <drogon/HttpTypes.h>
#include <drogon/HttpViewData.h>
#include <drogon/exports.h>
@ -35,8 +34,8 @@ using HttpResponsePtr = std::shared_ptr<HttpResponse>;
template <typename T>
T fromResponse(const HttpResponse &resp) {
LOG_ERROR
<< "You must specialize the fromResponse template for the type of "
<< DrClassMap::demangle(typeid(T).name());
<< "You must specialize the fromResponse template for the type of ";
//<< DrClassMap::demangle(typeid(T).name());
exit(1);
}
@ -47,8 +46,8 @@ T fromResponse(const HttpResponse &resp) {
*/
template <typename T>
HttpResponsePtr toResponse(T &&) {
LOG_ERROR << "You must specialize the toResponse template for the type of "
<< DrClassMap::demangle(typeid(T).name());
LOG_ERROR << "You must specialize the toResponse template for the type of ";
// << DrClassMap::demangle(typeid(T).name());
exit(1);
}
template <>

View File

@ -1,95 +0,0 @@
/**
*
* HttpSimpleController.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include <drogon/DrObject.h>
#include <drogon/HttpAppFramework.h>
#include <drogon/utils/HttpConstraint.h>
#include <trantor/utils/Logger.h>
#include <iostream>
#include <string>
#include <vector>
#define PATH_LIST_BEGIN \
static void initPathRouting() {
#define PATH_ADD(path, ...) registerSelf__(path, { __VA_ARGS__ });
#define PATH_LIST_END }
namespace drogon {
/**
* @brief The abstract base class for HTTP simple controllers.
*
*/
class HttpSimpleControllerBase : public virtual DrObjectBase {
public:
/**
* @brief The function is called when a HTTP request is routed to the
* controller.
*
* @param req The HTTP request.
* @param callback The callback via which a response is returned.
*/
virtual void asyncHandleHttpRequest(
const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback) = 0;
virtual ~HttpSimpleControllerBase() {
}
};
/**
* @brief The reflection base class template for HTTP simple controllers
*
* @tparam T The type of the implementation class
* @tparam AutoCreation The flag for automatically creating, user can set this
* flag to false for classes that have nondefault constructors.
*/
template <typename T, bool AutoCreation = true>
class HttpSimpleController : public DrObject<T>, public HttpSimpleControllerBase {
public:
static const bool isAutoCreation = AutoCreation;
virtual ~HttpSimpleController() {
}
protected:
HttpSimpleController() {
}
static void registerSelf__(
const std::string &path,
const std::vector<internal::HttpConstraint> &filtersAndMethods) {
LOG_TRACE << "register simple controller("
<< HttpSimpleController<T>::classTypeName()
<< ") on path:" << path;
app().registerHttpSimpleController(
path, HttpSimpleController<T>::classTypeName(), filtersAndMethods);
}
private:
class pathRegistrator {
public:
pathRegistrator() {
if (AutoCreation) {
T::initPathRouting();
}
}
};
friend pathRegistrator;
static pathRegistrator registrator_;
virtual void *touch() {
return &registrator_;
}
};
template <typename T, bool AutoCreation>
typename HttpSimpleController<T, AutoCreation>::pathRegistrator
HttpSimpleController<T, AutoCreation>::registrator_;
} // namespace drogon

View File

@ -1,31 +0,0 @@
// this file is generated by program automatically,don't modify it!
/**
*
* @file NotFound.h
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include <drogon/DrTemplate.h>
#include <drogon/exports.h>
namespace drogon {
/**
* @brief This class is used by the drogon to generate the 404 page. Users don't
* use this class directly.
*/
class DROGON_EXPORT NotFound final : public drogon::DrTemplate<NotFound> {
public:
NotFound() {
}
virtual std::string genText(const drogon::HttpViewData &) override;
};
} // namespace drogon

View File

@ -1,104 +0,0 @@
/**
*
* WebSocketController.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include <drogon/DrObject.h>
#include <drogon/HttpAppFramework.h>
#include <drogon/HttpTypes.h>
#include <drogon/WebSocketConnection.h>
#include <trantor/utils/Logger.h>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#define WS_PATH_LIST_BEGIN \
static void initPathRouting() {
#define WS_PATH_ADD(path, ...) registerSelf__(path, { __VA_ARGS__ });
#define WS_PATH_LIST_END }
namespace drogon {
/**
* @brief The abstract base class for WebSocket controllers.
*
*/
class WebSocketControllerBase : public virtual DrObjectBase {
public:
// This function is called when a new message is received
virtual void handleNewMessage(const WebSocketConnectionPtr &,
std::string &&,
const WebSocketMessageType &) = 0;
// This function is called after a new connection of WebSocket is
// established.
virtual void handleNewConnection(const HttpRequestPtr &,
const WebSocketConnectionPtr &) = 0;
// This function is called after a WebSocket connection is closed
virtual void handleConnectionClosed(const WebSocketConnectionPtr &) = 0;
virtual ~WebSocketControllerBase() {
}
};
using WebSocketControllerBasePtr = std::shared_ptr<WebSocketControllerBase>;
/**
* @brief The reflection base class template for WebSocket controllers
*
* @tparam T the type of the implementation class
* @tparam AutoCreation The flag for automatically creating, user can set this
* flag to false for classes that have nondefault constructors.
*/
template <typename T, bool AutoCreation = true>
class WebSocketController : public DrObject<T>, public WebSocketControllerBase {
public:
static const bool isAutoCreation = AutoCreation;
virtual ~WebSocketController() {
}
protected:
WebSocketController() {
}
static void registerSelf__(
const std::string &path,
const std::vector<internal::HttpConstraint> &filtersAndMethods) {
LOG_TRACE << "register websocket controller("
<< WebSocketController<T>::classTypeName()
<< ") on path:" << path;
app().registerWebSocketController(
path, WebSocketController<T>::classTypeName(), filtersAndMethods);
}
private:
class pathRegistrator {
public:
pathRegistrator() {
if (AutoCreation) {
T::initPathRouting();
}
}
};
friend pathRegistrator;
static pathRegistrator registrator_;
virtual void *touch() {
return &registrator_;
}
};
template <typename T, bool AutoCreation>
typename WebSocketController<T, AutoCreation>::pathRegistrator
WebSocketController<T, AutoCreation>::registrator_;
} // namespace drogon

View File

@ -23,8 +23,6 @@
#include <drogon/Cookie.h>
#include <drogon/HttpAppFramework.h>
#include <drogon/HttpClient.h>
#include <drogon/HttpController.h>
#include <drogon/HttpSimpleController.h>
#include <drogon/IOThreadStorage.h>
#include <drogon/MultiPart.h>
#include <drogon/Session.h>

View File

@ -13,7 +13,6 @@
#pragma once
#include <drogon/DrObject.h>
#include <json/json.h>
#include <trantor/utils/Logger.h>
#include <trantor/utils/NonCopyable.h>
@ -30,8 +29,7 @@ enum class PluginStatus {
* @brief The abstract base class for plugins.
*
*/
class DROGON_EXPORT PluginBase : public virtual DrObjectBase,
public trantor::NonCopyable {
class PluginBase : public trantor::NonCopyable {
public:
/// This method must be called by drogon.
void initialize() {
@ -105,7 +103,7 @@ struct IsPlugin {
* @tparam T The type of the implementation plugin classes.
*/
template <typename T>
class Plugin : public PluginBase, public DrObject<T> {
class Plugin : public PluginBase {
public:
virtual ~Plugin() {
}

View File

@ -14,7 +14,6 @@
#pragma once
#include <drogon/DrObject.h>
#include <functional>
#include <memory>
#include <tuple>

View File

@ -1,89 +0,0 @@
/**
*
* DrClassMap.cc
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#include <drogon/DrClassMap.h>
#include <drogon/DrObject.h>
#include <trantor/utils/Logger.h>
using namespace drogon;
namespace drogon {
namespace internal {
static std::unordered_map<std::string, std::shared_ptr<DrObjectBase> >
&getObjsMap() {
static std::unordered_map<std::string, std::shared_ptr<DrObjectBase> >
singleInstanceMap;
return singleInstanceMap;
}
static std::mutex &getMapMutex() {
static std::mutex mtx;
return mtx;
}
} // namespace internal
} // namespace drogon
void DrClassMap::registerClass(const std::string &className,
const DrAllocFunc &func) {
LOG_TRACE << "Register class:" << className;
getMap().insert(std::make_pair(className, func));
}
DrObjectBase *DrClassMap::newObject(const std::string &className) {
auto iter = getMap().find(className);
if (iter != getMap().end()) {
return iter->second();
} else
return nullptr;
}
const std::shared_ptr<DrObjectBase> &DrClassMap::getSingleInstance(
const std::string &className) {
auto &mtx = internal::getMapMutex();
auto &singleInstanceMap = internal::getObjsMap();
{
std::lock_guard<std::mutex> lock(mtx);
auto iter = singleInstanceMap.find(className);
if (iter != singleInstanceMap.end())
return iter->second;
}
auto newObj = std::shared_ptr<DrObjectBase>(newObject(className));
{
std::lock_guard<std::mutex> lock(mtx);
auto ret = singleInstanceMap.insert(
std::make_pair(className, std::move(newObj)));
return ret.first->second;
}
}
void DrClassMap::setSingleInstance(const std::shared_ptr<DrObjectBase> &ins) {
auto &mtx = internal::getMapMutex();
auto &singleInstanceMap = internal::getObjsMap();
std::lock_guard<std::mutex> lock(mtx);
singleInstanceMap[ins->className()] = ins;
}
std::vector<std::string> DrClassMap::getAllClassName() {
std::vector<std::string> ret;
for (auto const &iter : getMap()) {
ret.push_back(iter.first);
}
return ret;
}
std::unordered_map<std::string, DrAllocFunc> &DrClassMap::getMap() {
static std::unordered_map<std::string, DrAllocFunc> map;
return map;
}

View File

@ -1,52 +0,0 @@
/**
*
* @file DrTemplateBase.cc
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#include <drogon/DrClassMap.h>
#include <drogon/DrTemplateBase.h>
#include <trantor/utils/Logger.h>
#include <memory>
#include <regex>
using namespace drogon;
std::shared_ptr<DrTemplateBase> DrTemplateBase::newTemplate(
const std::string &templateName) {
LOG_TRACE << "http view name=" << templateName;
auto l = templateName.length();
if (l >= 4 && templateName[l - 4] == '.' && templateName[l - 3] == 'c' &&
templateName[l - 2] == 's' && templateName[l - 1] == 'p') {
std::string::size_type pos = 0;
std::string newName;
newName.reserve(templateName.size());
if (templateName[0] == '/' || templateName[0] == '\\') {
pos = 1;
} else if (templateName[0] == '.' &&
(templateName[1] == '/' || templateName[1] == '\\')) {
pos = 2;
}
while (pos < l - 4) {
if (templateName[pos] == '/' || templateName[pos] == '\\') {
newName.append("::");
} else {
newName.append(1, templateName[pos]);
}
++pos;
}
return std::shared_ptr<DrTemplateBase>(dynamic_cast<DrTemplateBase *>(
drogon::DrClassMap::newObject(newName)));
} else {
return std::shared_ptr<DrTemplateBase>(dynamic_cast<DrTemplateBase *>(
drogon::DrClassMap::newObject(templateName)));
}
}

View File

@ -1,82 +0,0 @@
/**
*
* @file FiltersFunction.cc
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#include "FiltersFunction.h"
#include "HttpAppFrameworkImpl.h"
#include "HttpRequestImpl.h"
#include "HttpResponseImpl.h"
#include <drogon/HttpFilter.h>
#include <queue>
namespace drogon {
namespace filters_function {
static void doFilterChains(
const std::vector<std::shared_ptr<HttpFilterBase> > &filters,
size_t index,
const HttpRequestImplPtr &req,
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)> >
&callbackPtr,
std::function<void()> &&missCallback) {
if (index < filters.size()) {
auto &filter = filters[index];
filter->doFilter(
req,
[req, callbackPtr](const HttpResponsePtr &res) {
HttpAppFrameworkImpl::instance().callCallback(req,
res,
*callbackPtr);
},
[index,
req,
callbackPtr,
&filters,
missCallback = std::move(missCallback)]() mutable {
doFilterChains(filters,
index + 1,
req,
callbackPtr,
std::move(missCallback));
});
} else {
missCallback();
}
}
std::vector<std::shared_ptr<HttpFilterBase> > createFilters(
const std::vector<std::string> &filterNames) {
std::vector<std::shared_ptr<HttpFilterBase> > filters;
for (auto const &filter : filterNames) {
auto object_ = DrClassMap::getSingleInstance(filter);
auto filter_ = std::dynamic_pointer_cast<HttpFilterBase>(object_);
if (filter_)
filters.push_back(filter_);
else {
LOG_ERROR << "filter " << filter << " not found";
}
}
return filters;
}
void doFilters(
const std::vector<std::shared_ptr<HttpFilterBase> > &filters,
const HttpRequestImplPtr &req,
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)> >
&callbackPtr,
std::function<void()> &&missCallback) {
doFilterChains(filters, 0, req, callbackPtr, std::move(missCallback));
}
} // namespace filters_function
} // namespace drogon

View File

@ -1,34 +0,0 @@
/**
*
* FiltersFunction.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include "impl_forwards.h"
#include <memory>
#include <string>
#include <vector>
namespace drogon {
namespace filters_function {
std::vector<std::shared_ptr<HttpFilterBase> > createFilters(
const std::vector<std::string> &filterNames);
void doFilters(
const std::vector<std::shared_ptr<HttpFilterBase> > &filters,
const HttpRequestImplPtr &req,
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)> >
&callbackPtr,
std::function<void()> &&missCallback);
} // namespace filters_function
} // namespace drogon

View File

@ -16,11 +16,9 @@
#include "AOPAdvice.h"
#include "ConfigLoader.h"
#include "HttpClientImpl.h"
#include "HttpControllersRouter.h"
#include "HttpRequestImpl.h"
#include "HttpResponseImpl.h"
#include "HttpServer.h"
#include "HttpSimpleControllersRouter.h"
#include "ListenerManager.h"
#include "PluginsManager.h"
#include "SessionManager.h"
@ -29,7 +27,6 @@
#include "WebSocketConnectionImpl.h"
#include "WebsocketControllersRouter.h"
#include <drogon/CacheMap.h>
#include <drogon/DrClassMap.h>
#include <drogon/HttpRequest.h>
#include <drogon/HttpResponse.h>
#include <drogon/HttpTypes.h>
@ -65,6 +62,7 @@ using namespace std::placeholders;
HttpAppFrameworkImpl::HttpAppFrameworkImpl() :
staticFileRouterPtr_(new StaticFileRouter{}),
/*
httpCtrlsRouterPtr_(new HttpControllersRouter(*staticFileRouterPtr_,
postRoutingAdvices_,
postRoutingObservers_,
@ -77,7 +75,7 @@ HttpAppFrameworkImpl::HttpAppFrameworkImpl() :
postRoutingObservers_,
preHandlingAdvices_,
preHandlingObservers_,
postHandlingAdvices_)),
postHandlingAdvices_)),*/
websockCtrlsRouterPtr_(
new WebsocketControllersRouter(postRoutingAdvices_,
postRoutingObservers_)),
@ -256,12 +254,13 @@ HttpAppFramework &HttpAppFrameworkImpl::registerHttpSimpleController(
const std::string &ctrlName,
const std::vector<internal::HttpConstraint> &filtersAndMethods) {
assert(!running_);
httpSimpleCtrlsRouterPtr_->registerHttpSimpleController(pathName,
ctrlName,
filtersAndMethods);
//httpSimpleCtrlsRouterPtr_->registerHttpSimpleController(pathName, ctrlName, filtersAndMethods);
return *this;
}
/*
void HttpAppFrameworkImpl::registerHttpController(
const std::string &pathPattern,
const internal::HttpBinderBasePtr &binder,
@ -287,6 +286,7 @@ void HttpAppFrameworkImpl::registerHttpControllerViaRegex(
httpCtrlsRouterPtr_->addHttpRegex(
regExp, binder, validMethods, filters, handlerName);
}
*/
HttpAppFramework &HttpAppFrameworkImpl::setThreadNum(size_t threadNum) {
if (threadNum == 0) {
@ -448,11 +448,13 @@ void HttpAppFrameworkImpl::run() {
}
asyncFileLogger.setFileName(baseName, ".log", logPath_);
asyncFileLogger.startLogging();
trantor::Logger::setOutputFunction(
[&](const char *msg, const uint64_t len) {
asyncFileLogger.output(msg, len);
},
[&]() { asyncFileLogger.flush(); });
asyncFileLogger.setFileSizeLimit(logfileSize_);
}
}
@ -500,13 +502,15 @@ void HttpAppFrameworkImpl::run() {
pluginsManagerPtr_->initializeAllPlugins(pluginConfig,
[](PluginBase *plugin) {
LOG_TRACE
<< "new plugin:"
<< plugin->className();
<< "new plugin:";
// << plugin->className();
// TODO: new plugin
});
}
httpCtrlsRouterPtr_->init(ioLoops);
httpSimpleCtrlsRouterPtr_->init(ioLoops);
//httpCtrlsRouterPtr_->init(ioLoops);
//httpSimpleCtrlsRouterPtr_->init(ioLoops);
staticFileRouterPtr_->init(ioLoops);
websockCtrlsRouterPtr_->init();
getLoop()->queueInLoop([this]() {
@ -634,12 +638,13 @@ void HttpAppFrameworkImpl::onNewWebsockRequest(
std::vector<std::tuple<std::string, HttpMethod, std::string> >
HttpAppFrameworkImpl::getHandlersInfo() const {
auto ret = httpSimpleCtrlsRouterPtr_->getHandlersInfo();
//auto ret = httpSimpleCtrlsRouterPtr_->getHandlersInfo();
/*
auto v = httpCtrlsRouterPtr_->getHandlersInfo();
ret.insert(ret.end(), v.begin(), v.end());
v = websockCtrlsRouterPtr_->getHandlersInfo();
ret.insert(ret.end(), v.begin(), v.end());
return ret;
ret.insert(ret.end(), v.begin(), v.end());*/
auto v = websockCtrlsRouterPtr_->getHandlersInfo();
//v.insert(ret.end(), v.begin(), v.end());
return v;
}
void HttpAppFrameworkImpl::callCallback(
const HttpRequestImplPtr &req,
@ -709,6 +714,8 @@ void HttpAppFrameworkImpl::onAsyncRequest(
callback(resp);
return;
}
/*
findSessionForRequest(req);
// Route to controller
if (!preRoutingObservers_.empty()) {
@ -733,7 +740,7 @@ void HttpAppFrameworkImpl::onAsyncRequest(
[this, callbackPtr, req]() {
httpSimpleCtrlsRouterPtr_->route(req, std::move(*callbackPtr));
});
}
}*/
}
trantor::EventLoop *HttpAppFrameworkImpl::getLoop() const {

View File

@ -440,6 +440,7 @@ public:
}
private:
/*
void registerHttpController(const std::string &pathPattern,
const internal::HttpBinderBasePtr &binder,
const std::vector<HttpMethod> &validMethods,
@ -451,6 +452,8 @@ private:
const std::vector<HttpMethod> &validMethods,
const std::vector<std::string> &filters,
const std::string &handlerName) override;
*/
void onAsyncRequest(
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback);
@ -472,9 +475,9 @@ private:
"\r\n" };
const std::unique_ptr<StaticFileRouter> staticFileRouterPtr_;
const std::unique_ptr<HttpControllersRouter> httpCtrlsRouterPtr_;
const std::unique_ptr<HttpSimpleControllersRouter>
httpSimpleCtrlsRouterPtr_;
//const std::unique_ptr<HttpControllersRouter> httpCtrlsRouterPtr_;
//const std::unique_ptr<HttpSimpleControllersRouter>
// httpSimpleCtrlsRouterPtr_;
const std::unique_ptr<WebsocketControllersRouter> websockCtrlsRouterPtr_;
const std::unique_ptr<ListenerManager> listenerManagerPtr_;

View File

@ -1,26 +0,0 @@
/**
*
* HttpBinder.h
* Martin Chang
*
* Copyright 2021, Martin Chang. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#include <drogon/HttpAppFramework.h>
#include <drogon/HttpBinder.h>
namespace drogon {
namespace internal {
void handleException(const std::exception &e,
const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback) {
app().getExceptionHandler()(e, req, std::move(callback));
}
} // namespace internal
} // namespace drogon

View File

@ -1,682 +0,0 @@
/**
*
* @file HttpControllersRouter.cc
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#include "HttpControllersRouter.h"
#include "AOPAdvice.h"
#include "FiltersFunction.h"
#include "HttpAppFrameworkImpl.h"
#include "HttpRequestImpl.h"
#include "HttpResponseImpl.h"
#include "StaticFileRouter.h"
#include <algorithm>
#include <cctype>
#include <deque>
using namespace drogon;
void HttpControllersRouter::doWhenNoHandlerFound(
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback) {
if (req->path() == "/" &&
!HttpAppFrameworkImpl::instance().getHomePage().empty()) {
req->setPath("/" + HttpAppFrameworkImpl::instance().getHomePage());
// Just call the fileRouter_.route instead of forwarding. so comment out
// those sentences.
// HttpAppFrameworkImpl::instance().forward(req, std::move(callback));
// return;
}
fileRouter_.route(req, std::move(callback));
}
void HttpControllersRouter::init(
const std::vector<trantor::EventLoop *> & /*ioLoops*/) {
auto initFilters = [](auto &binders) {
for (auto &binder : binders) {
if (binder) {
binder->filters_ =
filters_function::createFilters(binder->filterNames_);
}
}
};
for (auto &router : ctrlVector_) {
router.regex_ = std::regex(router.pathParameterPattern_,
std::regex_constants::icase);
initFilters(router.binders_);
}
for (auto &p : ctrlMap_) {
auto &router = p.second;
router.regex_ = std::regex(router.pathParameterPattern_,
std::regex_constants::icase);
initFilters(router.binders_);
}
}
std::vector<std::tuple<std::string, HttpMethod, std::string> >
HttpControllersRouter::getHandlersInfo() const {
std::vector<std::tuple<std::string, HttpMethod, std::string> > ret;
auto gatherInfo = [&](const auto &item) {
for (size_t i = 0; i < Invalid; ++i) {
if (item.binders_[i]) {
auto description =
item.binders_[i]->handlerName_.empty() ? std::string("Handler: ") +
item.binders_[i]->binderPtr_->handlerName() :
std::string("HttpController: ") +
item.binders_[i]->handlerName_;
auto info = std::tuple<std::string, HttpMethod, std::string>(
item.pathPattern_, (HttpMethod)i, std::move(description));
ret.emplace_back(std::move(info));
}
}
};
for (auto &item : ctrlVector_) {
gatherInfo(item);
}
for (auto &data : ctrlMap_) {
gatherInfo(data.second);
}
return ret;
}
void HttpControllersRouter::addHttpRegex(
const std::string &regExp,
const internal::HttpBinderBasePtr &binder,
const std::vector<HttpMethod> &validMethods,
const std::vector<std::string> &filters,
const std::string &handlerName) {
auto binderInfo = std::make_shared<CtrlBinder>();
binderInfo->filterNames_ = filters;
binderInfo->handlerName_ = handlerName;
binderInfo->binderPtr_ = binder;
drogon::app().getLoop()->queueInLoop([binderInfo]() {
// Recreate this with the correct number of threads.
binderInfo->responseCache_ = IOThreadStorage<HttpResponsePtr>();
});
{
for (auto &router : ctrlVector_) {
if (router.pathParameterPattern_ == regExp) {
if (!validMethods.empty()) {
for (auto const &method : validMethods) {
router.binders_[method] = binderInfo;
if (method == Options)
binderInfo->isCORS_ = true;
}
} else {
binderInfo->isCORS_ = true;
for (int i = 0; i < Invalid; ++i)
router.binders_[i] = binderInfo;
}
return;
}
}
}
struct HttpControllerRouterItem router;
router.pathParameterPattern_ = regExp;
router.pathPattern_ = regExp;
if (!validMethods.empty()) {
for (auto const &method : validMethods) {
router.binders_[method] = binderInfo;
if (method == Options)
binderInfo->isCORS_ = true;
}
} else {
binderInfo->isCORS_ = true;
for (int i = 0; i < Invalid; ++i)
router.binders_[i] = binderInfo;
}
ctrlVector_.push_back(std::move(router));
}
void HttpControllersRouter::addHttpPath(
const std::string &path,
const internal::HttpBinderBasePtr &binder,
const std::vector<HttpMethod> &validMethods,
const std::vector<std::string> &filters,
const std::string &handlerName) {
// Path is like /api/v1/service/method/{1}/{2}/xxx...
std::vector<size_t> places;
std::string tmpPath = path;
std::string paras;
static const std::regex regex("\\{([^/]*)\\}");
std::smatch results;
auto pos = tmpPath.find('?');
if (pos != std::string::npos) {
paras = tmpPath.substr(pos + 1);
tmpPath = tmpPath.substr(0, pos);
}
std::string originPath = tmpPath;
size_t placeIndex = 1;
while (std::regex_search(tmpPath, results, regex)) {
if (results.size() > 1) {
auto result = results[1].str();
if (!result.empty() &&
std::all_of(result.begin(), result.end(), [](const char c) {
return std::isdigit(c);
})) {
auto place = (size_t)std::stoi(result);
if (place > binder->paramCount() || place == 0) {
LOG_ERROR << "Parameter placeholder(value=" << place
<< ") out of range (1 to " << binder->paramCount()
<< ")";
LOG_ERROR << "Path pattern: " << path;
exit(1);
}
if (!std::all_of(places.begin(),
places.end(),
[place](size_t i) { return i != place; })) {
LOG_ERROR << "Parameter placeholders are duplicated: index="
<< place;
LOG_ERROR << "Path pattern: " << path;
exit(1);
}
places.push_back(place);
} else {
static const std::regex regNumberAndName("([0-9]+):.*");
std::smatch regexResult;
if (std::regex_match(result, regexResult, regNumberAndName)) {
assert(regexResult.size() == 2 && regexResult[1].matched);
auto num = regexResult[1].str();
auto place = (size_t)std::stoi(num);
if (place > binder->paramCount() || place == 0) {
LOG_ERROR << "Parameter placeholder(value=" << place
<< ") out of range (1 to "
<< binder->paramCount() << ")";
LOG_ERROR << "Path pattern: " << path;
exit(1);
}
if (!std::all_of(places.begin(),
places.end(),
[place](size_t i) { return i != place; })) {
LOG_ERROR
<< "Parameter placeholders are duplicated: index="
<< place;
LOG_ERROR << "Path pattern: " << path;
exit(1);
}
places.push_back(place);
} else {
if (!std::all_of(places.begin(),
places.end(),
[placeIndex](size_t i) {
return i != placeIndex;
})) {
LOG_ERROR
<< "Parameter placeholders are duplicated: index="
<< placeIndex;
LOG_ERROR << "Path pattern: " << path;
exit(1);
}
places.push_back(placeIndex);
}
}
++placeIndex;
}
tmpPath = results.suffix();
}
std::vector<std::pair<std::string, size_t> > parametersPlaces;
if (!paras.empty()) {
static const std::regex pregex("([^&]*)=\\{([^&]*)\\}&*");
while (std::regex_search(paras, results, pregex)) {
if (results.size() > 2) {
auto result = results[2].str();
if (!result.empty() &&
std::all_of(result.begin(), result.end(), [](const char c) {
return std::isdigit(c);
})) {
auto place = (size_t)std::stoi(result);
if (place > binder->paramCount() || place == 0) {
LOG_ERROR << "Parameter placeholder(value=" << place
<< ") out of range (1 to "
<< binder->paramCount() << ")";
LOG_ERROR << "Path pattern: " << path;
exit(1);
}
if (!std::all_of(places.begin(),
places.end(),
[place](size_t i) {
return i != place;
}) ||
!all_of(parametersPlaces.begin(),
parametersPlaces.end(),
[place](const std::pair<std::string, size_t>
&item) {
return item.second != place;
})) {
LOG_ERROR << "Parameter placeholders are "
"duplicated: index="
<< place;
LOG_ERROR << "Path pattern: " << path;
exit(1);
}
parametersPlaces.emplace_back(results[1].str(), place);
} else {
std::regex regNumberAndName("([0-9]+):.*");
std::smatch regexResult;
if (std::regex_match(result, regexResult, regNumberAndName)) {
assert(regexResult.size() == 2 &&
regexResult[1].matched);
auto num = regexResult[1].str();
auto place = (size_t)std::stoi(num);
if (place > binder->paramCount() || place == 0) {
LOG_ERROR << "Parameter placeholder(value=" << place
<< ") out of range (1 to "
<< binder->paramCount() << ")";
LOG_ERROR << "Path pattern: " << path;
exit(1);
}
if (!std::all_of(places.begin(),
places.end(),
[place](size_t i) {
return i != place;
}) ||
!all_of(parametersPlaces.begin(),
parametersPlaces.end(),
[place](const std::pair<std::string, size_t>
&item) {
return item.second != place;
})) {
LOG_ERROR << "Parameter placeholders are "
"duplicated: index="
<< place;
LOG_ERROR << "Path pattern: " << path;
exit(1);
}
parametersPlaces.emplace_back(results[1].str(), place);
} else {
if (!std::all_of(places.begin(),
places.end(),
[placeIndex](size_t i) {
return i != placeIndex;
}) ||
!all_of(parametersPlaces.begin(),
parametersPlaces.end(),
[placeIndex](
const std::pair<std::string, size_t>
&item) {
return item.second != placeIndex;
})) {
LOG_ERROR << "Parameter placeholders are "
"duplicated: index="
<< placeIndex;
LOG_ERROR << "Path pattern: " << path;
exit(1);
}
parametersPlaces.emplace_back(results[1].str(),
placeIndex);
}
}
++placeIndex;
}
paras = results.suffix();
}
}
auto pathParameterPattern =
std::regex_replace(originPath, regex, "([^/]*)");
auto binderInfo = std::make_shared<CtrlBinder>();
binderInfo->filterNames_ = filters;
binderInfo->handlerName_ = handlerName;
binderInfo->binderPtr_ = binder;
binderInfo->parameterPlaces_ = std::move(places);
binderInfo->queryParametersPlaces_ = std::move(parametersPlaces);
drogon::app().getLoop()->queueInLoop([binderInfo]() {
// Recreate this with the correct number of threads.
binderInfo->responseCache_ = IOThreadStorage<HttpResponsePtr>();
});
bool routingRequiresRegex = (originPath != pathParameterPattern);
HttpControllerRouterItem *existingRouterItemPtr = nullptr;
// If exists another controllers on the same route. Updathe them then exit
if (routingRequiresRegex) {
for (auto &router : ctrlVector_) {
if (router.pathParameterPattern_ == pathParameterPattern)
existingRouterItemPtr = &router;
}
} else {
std::string loweredPath;
loweredPath.resize(originPath.size());
std::transform(originPath.begin(),
originPath.end(),
loweredPath.begin(),
tolower);
auto it = ctrlMap_.find(loweredPath);
if (it != ctrlMap_.end())
existingRouterItemPtr = &it->second;
}
if (existingRouterItemPtr != nullptr) {
auto &router = *existingRouterItemPtr;
if (!validMethods.empty()) {
for (auto const &method : validMethods) {
router.binders_[method] = binderInfo;
if (method == Options)
binderInfo->isCORS_ = true;
}
} else {
binderInfo->isCORS_ = true;
for (int i = 0; i < Invalid; ++i)
router.binders_[i] = binderInfo;
}
return;
}
struct HttpControllerRouterItem router;
router.pathParameterPattern_ = pathParameterPattern;
router.pathPattern_ = path;
if (!validMethods.empty()) {
for (auto const &method : validMethods) {
router.binders_[method] = binderInfo;
if (method == Options)
binderInfo->isCORS_ = true;
}
} else {
binderInfo->isCORS_ = true;
for (int i = 0; i < Invalid; ++i)
router.binders_[i] = binderInfo;
}
if (routingRequiresRegex)
ctrlVector_.push_back(std::move(router));
else {
std::string loweredPath;
loweredPath.resize(originPath.size());
std::transform(originPath.begin(),
originPath.end(),
loweredPath.begin(),
tolower);
ctrlMap_[loweredPath] = std::move(router);
}
}
void HttpControllersRouter::route(
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback) {
// Find http controller
HttpControllerRouterItem *routerItemPtr = nullptr;
std::smatch result;
std::string loweredPath = req->path();
std::transform(loweredPath.begin(),
loweredPath.end(),
loweredPath.begin(),
tolower);
auto it = ctrlMap_.find(loweredPath);
// Try to find a controller in the hash map. If can't linear search
// with regex.
if (it != ctrlMap_.end()) {
routerItemPtr = &it->second;
} else {
for (auto &item : ctrlVector_) {
auto const &ctrlRegex = item.regex_;
if (std::regex_match(req->path(), result, ctrlRegex)) {
routerItemPtr = &item;
break;
}
}
}
// No handler found
if (routerItemPtr == nullptr) {
doWhenNoHandlerFound(req, std::move(callback));
return;
}
HttpControllerRouterItem &routerItem = *routerItemPtr;
assert(Invalid > req->method());
req->setMatchedPathPattern(routerItem.pathPattern_);
auto &binder = routerItem.binders_[req->method()];
if (!binder) {
// Invalid Http Method
if (req->method() != Options) {
callback(app().getCustomErrorHandler()(k405MethodNotAllowed));
} else {
callback(app().getCustomErrorHandler()(k403Forbidden));
}
return;
}
if (!postRoutingObservers_.empty()) {
for (auto &observer : postRoutingObservers_) {
observer(req);
}
}
if (postRoutingAdvices_.empty()) {
if (!binder->filters_.empty()) {
auto &filters = binder->filters_;
auto callbackPtr =
std::make_shared<std::function<void(const HttpResponsePtr &)> >(
std::move(callback));
filters_function::doFilters(filters,
req,
callbackPtr,
[req,
callbackPtr,
this,
&binder,
&routerItem,
result = std::move(result)]() mutable {
doPreHandlingAdvices(
binder,
routerItem,
req,
std::move(result),
std::move(*callbackPtr));
});
} else {
doPreHandlingAdvices(binder,
routerItem,
req,
std::move(result),
std::move(callback));
}
} else {
auto callbackPtr =
std::make_shared<std::function<void(const HttpResponsePtr &)> >(
std::move(callback));
doAdvicesChain(postRoutingAdvices_,
0,
req,
callbackPtr,
[&binder,
callbackPtr,
req,
this,
&routerItem,
result = std::move(result)]() mutable {
if (!binder->filters_.empty()) {
auto &filters = binder->filters_;
filters_function::doFilters(
filters,
req,
callbackPtr,
[this,
req,
callbackPtr,
&binder,
&routerItem,
result = std::move(result)]() mutable {
doPreHandlingAdvices(binder,
routerItem,
req,
std::move(result),
std::move(
*callbackPtr));
});
} else {
doPreHandlingAdvices(binder,
routerItem,
req,
std::move(result),
std::move(*callbackPtr));
}
});
}
}
void HttpControllersRouter::doControllerHandler(
const CtrlBinderPtr &ctrlBinderPtr,
const HttpControllerRouterItem & /*routerItem*/,
const HttpRequestImplPtr &req,
const std::smatch &matchResult,
std::function<void(const HttpResponsePtr &)> &&callback) {
auto &responsePtr = *(ctrlBinderPtr->responseCache_);
if (responsePtr) {
if (responsePtr->expiredTime() == 0 ||
(trantor::Date::now() <
responsePtr->creationDate().after(
static_cast<double>(responsePtr->expiredTime())))) {
// use cached response!
LOG_TRACE << "Use cached response";
invokeCallback(callback, req, responsePtr);
return;
} else {
responsePtr.reset();
}
}
std::deque<std::string> params(ctrlBinderPtr->parameterPlaces_.size());
for (size_t j = 1; j < matchResult.size(); ++j) {
if (!matchResult[j].matched)
continue;
size_t place = j;
if (j <= ctrlBinderPtr->parameterPlaces_.size()) {
place = ctrlBinderPtr->parameterPlaces_[j - 1];
}
if (place > params.size())
params.resize(place);
params[place - 1] = matchResult[j].str();
LOG_TRACE << "place=" << place << " para:" << params[place - 1];
}
if (!ctrlBinderPtr->queryParametersPlaces_.empty()) {
auto &queryPara = req->getParameters();
for (auto const &paraPlace : ctrlBinderPtr->queryParametersPlaces_) {
auto place = paraPlace.second;
if (place > params.size())
params.resize(place);
auto iter = queryPara.find(paraPlace.first);
if (iter != queryPara.end()) {
params[place - 1] = iter->second;
} else {
params[place - 1] = std::string{};
}
}
}
ctrlBinderPtr->binderPtr_->handleHttpRequest(
params,
req,
[this, req, ctrlBinderPtr, callback = std::move(callback)](
const HttpResponsePtr &resp) {
if (resp->expiredTime() >= 0 && resp->statusCode() != k404NotFound) {
// cache the response;
static_cast<HttpResponseImpl *>(resp.get())->makeHeaderString();
auto loop = req->getLoop();
if (loop->isInLoopThread()) {
ctrlBinderPtr->responseCache_.setThreadData(resp);
} else {
req->getLoop()->queueInLoop([resp, &ctrlBinderPtr]() {
ctrlBinderPtr->responseCache_.setThreadData(resp);
});
}
}
invokeCallback(callback, req, resp);
});
}
void HttpControllersRouter::doPreHandlingAdvices(
const CtrlBinderPtr &ctrlBinderPtr,
const HttpControllerRouterItem &routerItem,
const HttpRequestImplPtr &req,
std::smatch &&matchResult,
std::function<void(const HttpResponsePtr &)> &&callback) {
if (req->method() == Options) {
auto resp = HttpResponse::newHttpResponse();
resp->setContentTypeCode(ContentType::CT_TEXT_PLAIN);
std::string methods = "OPTIONS,";
if (routerItem.binders_[Get] && routerItem.binders_[Get]->isCORS_) {
methods.append("GET,HEAD,");
}
if (routerItem.binders_[Post] && routerItem.binders_[Post]->isCORS_) {
methods.append("POST,");
}
if (routerItem.binders_[Put] && routerItem.binders_[Put]->isCORS_) {
methods.append("PUT,");
}
if (routerItem.binders_[Delete] && routerItem.binders_[Delete]->isCORS_) {
methods.append("DELETE,");
}
if (routerItem.binders_[Patch] && routerItem.binders_[Patch]->isCORS_) {
methods.append("PATCH,");
}
methods.resize(methods.length() - 1);
resp->addHeader("ALLOW", methods);
auto &origin = req->getHeader("Origin");
if (origin.empty()) {
resp->addHeader("Access-Control-Allow-Origin", "*");
} else {
resp->addHeader("Access-Control-Allow-Origin", origin);
}
resp->addHeader("Access-Control-Allow-Methods", methods);
auto &headers = req->getHeaderBy("access-control-request-headers");
if (!headers.empty()) {
resp->addHeader("Access-Control-Allow-Headers", headers);
}
callback(resp);
return;
}
if (!preHandlingObservers_.empty()) {
for (auto &observer : preHandlingObservers_) {
observer(req);
}
}
if (preHandlingAdvices_.empty()) {
doControllerHandler(
ctrlBinderPtr, routerItem, req, matchResult, std::move(callback));
} else {
auto callbackPtr =
std::make_shared<std::function<void(const HttpResponsePtr &)> >(
std::move(callback));
doAdvicesChain(
preHandlingAdvices_,
0,
req,
std::make_shared<std::function<void(const HttpResponsePtr &)> >(
[req, callbackPtr](const HttpResponsePtr &resp) {
HttpAppFrameworkImpl::instance().callCallback(req,
resp,
*callbackPtr);
}),
[this,
ctrlBinderPtr,
&routerItem,
req,
callbackPtr,
result = std::move(matchResult)]() {
doControllerHandler(ctrlBinderPtr,
routerItem,
req,
result,
std::move(*callbackPtr));
});
}
}
void HttpControllersRouter::invokeCallback(
const std::function<void(const HttpResponsePtr &)> &callback,
const HttpRequestImplPtr &req,
const HttpResponsePtr &resp) {
for (auto &advice : postHandlingAdvices_) {
advice(req, resp);
}
HttpAppFrameworkImpl::instance().callCallback(req, resp, callback);
}

View File

@ -1,135 +0,0 @@
/**
*
* HttpControllersRouter.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include "impl_forwards.h"
#include <drogon/HttpBinder.h>
#include <drogon/IOThreadStorage.h>
#include <drogon/drogon_callbacks.h>
#include <trantor/utils/NonCopyable.h>
#include <atomic>
#include <map>
#include <memory>
#include <mutex>
#include <regex>
#include <string>
#include <unordered_map>
#include <vector>
namespace drogon {
class HttpControllersRouter : public trantor::NonCopyable {
public:
HttpControllersRouter(
StaticFileRouter &router,
const std::vector<std::function<void(const HttpRequestPtr &,
AdviceCallback &&,
AdviceChainCallback &&)> >
&postRoutingAdvices,
const std::vector<std::function<void(const HttpRequestPtr &)> >
&postRoutingObservers,
const std::vector<std::function<void(const HttpRequestPtr &,
AdviceCallback &&,
AdviceChainCallback &&)> >
&preHandlingAdvices,
const std::vector<std::function<void(const HttpRequestPtr &)> >
&preHandlingObservers,
const std::vector<std::function<void(const HttpRequestPtr &,
const HttpResponsePtr &)> >
&postHandlingAdvices) :
fileRouter_(router),
postRoutingAdvices_(postRoutingAdvices),
preHandlingAdvices_(preHandlingAdvices),
postRoutingObservers_(postRoutingObservers),
preHandlingObservers_(preHandlingObservers),
postHandlingAdvices_(postHandlingAdvices) {
}
void init(const std::vector<trantor::EventLoop *> &ioLoops);
void addHttpPath(const std::string &path,
const internal::HttpBinderBasePtr &binder,
const std::vector<HttpMethod> &validMethods,
const std::vector<std::string> &filters,
const std::string &handlerName = "");
void addHttpRegex(const std::string &regExp,
const internal::HttpBinderBasePtr &binder,
const std::vector<HttpMethod> &validMethods,
const std::vector<std::string> &filters,
const std::string &handlerName = "");
void route(const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback);
std::vector<std::tuple<std::string, HttpMethod, std::string> >
getHandlersInfo() const;
private:
StaticFileRouter &fileRouter_;
struct CtrlBinder {
internal::HttpBinderBasePtr binderPtr_;
std::string handlerName_;
std::vector<std::string> filterNames_;
std::vector<std::shared_ptr<HttpFilterBase> > filters_;
std::vector<size_t> parameterPlaces_;
std::vector<std::pair<std::string, size_t> > queryParametersPlaces_;
IOThreadStorage<HttpResponsePtr> responseCache_;
bool isCORS_{ false };
};
using CtrlBinderPtr = std::shared_ptr<CtrlBinder>;
struct HttpControllerRouterItem {
std::string pathParameterPattern_;
std::string pathPattern_;
std::regex regex_;
CtrlBinderPtr binders_[Invalid]{
nullptr
}; // The enum value of Invalid is the http methods number
};
std::unordered_map<std::string, HttpControllerRouterItem> ctrlMap_;
std::vector<HttpControllerRouterItem> ctrlVector_;
const std::vector<std::function<void(const HttpRequestPtr &,
AdviceCallback &&,
AdviceChainCallback &&)> >
&postRoutingAdvices_;
const std::vector<std::function<void(const HttpRequestPtr &,
AdviceCallback &&,
AdviceChainCallback &&)> >
&preHandlingAdvices_;
const std::vector<std::function<void(const HttpRequestPtr &)> >
&postRoutingObservers_;
const std::vector<std::function<void(const HttpRequestPtr &)> >
&preHandlingObservers_;
const std::vector<
std::function<void(const HttpRequestPtr &, const HttpResponsePtr &)> >
&postHandlingAdvices_;
void doPreHandlingAdvices(
const CtrlBinderPtr &ctrlBinderPtr,
const HttpControllerRouterItem &routerItem,
const HttpRequestImplPtr &req,
std::smatch &&matchResult,
std::function<void(const HttpResponsePtr &)> &&callback);
void doControllerHandler(
const CtrlBinderPtr &ctrlBinderPtr,
const HttpControllerRouterItem &routerItem,
const HttpRequestImplPtr &req,
const std::smatch &matchResult,
std::function<void(const HttpResponsePtr &)> &&callback);
void invokeCallback(
const std::function<void(const HttpResponsePtr &)> &callback,
const HttpRequestImplPtr &req,
const HttpResponsePtr &resp);
void doWhenNoHandlerFound(
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback);
};
} // namespace drogon

View File

@ -43,12 +43,13 @@ static inline void doResponseCreateAdvices(
}
static inline HttpResponsePtr genHttpResponse(const std::string &viewName,
const HttpViewData &data) {
/*
auto templ = DrTemplateBase::newTemplate(viewName);
if (templ) {
auto res = HttpResponse::newHttpResponse();
res->setBody(templ->genText(data));
return res;
}
}*/
return drogon::HttpResponse::newNotFoundResponse();
}
} // namespace drogon

View File

@ -1,343 +0,0 @@
/**
*
* @file HttpSimpleControllersRouter.cc
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#include "HttpSimpleControllersRouter.h"
#include "AOPAdvice.h"
#include "FiltersFunction.h"
#include "HttpAppFrameworkImpl.h"
#include "HttpControllersRouter.h"
#include "HttpRequestImpl.h"
#include "HttpResponseImpl.h"
#include <drogon/HttpSimpleController.h>
#include <drogon/utils/HttpConstraint.h>
using namespace drogon;
void HttpSimpleControllersRouter::registerHttpSimpleController(
const std::string &pathName,
const std::string &ctrlName,
const std::vector<internal::HttpConstraint> &filtersAndMethods) {
assert(!pathName.empty());
assert(!ctrlName.empty());
std::string path(pathName);
std::transform(pathName.begin(), pathName.end(), path.begin(), tolower);
std::lock_guard<std::mutex> guard(simpleCtrlMutex_);
std::vector<HttpMethod> validMethods;
std::vector<std::string> filters;
for (auto const &filterOrMethod : filtersAndMethods) {
if (filterOrMethod.type() == internal::ConstraintType::HttpFilter) {
filters.push_back(filterOrMethod.getFilterName());
} else if (filterOrMethod.type() == internal::ConstraintType::HttpMethod) {
validMethods.push_back(filterOrMethod.getHttpMethod());
} else {
LOG_ERROR << "Invalid controller constraint type";
exit(1);
}
}
auto &item = simpleCtrlMap_[path];
auto binder = std::make_shared<CtrlBinder>();
binder->controllerName_ = ctrlName;
binder->filterNames_ = filters;
drogon::app().getLoop()->queueInLoop([binder, ctrlName]() {
auto &object_ = DrClassMap::getSingleInstance(ctrlName);
auto controller =
std::dynamic_pointer_cast<HttpSimpleControllerBase>(object_);
binder->controller_ = controller;
// Recreate this with the correct number of threads.
binder->responseCache_ = IOThreadStorage<HttpResponsePtr>();
});
if (validMethods.size() > 0) {
for (auto const &method : validMethods) {
item.binders_[method] = binder;
if (method == Options) {
binder->isCORS_ = true;
}
}
} else {
// All HTTP methods are valid
for (size_t i = 0; i < Invalid; ++i) {
item.binders_[i] = binder;
}
binder->isCORS_ = true;
}
}
void HttpSimpleControllersRouter::route(
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback) {
std::string pathLower(req->path().length(), 0);
std::transform(req->path().begin(),
req->path().end(),
pathLower.begin(),
tolower);
auto iter = simpleCtrlMap_.find(pathLower);
if (iter != simpleCtrlMap_.end()) {
auto &ctrlInfo = iter->second;
req->setMatchedPathPattern(iter->first);
auto &binder = ctrlInfo.binders_[req->method()];
if (!binder) {
// Invalid Http Method
if (req->method() != Options) {
callback(app().getCustomErrorHandler()(k405MethodNotAllowed));
} else {
callback(app().getCustomErrorHandler()(k403Forbidden));
}
return;
}
// Do post routing advices.
if (!postRoutingObservers_.empty()) {
for (auto &observer : postRoutingObservers_) {
observer(req);
}
}
auto &filters = ctrlInfo.binders_[req->method()]->filters_;
if (postRoutingAdvices_.empty()) {
if (!filters.empty()) {
auto callbackPtr = std::make_shared<
std::function<void(const HttpResponsePtr &)> >(
std::move(callback));
filters_function::doFilters(
filters,
req,
callbackPtr,
[this, &ctrlInfo, req, callbackPtr, &binder]() mutable {
doPreHandlingAdvices(binder,
ctrlInfo,
req,
std::move(*callbackPtr));
});
} else {
doPreHandlingAdvices(binder,
ctrlInfo,
req,
std::move(callback));
}
return;
} else {
auto callbackPtr =
std::make_shared<std::function<void(const HttpResponsePtr &)> >(
std::move(callback));
doAdvicesChain(
postRoutingAdvices_,
0,
req,
callbackPtr,
[callbackPtr,
&filters,
req,
&ctrlInfo,
this,
&binder]() mutable {
if (!filters.empty()) {
filters_function::doFilters(
filters,
req,
callbackPtr,
[this,
&ctrlInfo,
req,
callbackPtr,
&binder]() mutable {
doPreHandlingAdvices(binder,
ctrlInfo,
req,
std::move(*callbackPtr));
});
} else {
doPreHandlingAdvices(binder,
ctrlInfo,
req,
std::move(*callbackPtr));
}
});
}
return;
}
httpCtrlsRouter_.route(req, std::move(callback));
}
void HttpSimpleControllersRouter::doControllerHandler(
const CtrlBinderPtr &ctrlBinderPtr,
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback) {
auto &controller = ctrlBinderPtr->controller_;
if (controller) {
auto &responsePtr = *(ctrlBinderPtr->responseCache_);
if (responsePtr) {
if (responsePtr->expiredTime() == 0 ||
(trantor::Date::now() <
responsePtr->creationDate().after(
static_cast<double>(responsePtr->expiredTime())))) {
// use cached response!
LOG_TRACE << "Use cached response";
invokeCallback(callback, req, responsePtr);
return;
} else {
responsePtr.reset();
}
}
try {
controller->asyncHandleHttpRequest(
req,
[this, req, callback, &ctrlBinderPtr](
const HttpResponsePtr &resp) {
auto newResp = resp;
if (resp->expiredTime() >= 0 &&
resp->statusCode() != k404NotFound) {
// cache the response;
static_cast<HttpResponseImpl *>(resp.get())
->makeHeaderString();
auto loop = req->getLoop();
if (loop->isInLoopThread()) {
ctrlBinderPtr->responseCache_.setThreadData(resp);
} else {
loop->queueInLoop([resp, &ctrlBinderPtr]() {
ctrlBinderPtr->responseCache_.setThreadData(
resp);
});
}
}
invokeCallback(callback, req, newResp);
});
} catch (const std::exception &e) {
app().getExceptionHandler()(e, req, std::move(callback));
return;
} catch (...) {
LOG_ERROR << "Exception not derived from std::exception";
return;
}
return;
} else {
const std::string &ctrlName = ctrlBinderPtr->controllerName_;
LOG_ERROR << "can't find controller " << ctrlName;
auto res = drogon::HttpResponse::newNotFoundResponse();
invokeCallback(callback, req, res);
}
}
std::vector<std::tuple<std::string, HttpMethod, std::string> >
HttpSimpleControllersRouter::getHandlersInfo() const {
std::vector<std::tuple<std::string, HttpMethod, std::string> > ret;
for (auto &item : simpleCtrlMap_) {
for (size_t i = 0; i < Invalid; ++i) {
if (item.second.binders_[i]) {
auto info = std::tuple<std::string, HttpMethod, std::string>(
item.first,
(HttpMethod)i,
std::string("HttpSimpleController: ") +
item.second.binders_[i]->controllerName_);
ret.emplace_back(std::move(info));
}
}
}
return ret;
}
void HttpSimpleControllersRouter::init(
const std::vector<trantor::EventLoop *> & /*ioLoops*/) {
for (auto &iter : simpleCtrlMap_) {
auto &item = iter.second;
for (size_t i = 0; i < Invalid; ++i) {
auto &binder = item.binders_[i];
if (binder) {
binder->filters_ =
filters_function::createFilters(binder->filterNames_);
}
}
}
}
void HttpSimpleControllersRouter::doPreHandlingAdvices(
const CtrlBinderPtr &ctrlBinderPtr,
const SimpleControllerRouterItem &routerItem,
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback) {
if (req->method() == Options) {
auto resp = HttpResponse::newHttpResponse();
resp->setContentTypeCode(ContentType::CT_TEXT_PLAIN);
std::string methods = "OPTIONS,";
if (routerItem.binders_[Get] && routerItem.binders_[Get]->isCORS_) {
methods.append("GET,HEAD,");
}
if (routerItem.binders_[Post] && routerItem.binders_[Post]->isCORS_) {
methods.append("POST,");
}
if (routerItem.binders_[Put] && routerItem.binders_[Put]->isCORS_) {
methods.append("PUT,");
}
if (routerItem.binders_[Delete] && routerItem.binders_[Delete]->isCORS_) {
methods.append("DELETE,");
}
if (routerItem.binders_[Patch] && routerItem.binders_[Patch]->isCORS_) {
methods.append("PATCH,");
}
methods.resize(methods.length() - 1);
resp->addHeader("ALLOW", methods);
auto &origin = req->getHeader("Origin");
if (origin.empty()) {
resp->addHeader("Access-Control-Allow-Origin", "*");
} else {
resp->addHeader("Access-Control-Allow-Origin", origin);
}
resp->addHeader("Access-Control-Allow-Methods", methods);
auto &headers = req->getHeaderBy("access-control-request-headers");
if (!headers.empty()) {
resp->addHeader("Access-Control-Allow-Headers", headers);
}
callback(resp);
return;
}
if (!preHandlingObservers_.empty()) {
for (auto &observer : preHandlingObservers_) {
observer(req);
}
}
if (preHandlingAdvices_.empty()) {
doControllerHandler(ctrlBinderPtr, req, std::move(callback));
} else {
auto callbackPtr =
std::make_shared<std::function<void(const HttpResponsePtr &)> >(
std::move(callback));
doAdvicesChain(
preHandlingAdvices_,
0,
req,
std::make_shared<std::function<void(const HttpResponsePtr &)> >(
[req, callbackPtr](const HttpResponsePtr &resp) {
HttpAppFrameworkImpl::instance().callCallback(req,
resp,
*callbackPtr);
}),
[this, ctrlBinderPtr, req, callbackPtr]() {
doControllerHandler(ctrlBinderPtr,
req,
std::move(*callbackPtr));
});
}
}
void HttpSimpleControllersRouter::invokeCallback(
const std::function<void(const HttpResponsePtr &)> &callback,
const HttpRequestImplPtr &req,
const HttpResponsePtr &resp) {
for (auto &advice : postHandlingAdvices_) {
advice(req, resp);
}
HttpAppFrameworkImpl::instance().callCallback(req, resp, callback);
}

View File

@ -1,120 +0,0 @@
/**
*
* HttpSimpleControllersRouter.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include "impl_forwards.h"
#include <drogon/IOThreadStorage.h>
#include <drogon/drogon_callbacks.h>
#include <drogon/utils/HttpConstraint.h>
#include <trantor/utils/NonCopyable.h>
#include <atomic>
#include <map>
#include <memory>
#include <mutex>
#include <regex>
#include <shared_mutex>
#include <string>
#include <unordered_map>
#include <vector>
namespace drogon {
class HttpSimpleControllersRouter : public trantor::NonCopyable {
public:
HttpSimpleControllersRouter(
HttpControllersRouter &httpCtrlRouter,
const std::vector<std::function<void(const HttpRequestPtr &,
AdviceCallback &&,
AdviceChainCallback &&)> >
&postRoutingAdvices,
const std::vector<std::function<void(const HttpRequestPtr &)> >
&postRoutingObservers,
const std::vector<std::function<void(const HttpRequestPtr &,
AdviceCallback &&,
AdviceChainCallback &&)> >
&preHandlingAdvices,
const std::vector<std::function<void(const HttpRequestPtr &)> >
&preHandlingObservers,
const std::vector<std::function<void(const HttpRequestPtr &,
const HttpResponsePtr &)> >
&postHandlingAdvices) :
httpCtrlsRouter_(httpCtrlRouter),
postRoutingAdvices_(postRoutingAdvices),
preHandlingAdvices_(preHandlingAdvices),
postRoutingObservers_(postRoutingObservers),
preHandlingObservers_(preHandlingObservers),
postHandlingAdvices_(postHandlingAdvices) {
}
void registerHttpSimpleController(
const std::string &pathName,
const std::string &ctrlName,
const std::vector<internal::HttpConstraint> &filtersAndMethods);
void route(const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback);
void init(const std::vector<trantor::EventLoop *> &ioLoops);
std::vector<std::tuple<std::string, HttpMethod, std::string> >
getHandlersInfo() const;
private:
HttpControllersRouter &httpCtrlsRouter_;
const std::vector<std::function<void(const HttpRequestPtr &,
AdviceCallback &&,
AdviceChainCallback &&)> >
&postRoutingAdvices_;
const std::vector<std::function<void(const HttpRequestPtr &,
AdviceCallback &&,
AdviceChainCallback &&)> >
&preHandlingAdvices_;
const std::vector<std::function<void(const HttpRequestPtr &)> >
&postRoutingObservers_;
const std::vector<std::function<void(const HttpRequestPtr &)> >
&preHandlingObservers_;
const std::vector<
std::function<void(const HttpRequestPtr &, const HttpResponsePtr &)> >
&postHandlingAdvices_;
struct CtrlBinder {
std::shared_ptr<HttpSimpleControllerBase> controller_;
std::string controllerName_;
std::vector<std::string> filterNames_;
std::vector<std::shared_ptr<HttpFilterBase> > filters_;
IOThreadStorage<HttpResponsePtr> responseCache_;
bool isCORS_{ false };
};
using CtrlBinderPtr = std::shared_ptr<CtrlBinder>;
struct SimpleControllerRouterItem {
CtrlBinderPtr binders_[Invalid];
};
std::unordered_map<std::string, SimpleControllerRouterItem> simpleCtrlMap_;
std::mutex simpleCtrlMutex_;
void doPreHandlingAdvices(
const CtrlBinderPtr &ctrlBinderPtr,
const SimpleControllerRouterItem &routerItem,
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback);
void doControllerHandler(
const CtrlBinderPtr &ctrlBinderPtr,
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback);
void invokeCallback(
const std::function<void(const HttpResponsePtr &)> &callback,
const HttpRequestImplPtr &req,
const HttpResponsePtr &resp);
};
} // namespace drogon

View File

@ -1,50 +0,0 @@
// this file is generated by program automatically,don't modify it!
/**
*
* NotFound.cc
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#include <drogon/NotFound.h>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace drogon;
std::string NotFound::genText(const HttpViewData &NotFound_view_data) {
std::stringstream NotFound_tmp_stream;
NotFound_tmp_stream << "<html>\n";
NotFound_tmp_stream << "<head><title>404 Not Found</title></head>\n";
NotFound_tmp_stream << "<body bgcolor=\"white\">\n";
NotFound_tmp_stream << "<center><h1>404 Not Found</h1></center>\n";
NotFound_tmp_stream << "<hr><center>drogon/";
NotFound_tmp_stream << NotFound_view_data.get<std::string>("version");
NotFound_tmp_stream << "</center>\n";
NotFound_tmp_stream << "</body>\n";
NotFound_tmp_stream << "</html>\n";
NotFound_tmp_stream << "<!-- a padding to disable MSIE and Chrome friendly "
"error page -->\n";
NotFound_tmp_stream << "<!-- a padding to disable MSIE and Chrome friendly "
"error page -->\n";
NotFound_tmp_stream << "<!-- a padding to disable MSIE and Chrome friendly "
"error page -->\n";
NotFound_tmp_stream << "<!-- a padding to disable MSIE and Chrome friendly "
"error page -->\n";
NotFound_tmp_stream << "<!-- a padding to disable MSIE and Chrome friendly "
"error page -->\n";
NotFound_tmp_stream << "<!-- a padding to disable MSIE and Chrome friendly "
"error page -->\n";
return NotFound_tmp_stream.str();
}

View File

@ -56,10 +56,12 @@ void PluginsManager::initializeAllPlugins(
}
}
}
pluginPtr->setInitializedCallback([this](PluginBase *p) {
LOG_TRACE << "Plugin " << p->className() << " initialized!";
//LOG_TRACE << "Plugin " << p->className() << " initialized!";
initializedPlugins_.push_back(p);
});
plugins.push_back(pluginPtr);
}
// Initialize them, Depth first
@ -70,6 +72,8 @@ void PluginsManager::initializeAllPlugins(
}
PluginBase *PluginsManager::getPlugin(const std::string &pluginName) {
/*
auto iter = pluginsMap_.find(pluginName);
if (iter == pluginsMap_.end()) {
auto *p = DrClassMap::newObject(pluginName);
@ -85,5 +89,8 @@ PluginBase *PluginsManager::getPlugin(const std::string &pluginName) {
} else {
return iter->second.get();
}
*/
return nullptr;
}

View File

@ -136,7 +136,7 @@ void StaticFileRouter::route(
}
}
}
/*
if (location.filters_.empty()) {
sendStaticFileResponse(filePath,
req,
@ -144,9 +144,11 @@ void StaticFileRouter::route(
string_view{
location.defaultContentType_ });
} else {
auto callbackPtr = std::make_shared<
std::function<void(const drogon::HttpResponsePtr &)> >(
std::move(callback));
filters_function::doFilters(
location.filters_,
req,
@ -161,7 +163,7 @@ void StaticFileRouter::route(
std::move(*callbackPtr),
string_view{ contentType });
});
}
}*/
return;
}
@ -205,6 +207,7 @@ void StaticFileRouter::sendStaticFileResponse(
const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
const string_view &defaultContentType) { // find cached response
HttpResponsePtr cachedResp;
auto &cacheMap = staticFilesCache_->getThreadData();
auto iter = cacheMap.find(filePath);

View File

@ -14,7 +14,6 @@
#pragma once
#include "FiltersFunction.h"
#include "impl_forwards.h"
#include <drogon/CacheMap.h>
#include <drogon/IOThreadStorage.h>
@ -123,7 +122,9 @@ private:
std::vector<std::pair<std::string, std::string> > headers_;
bool implicitPageEnable_{ true };
std::string implicitPage_{ "index.html" };
DefaultHandler defaultHandler_ = StaticFileRouter::defaultHandler;
struct Location {
std::string uriPrefix_;
std::string defaultContentType_;
@ -132,7 +133,8 @@ private:
bool isCaseSensitive_;
bool allowAll_;
bool isRecursive_;
std::vector<std::shared_ptr<drogon::HttpFilterBase> > filters_;
//std::vector<std::shared_ptr<drogon::HttpFilterBase> > filters_;
Location(const std::string &uriPrefix,
const std::string &defaultContentType,
const std::string &alias,
@ -144,13 +146,14 @@ private:
alias_(alias),
isCaseSensitive_(isCaseSensitive),
allowAll_(allowAll),
isRecursive_(isRecursive),
filters_(filters_function::createFilters(filters)) {
if (!defaultContentType.empty()) {
defaultContentType_ =
std::string{ "content-type: " } + defaultContentType + "\r\n";
}
}
isRecursive_(isRecursive)
/*filters_(filters_function::createFilters(filters))*/ {
if (!defaultContentType.empty()) {
defaultContentType_ =
std::string{ "content-type: " } + defaultContentType + "\r\n";
}
}
};
std::unique_ptr<IOThreadStorage<std::vector<Location> > > ioLocationsPtr_;
std::vector<Location> locations_;

View File

@ -14,12 +14,10 @@
#include "WebsocketControllersRouter.h"
#include "AOPAdvice.h"
#include "FiltersFunction.h"
#include "HttpRequestImpl.h"
#include "HttpResponseImpl.h"
#include "WebSocketConnectionImpl.h"
#include <drogon/HttpFilter.h>
#include <drogon/WebSocketController.h>
#include <drogon/config.h>
#ifdef OpenSSL_FOUND
#include <openssl/sha.h>
@ -52,12 +50,15 @@ void WebsocketControllersRouter::registerWebSocketController(
auto binder = std::make_shared<CtrlBinder>();
binder->controllerName_ = ctrlName;
binder->filterNames_ = filters;
/*
drogon::app().getLoop()->queueInLoop([binder, ctrlName]() {
auto &object_ = DrClassMap::getSingleInstance(ctrlName);
auto controller =
std::dynamic_pointer_cast<WebSocketControllerBase>(object_);
binder->controller_ = controller;
});
});*/
if (validMethods.size() > 0) {
for (auto const &method : validMethods) {
@ -90,6 +91,8 @@ void WebsocketControllersRouter::route(
if (iter != wsCtrlMap_.end()) {
auto &ctrlInfo = iter->second;
req->setMatchedPathPattern(iter->first);
/*
auto &binder = ctrlInfo.binders_[req->method()];
if (!binder) {
// Invalid Http Method
@ -101,12 +104,17 @@ void WebsocketControllersRouter::route(
}
return;
}
*/
// Do post routing advices.
if (!postRoutingObservers_.empty()) {
for (auto &observer : postRoutingObservers_) {
observer(req);
}
}
/*
auto &filters = ctrlInfo.binders_[req->method()]->filters_;
if (postRoutingAdvices_.empty()) {
if (!filters.empty()) {
@ -176,6 +184,8 @@ void WebsocketControllersRouter::route(
}
});
}
*/
return;
}
}
@ -187,6 +197,7 @@ void WebsocketControllersRouter::route(
std::vector<std::tuple<std::string, HttpMethod, std::string> >
WebsocketControllersRouter::getHandlersInfo() const {
std::vector<std::tuple<std::string, HttpMethod, std::string> > ret;
/*
for (auto &item : wsCtrlMap_) {
for (size_t i = 0; i < Invalid; ++i) {
if (item.second.binders_[i]) {
@ -198,7 +209,7 @@ WebsocketControllersRouter::getHandlersInfo() const {
ret.emplace_back(std::move(info));
}
}
}
}*/
return ret;
}
@ -257,29 +268,34 @@ void WebsocketControllersRouter::doControllerHandler(
resp->addHeader("Sec-WebSocket-Accept", base64Key);
callback(resp);
auto ctrlPtr = routerItem.binders_[req->method()]->controller_;
/*
wsConnPtr->setMessageCallback(
[ctrlPtr](std::string &&message,
const WebSocketConnectionImplPtr &connPtr,
const WebSocketMessageType &type) {
ctrlPtr->handleNewMessage(connPtr, std::move(message), type);
});
wsConnPtr->setCloseCallback(
[ctrlPtr](const WebSocketConnectionImplPtr &connPtr) {
ctrlPtr->handleConnectionClosed(connPtr);
});
ctrlPtr->handleNewConnection(req, wsConnPtr);
*/
return;
}
void WebsocketControllersRouter::init() {
/*
for (auto &iter : wsCtrlMap_) {
auto &item = iter.second;
for (size_t i = 0; i < Invalid; ++i) {
auto &binder = item.binders_[i];
if (binder) {
binder->filters_ =
filters_function::createFilters(binder->filterNames_);
binder->filters_ = filters_function::createFilters(binder->filterNames_);
}
}
}
*/
}

View File

@ -26,9 +26,7 @@ class WebSocketConnectionImpl;
using WebSocketConnectionImplPtr = std::shared_ptr<WebSocketConnectionImpl>;
class HttpRequestParser;
class StaticFileRouter;
class HttpControllersRouter;
class WebsocketControllersRouter;
class HttpSimpleControllersRouter;
class PluginsManager;
class ListenerManager;
class SharedLibManager;