GithubHelp home page GithubHelp logo

drogonframework / drogon Goto Github PK

View Code? Open in Web Editor NEW
10.8K 207.0 1.0K 5.35 MB

Drogon: A C++14/17/20 based HTTP web application framework running on Linux/macOS/Unix/Windows

License: MIT License

CMake 2.94% C++ 95.86% Shell 0.27% Dockerfile 0.10% HTML 0.77% C 0.07%
linux http-framework http-server http drogon non-blocking-io asynchronous-programming

drogon's Introduction

Build Status Join the chat at https://gitter.im/drogon-web/community Join the telegram group at https://t.me/joinchat/_mMNGv0748ZkMDAx Join our Discord Docker image

English | 简体中文 | 繁體中文

Overview

Drogon is a C++17/20 based HTTP application framework. Drogon can be used to easily build various types of web application server programs using C++. Drogon is the name of a dragon in the American TV series "Game of Thrones" that I really like.

Drogon is a cross-platform framework, It supports Linux, macOS, FreeBSD, OpenBSD, HaikuOS, and Windows. Its main features are as follows:

  • Use a non-blocking I/O network lib based on epoll (kqueue under macOS/FreeBSD) to provide high-concurrency, high-performance network IO, please visit the TFB Tests Results for more details;
  • Provide a completely asynchronous programming mode;
  • Support Http1.0/1.1 (server side and client side);
  • Based on template, a simple reflection mechanism is implemented to completely decouple the main program framework, controllers and views.
  • Support cookies and built-in sessions;
  • Support back-end rendering, the controller generates the data to the view to generate the Html page. Views are described by CSP template files, C++ codes are embedded into Html pages through CSP tags. And the drogon command-line tool automatically generates the C++ code files for compilation;
  • Support view page dynamic loading (dynamic compilation and loading at runtime);
  • Provide a convenient and flexible routing solution from the path to the controller handler;
  • Support filter chains to facilitate the execution of unified logic (such as login verification, Http Method constraint verification, etc.) before handling HTTP requests;
  • Support https (based on OpenSSL);
  • Support WebSocket (server side and client side);
  • Support JSON format request and response, very friendly to the Restful API application development;
  • Support file download and upload;
  • Support gzip, brotli compression transmission;
  • Support pipelining;
  • Provide a lightweight command line tool, drogon_ctl, to simplify the creation of various classes in Drogon and the generation of view code;
  • Support non-blocking I/O based asynchronously reading and writing database (PostgreSQL and MySQL(MariaDB) database);
  • Support asynchronously reading and writing sqlite3 database based on thread pool;
  • Support Redis with asynchronous reading and writing;
  • Support ARM Architecture;
  • Provide a convenient lightweight ORM implementation that supports for regular object-to-database bidirectional mapping;
  • Support plugins which can be installed by the configuration file at load time;
  • Support AOP with built-in joinpoints.
  • Support C++ coroutines

A very simple example

Unlike most C++ frameworks, the main program of the drogon application can be kept clean and simple. Drogon uses a few tricks to decouple controllers from the main program. The routing settings of controllers can be done through macros or configuration file.

Below is the main program of a typical drogon application:

#include <drogon/drogon.h>
using namespace drogon;
int main()
{
    app().setLogPath("./")
         .setLogLevel(trantor::Logger::kWarn)
         .addListener("0.0.0.0", 80)
         .setThreadNum(16)
         .enableRunAsDaemon()
         .run();
}

It can be further simplified by using configuration file as follows:

#include <drogon/drogon.h>
using namespace drogon;
int main()
{
    app().loadConfigFile("./config.json").run();
}

Drogon provides some interfaces for adding controller logic directly in the main() function, for example, user can register a handler like this in Drogon:

app().registerHandler("/test?username={name}",
                    [](const HttpRequestPtr& req,
                       std::function<void (const HttpResponsePtr &)> &&callback,
                       const std::string &name)
                    {
                        Json::Value json;
                        json["result"]="ok";
                        json["message"]=std::string("hello,")+name;
                        auto resp=HttpResponse::newHttpJsonResponse(json);
                        callback(resp);
                    },
                    {Get,"LoginFilter"});

While such interfaces look intuitive, they are not suitable for complex business logic scenarios. Assuming there are tens or even hundreds of handlers that need to be registered in the framework, isn't it a better practice to implement them separately in their respective classes? So unless your logic is very simple, we don't recommend using above interfaces. Instead, we can create an HttpSimpleController as follows:

/// The TestCtrl.h file
#pragma once
#include <drogon/HttpSimpleController.h>
using namespace drogon;
class TestCtrl:public drogon::HttpSimpleController<TestCtrl>
{
public:
    void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
    PATH_LIST_BEGIN
    PATH_ADD("/test",Get);
    PATH_LIST_END
};

/// The TestCtrl.cc file
#include "TestCtrl.h"
void TestCtrl::asyncHandleHttpRequest(const HttpRequestPtr& req,
                                      std::function<void (const HttpResponsePtr &)> &&callback)
{
    //write your application logic here
    auto resp = HttpResponse::newHttpResponse();
    resp->setBody("<p>Hello, world!</p>");
    resp->setExpiredTime(0);
    callback(resp);
}

Most of the above programs can be automatically generated by the command line tool drogon_ctl provided by drogon (The command is drogon_ctl create controller TestCtrl). All the user needs to do is add their own business logic. In the example, the controller returns a Hello, world! string when the client accesses the http://ip/test URL.

For JSON format response, we create the controller as follows:

/// The header file
#pragma once
#include <drogon/HttpSimpleController.h>
using namespace drogon;
class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
{
  public:
    void asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) override;
    PATH_LIST_BEGIN
    //list path definitions here;
    PATH_ADD("/json", Get);
    PATH_LIST_END
};

/// The source file
#include "JsonCtrl.h"
void JsonCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req,
                                      std::function<void(const HttpResponsePtr &)> &&callback)
{
    Json::Value ret;
    ret["message"] = "Hello, World!";
    auto resp = HttpResponse::newHttpJsonResponse(ret);
    callback(resp);
}

Let's go a step further and create a demo RESTful API with the HttpController class, as shown below (Omit the source file):

/// The header file
#pragma once
#include <drogon/HttpController.h>
using namespace drogon;
namespace api
{
namespace v1
{
class User : public drogon::HttpController<User>
{
  public:
    METHOD_LIST_BEGIN
    //use METHOD_ADD to add your custom processing function here;
    METHOD_ADD(User::getInfo, "/{id}", Get);                  //path is /api/v1/User/{arg1}
    METHOD_ADD(User::getDetailInfo, "/{id}/detailinfo", Get);  //path is /api/v1/User/{arg1}/detailinfo
    METHOD_ADD(User::newUser, "/{name}", Post);                 //path is /api/v1/User/{arg1}
    METHOD_LIST_END
    //your declaration of processing function maybe like this:
    void getInfo(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, int userId) const;
    void getDetailInfo(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, int userId) const;
    void newUser(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, std::string &&userName);
  public:
    User()
    {
        LOG_DEBUG << "User constructor!";
    }
};
} // namespace v1
} // namespace api

As you can see, users can use the HttpController to map paths and parameters at the same time. This is a very convenient way to create a RESTful API application.

In addition, you can also find that all handler interfaces are in asynchronous mode, where the response is returned by a callback object. This design is for performance reasons because in asynchronous mode the drogon application can handle a large number of concurrent requests with a small number of threads.

After compiling all of the above source files, we get a very simple web application. This is a good start. For more information, please visit the wiki

Cross-compilation

Drogon supports cross-compilation, you should define the CMAKE_SYSTEM_NAME in toolchain file, for example:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

You can disable building options for examples and drogon_ctl by settings BUILD_EXAMPLES and BUILD_CTL to OFF in the toolchain file.

Building options

Drogon provides some building options, you can enable or disable them by setting the corresponding variables to ON or OFF in the cmake command line, cmake file etc...

Option name Description Default value
BUILD_CTL Build drogon_ctl ON
BUILD_EXAMPLES Build examples ON
BUILD_ORM Build orm ON
COZ_PROFILING Use coz for profiling OFF
BUILD_SHARED_LIBS Build drogon as a shared lib OFF
BUILD_DOC Build Doxygen documentation OFF
BUILD_BROTLI Build Brotli ON
BUILD_YAML_CONFIG Build yaml config ON
USE_SUBMODULE Use trantor as a submodule ON

Contributions

This project exists thanks to all the people who contribute code.

Code contributors

Every contribution is welcome. Please refer to the contribution guidelines for more information.

drogon's People

Contributors

0rangefox avatar albaropereyra22 avatar an-tao avatar antores avatar bansan85 avatar bertrandd avatar dependabot[bot] avatar fantasy-peak avatar greisby avatar hadesd avatar haydenzhourepo avatar hwc0919 avatar ihmc3jn09hk avatar interfector18 avatar itgenie98 avatar ivanka2012 avatar juergengleiss avatar ken-matsui avatar marty1885 avatar mensinda avatar mis1eader-dev avatar omarmohamedkh avatar pkovacs avatar rbugajewski avatar roq3 avatar tanglong3bf avatar tao-an avatar taoan avatar timomrs avatar vayudev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

drogon's Issues

如果通過 request payload 提交信息,拿不到值

目前的獲取提交的數據的方法,有 get, post,
但是在 post 方法下, 使用 from 提交可以拿到值,但是使用 post/body 方式提交的,則無法獲取到值

如果使用 request->getJsonObject();

拿到的是一個空指針, 不知道是我獲取的方式問題,還是框架目前不支持 body 方式?

<%view %> code block can't start at new line

when I put <%view %> code block at new line, as below:

The father csp
<%view child %>

the error comes out:

[ 14%] Generating father.h, father.cc
create view:/mnt/d/mytest/views/father.csp
create HttpView Class file by /mnt/d/mytest/views/father.csp
className=father
Scanning dependencies of target mytest
[ 28%] Building CXX object CMakeFiles/mytest.dir/father.cc.o
/mnt/d/mytest/build/father.cc:25:23: warning: missing terminating " character
\n";ther_tmp_stream << "
                       ^
/mnt/d/mytest/build/father.cc:25:23: error: missing terminating " character
/mnt/d/mytest/build/father.cc:26:1: error: stray ‘\’ in program
  father_tmp_stream << "This is father\n";
 ^
/mnt/d/mytest/build/father.cc:26:3: warning: missing terminating " character
  father_tmp_stream << "This is father\n";
   ^
/mnt/d/mytest/build/father.cc:26:3: error: missing terminating " character
  father_tmp_stream << "This is father\n";
   ^~
/mnt/d/mytest/build/father.cc: In member function ‘virtual std::string father::genText(const DrTemplateData&)’:
/mnt/d/mytest/build/father.cc:26:2: error: ‘n’ was not declared in this scope
  father_tmp_stream << "This is father\n";
  ^
CMakeFiles/mytest.dir/build.make:115: recipe for target 'CMakeFiles/mytest.dir/father.cc.o' failed
make[2]: *** [CMakeFiles/mytest.dir/father.cc.o] Error 1
CMakeFiles/Makefile2:75: recipe for target 'CMakeFiles/mytest.dir/all' failed
make[1]: *** [CMakeFiles/mytest.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

but, if it end with the pre line, it works.

The father csp<%view child %>

Missing atomic link

When compiling, g++ reports that the atomic library is missing in drogon_ctl, _drogon_ctl and all the examples. This likely only happens for c++14 builds.

[53%] Linking CXX executable drogon_ctl
/usr/bin/ld: ../libdrogon.a(HttpAppFrameworkImpl.cc.o): in function `drogon::HttpAppFrameworkImpl::onConnection(std::shared_ptr<trantor::TcpConnection> const&)':
HttpAppFrameworkImpl.cc:(.text+0x2b00): undefined reference to `__atomic_load_8'
/usr/bin/ld: HttpAppFrameworkImpl.cc:(.text+0x2bac): undefined reference to `__atomic_fetch_add_8'
/usr/bin/ld: ../libdrogon.a(HttpAppFrameworkImpl.cc.o): in function `std::__atomic_base<long long>::operator--(int)':
HttpAppFrameworkImpl.cc:(.text._ZNSt13__atomic_baseIxEmmEi[_ZNSt13__atomic_baseIxEmmEi]+0x40): undefined reference to `__atomic_fetch_sub_8'
/usr/bin/ld: ../trantor/libtrantor.a(Timer.cc.o): in function `std::__atomic_base<unsigned long long>::operator++()':
Timer.cc:(.text._ZNSt13__atomic_baseIyEppEv[_ZNSt13__atomic_baseIyEppEv]+0x28): undefined reference to `__atomic_fetch_add_8'
collect2: error: ld returned 1 exit status
make[2]: *** [drogon_ctl/CMakeFiles/drogon_ctl.dir/build.make:499: drogon_ctl/drogon_ctl] Error 1
make[1]: *** [CMakeFiles/Makefile2:518: drogon_ctl/CMakeFiles/drogon_ctl.dir/all] Error 2

To fix
add target_link_libraries(drogon_ctl PUBLIC atomic) to drogon_ctl/CMakeLists.txt and to each of the examples.

Environment:

  • OS: raspberry buster and ubuntu 18.04 (with cmake altered to use c++14)
  • drogon version: latest master (456d003)

CMAKE_MODULE_PATH being overwrriten

If drogon is included as a sub-module in other project, this line overwrites top level CMAKE_MODULE_PATH which will add drogon/cmake_modules to its own CMAKE_MODULE_PATH.

https://github.com/an-tao/drogon/blob/8d251f8158c77283a2ba87d5c9f12ce63af3ea99/CMakeLists.txt#L28

I think this line would be better if it was replaced with the following?

list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules/)

or

set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules/) 

Compile Issue on Generated Models

Describe the bug
Build errors with orm generated files on debian 9.

To Reproduce
Steps to reproduce the behavior:

  1. Create MySQL database structure.
  2. Run drogon ctl command to generate
    COMPILE LOG:
Scanning dependencies of target hempeno
[  3%] Building CXX object CMakeFiles/hempeno.dir/models/Brands.cc.o
In file included from /usr/include/c++/6/bits/shared_ptr.h:52:0,
                 from /usr/include/c++/6/memory:82,
                 from /usr/local/include/drogon/orm/Result.h:20,
                 from /var/www/html/hempeno/hempeno/models/Brands.h:9,
                 from /var/www/html/hempeno/hempeno/models/Brands.cc:8:
/usr/include/c++/6/bits/shared_ptr_base.h: In instantiation of ‘std::__shared_ptr<_Tp, _Lp>& std::__shared_ptr<_Tp, _Lp>::operator=(std::__shared_ptr<_Tp1, _Lp>&&) [with _Tp1 = long unsigned int; _Tp = long int; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]’:
/usr/include/c++/6/bits/shared_ptr.h:302:4:   required from ‘std::shared_ptr<_Tp>& std::shared_ptr<_Tp>::operator=(std::shared_ptr<_Tp1>&&) [with _Tp1 = long unsigned int; _Tp = long int]’
/var/www/html/hempeno/hempeno/models/Brands.cc:112:40:   required from here
/usr/include/c++/6/bits/shared_ptr_base.h:1011:4: error: no matching function for call to ‘std::__shared_ptr<long int, (__gnu_cxx::_Lock_policy)2u>::__shared_ptr(std::remove_reference<std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>&>::type)’
    __shared_ptr(std::move(__r)).swap(*this);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:1149:7: note: candidate: std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__weak_ptr<_Tp, _Lp>&, std::nothrow_t) [with _Tp = long int; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]
       __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
       ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:1149:7: note:   candidate expects 2 arguments, 1 provided
/usr/include/c++/6/bits/shared_ptr_base.h:1097:2: note: candidate: template<class _Alloc, class ... _Args> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...)
  __shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
  ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:1097:2: note:   template argument deduction/substitution failed:
/usr/include/c++/6/bits/shared_ptr_base.h:1011:4: note:   candidate expects at least 2 arguments, 1 provided
    __shared_ptr(std::move(__r)).swap(*this);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:979:17: note: candidate: constexpr std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::nullptr_t) [with _Tp = long int; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u; std::nullptr_t = std::nullptr_t]
       constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
                 ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:979:17: note:   no known conversion for argument 1 from ‘std::remove_reference<std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>}’ to ‘std::nullptr_t’
/usr/include/c++/6/bits/shared_ptr_base.h:976:2: note: candidate: template<class _Tp1> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::auto_ptr<_Up>&&)
  __shared_ptr(std::auto_ptr<_Tp1>&& __r);
  ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:976:2: note:   template argument deduction/substitution failed:
/usr/include/c++/6/bits/shared_ptr_base.h:1011:4: note:   ‘std::remove_reference<std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>}’ is not derived from ‘std::auto_ptr<_Up>’
    __shared_ptr(std::move(__r)).swap(*this);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:964:2: note: candidate: template<class _Tp1, class _Del, class> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::unique_ptr<_Up, _Ep>&&)
  __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
  ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:964:2: note:   template argument deduction/substitution failed:
/usr/include/c++/6/bits/shared_ptr_base.h:1011:4: note:   ‘std::remove_reference<std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>}’ is not derived from ‘std::unique_ptr<_Tp, _Dp>’
    __shared_ptr(std::move(__r)).swap(*this);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:951:11: note: candidate: template<class _Tp1> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__weak_ptr<_Tp1, _Lp>&)
  explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
           ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:951:11: note:   template argument deduction/substitution failed:
/usr/include/c++/6/bits/shared_ptr_base.h:1011:4: note:   ‘std::remove_reference<std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>}’ is not derived from ‘const std::__weak_ptr<_Tp>’
    __shared_ptr(std::move(__r)).swap(*this);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:943:2: note: candidate: template<class _Tp1, class> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::__shared_ptr<_Tp1, _Lp>&&)
  __shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
  ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:943:2: note:   template argument deduction/substitution failed:
/usr/include/c++/6/bits/shared_ptr_base.h:935:7: note: candidate: std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::__shared_ptr<_Tp, _Lp>&&) [with _Tp = long int; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]
       __shared_ptr(__shared_ptr&& __r) noexcept
       ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:935:7: note:   no known conversion for argument 1 from ‘std::remove_reference<std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>}’ to ‘std::__shared_ptr<long int, (__gnu_cxx::_Lock_policy)2u>&&’
/usr/include/c++/6/bits/shared_ptr_base.h:931:2: note: candidate: template<class _Tp1, class> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__shared_ptr<_Tp1, _Lp>&)
  __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
  ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:931:2: note:   template argument deduction/substitution failed:
/usr/include/c++/6/bits/shared_ptr_base.h:926:7: note: candidate: std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__shared_ptr<_Tp, _Lp>&) [with _Tp = long int; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]
       __shared_ptr(const __shared_ptr&) noexcept = default;
       ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:926:7: note:   no known conversion for argument 1 from ‘std::remove_reference<std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>&>::type {aka std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>}’ to ‘const std::__shared_ptr<long int, (__gnu_cxx::_Lock_policy)2u>&’
/usr/include/c++/6/bits/shared_ptr_base.h:922:2: note: candidate: template<class _Tp1> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(const std::__shared_ptr<_Tp1, _Lp>&, _Tp*)
  __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) noexcept
  ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:922:2: note:   template argument deduction/substitution failed:
/usr/include/c++/6/bits/shared_ptr_base.h:1011:4: note:   candidate expects 2 arguments, 1 provided
    __shared_ptr(std::move(__r)).swap(*this);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:917:9: note: candidate: template<class _Deleter, class _Alloc> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::nullptr_t, _Deleter, _Alloc)
         __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
         ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:917:9: note:   template argument deduction/substitution failed:
/usr/include/c++/6/bits/shared_ptr_base.h:1011:4: note:   candidate expects 3 arguments, 1 provided
    __shared_ptr(std::move(__r)).swap(*this);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:912:2: note: candidate: template<class _Deleter> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::nullptr_t, _Deleter)
  __shared_ptr(nullptr_t __p, _Deleter __d)
  ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:912:2: note:   template argument deduction/substitution failed:
/usr/include/c++/6/bits/shared_ptr_base.h:1011:4: note:   candidate expects 2 arguments, 1 provided
    __shared_ptr(std::move(__r)).swap(*this);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:903:2: note: candidate: template<class _Tp1, class _Deleter, class _Alloc> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*, _Deleter, _Alloc)
  __shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
  ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:903:2: note:   template argument deduction/substitution failed:
/usr/include/c++/6/bits/shared_ptr_base.h:1011:4: note:   mismatched types ‘_Tp1*’ and ‘std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>’
    __shared_ptr(std::move(__r)).swap(*this);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:894:2: note: candidate: template<class _Tp1, class _Deleter> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*, _Deleter)
  __shared_ptr(_Tp1* __p, _Deleter __d)
  ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:894:2: note:   template argument deduction/substitution failed:
/usr/include/c++/6/bits/shared_ptr_base.h:1011:4: note:   mismatched types ‘_Tp1*’ and ‘std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>’
    __shared_ptr(std::move(__r)).swap(*this);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:884:11: note: candidate: template<class _Tp1> std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*)
  explicit __shared_ptr(_Tp1* __p)
           ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:884:11: note:   template argument deduction/substitution failed:
/usr/include/c++/6/bits/shared_ptr_base.h:1011:4: note:   mismatched types ‘_Tp1*’ and ‘std::__shared_ptr<long unsigned int, (__gnu_cxx::_Lock_policy)2u>’
    __shared_ptr(std::move(__r)).swap(*this);
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:879:17: note: candidate: constexpr std::__shared_ptr<_Tp, _Lp>::__shared_ptr() [with _Tp = long int; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]
       constexpr __shared_ptr() noexcept
                 ^~~~~~~~~~~~
/usr/include/c++/6/bits/shared_ptr_base.h:879:17: note:   candidate expects 0 arguments, 1 provided
CMakeFiles/hempeno.dir/build.make:141: recipe for target 'CMakeFiles/hempeno.dir/models/Brands.cc.o' failed
make[2]: *** [CMakeFiles/hempeno.dir/models/Brands.cc.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/hempeno.dir/all' failed
make[1]: *** [CMakeFiles/hempeno.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

implement gzip_static - feature request

There is always a compromise between saving a few cpu cycles (using sendfile, not using zip, etc..) and saving bandwidth (using on the fly gzip compression)

gzip_static is a nice compromise, saving both cpu cycles and bandwidth.

Would love to see this feature in drogon.

Thanks

CORS issue when POST data.

fetch(url, {
    method: 'POST',
    headers: {
     'Content-Type': 'application/json',
     'Access-Control-Allow-Origin': '*',
    },
    body: JSON.stringify(json)
})

My handler method is :
METHOD_ADD(User::newForm,"/accessory?materialId={1}&slug={2}&name={3}",Post,Options);
but the request from browser has been blocked by CORS policy.
Please Help

[Question] Servier-sent events support?

I see that there is some support for websockets in Drogon. Just wonder if Server-sent events are also supported (or planned) as an alternative to websockets, when only server->client comunication is desired.

Aarch64 (Nvidia Xavier) Test Results: All Tests Pass

Not an issue, just reporting test results. Should be closed.

$ ./test.sh
20190610 15:00:45.864121 UTC 26139 DEBUG [TestController] TestController constructor - TestController.h:22
     _
  __| |_ __ ___   __ _  ___  _ __
 / _` | '__/ _ \ / _` |/ _ \| '_ \
| (_| | | | (_) | (_| | (_) | | | |
 \__,_|_|  \___/ \__, |\___/|_| |_|
                 |___/

empty custom config!
20190610 15:00:45.875527 UTC 26139 DEBUG [operator()] Event loop is running! - main.cc:191
/slow (GET) HttpSimpleController: example::TestController
/path/name (GET) HttpSimpleController: controllerClassName
/path/name (POST) HttpSimpleController: controllerClassName
/tpost (POST) HttpSimpleController: example::TestController
/tpost (OPTIONS) HttpSimpleController: example::TestController
/json (GET) HttpSimpleController: JsonTestController
/view (GET) HttpSimpleController: TestViewCtl
/view (POST) HttpSimpleController: TestViewCtl
/view (Head) HttpSimpleController: TestViewCtl
/view (PUT) HttpSimpleController: TestViewCtl
/view (DELETE) HttpSimpleController: TestViewCtl
/view (OPTIONS) HttpSimpleController: TestViewCtl
/forward (GET) HttpSimpleController: ForwardCtrl
/listpara (GET) HttpSimpleController: ListParaCtl
/test (GET) HttpSimpleController: example::TestController
/test (POST) HttpSimpleController: example::TestController
/test (Head) HttpSimpleController: example::TestController
/test (PUT) HttpSimpleController: example::TestController
/test (DELETE) HttpSimpleController: example::TestController
/test (OPTIONS) HttpSimpleController: example::TestController
/pipe (GET) HttpSimpleController: PipeliningTest
/ (GET) HttpSimpleController: example::TestController
/ (POST) HttpSimpleController: TestViewCtl
/api/Attachment (GET) HttpController: Attachment::get
/api/Attachment/upload (POST) HttpController: Attachment::upload
/api/Attachment/download (GET) HttpController: Attachment::download
/api/v1/ApiTest (GET) HttpController: ApiTest::rootGet
/api/v1/ApiTest (POST) HttpController: ApiTest::rootPost
/api/v1/ApiTest (OPTIONS) HttpController: ApiTest::rootPost
/api/v1/ApiTest/get/{2}/{1} (GET) HttpController: ApiTest::get
/api/v1/ApiTest/{1}/List?P2={2} (GET) HttpController: ApiTest::your_method_name
/api/v1/ApiTest/static (GET) HttpController: ApiTest::staticApi
/api/v1/ApiTest/static (POST) HttpController: ApiTest::staticApi
/api/v1/ApiTest/static (PUT) HttpController: ApiTest::staticApi
/api/v1/ApiTest/static (DELETE) HttpController: ApiTest::staticApi
/api/v1/ApiTest/static (OPTIONS) HttpController: ApiTest::staticApi
/api/v1/ApiTest/get/{1} (GET) HttpController: ApiTest::get2
/absolute/{1} (GET) HttpController: ApiTest::get2
/api/v1/ApiTest/json (POST) HttpController: ApiTest::jsonTest
/api/v1/ApiTest/form (POST) HttpController: ApiTest::formTest
/api/v1/Test/get/{2}/{1} (GET) HttpController: Test::get
/api/v1/Test/{2}/info (GET) HttpController: Test::list
/api/v1/handle1/{1}/{2}/?p3={3}&p4={4} (GET) Handler: void (A::*)(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int) const
/api/v1/handle1/{1}/{2}/?p3={3}&p4={4} (POST) Handler: void (A::*)(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int) const
/api/v1/handle1/{1}/{2}/?p3={3}&p4={4} (Head) Handler: void (A::*)(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int) const
/api/v1/handle1/{1}/{2}/?p3={3}&p4={4} (PUT) Handler: void (A::*)(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int) const
/api/v1/handle1/{1}/{2}/?p3={3}&p4={4} (DELETE) Handler: void (A::*)(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int) const
/api/v1/handle1/{1}/{2}/?p3={3}&p4={4} (OPTIONS) Handler: void (A::*)(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int) const
/api/v1/handle11/{1}/{2}/?p3={3}&p4={4} (GET) Handler: void (*)(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)
/api/v1/handle11/{1}/{2}/?p3={3}&p4={4} (POST) Handler: void (*)(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)
/api/v1/handle11/{1}/{2}/?p3={3}&p4={4} (Head) Handler: void (*)(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)
/api/v1/handle11/{1}/{2}/?p3={3}&p4={4} (PUT) Handler: void (*)(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)
/api/v1/handle11/{1}/{2}/?p3={3}&p4={4} (DELETE) Handler: void (*)(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)
/api/v1/handle11/{1}/{2}/?p3={3}&p4={4} (OPTIONS) Handler: void (*)(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)
/api/v1/handle2/{1}/{2} (GET) Handler: main::{lambda(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, float)#1}
/api/v1/handle2/{1}/{2} (POST) Handler: main::{lambda(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, float)#1}
/api/v1/handle2/{1}/{2} (Head) Handler: main::{lambda(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, float)#1}
/api/v1/handle2/{1}/{2} (PUT) Handler: main::{lambda(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, float)#1}
/api/v1/handle2/{1}/{2} (DELETE) Handler: main::{lambda(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, float)#1}
/api/v1/handle2/{1}/{2} (OPTIONS) Handler: main::{lambda(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, float)#1}
/api/v1/handle3/{1}/{2} (GET) Handler: B
/api/v1/handle3/{1}/{2} (POST) Handler: B
/api/v1/handle3/{1}/{2} (Head) Handler: B
/api/v1/handle3/{1}/{2} (PUT) Handler: B
/api/v1/handle3/{1}/{2} (DELETE) Handler: B
/api/v1/handle3/{1}/{2} (OPTIONS) Handler: B
/api/v1/handle4/{4}/{3}/{1} (GET) Handler: std::function<void (std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)>
/api/v1/handle4/{4}/{3}/{1} (POST) Handler: std::function<void (std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)>
/api/v1/handle4/{4}/{3}/{1} (Head) Handler: std::function<void (std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)>
/api/v1/handle4/{4}/{3}/{1} (PUT) Handler: std::function<void (std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)>
/api/v1/handle4/{4}/{3}/{1} (DELETE) Handler: std::function<void (std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)>
/api/v1/handle4/{4}/{3}/{1} (OPTIONS) Handler: std::function<void (std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)>
/CustomCtrl/{1} (GET) HttpController: CustomCtrl::hello
/chat (GET) WebsocketController: example::WebSocketTest
20190610 15:00:45.877341 UTC 26139 INFO  Start to run... - HttpAppFrameworkImpl.cc:242
Initializing daemon mode
Test http requests and responses.
1	Good	GET /slow
2	Good	GET /api/v1/apitest/get/111
3	Good	POST /api/v1/apitest/json
4	Good	GET /
5	Good	GET /tpost
6	Good	POST /tpost
7	Good	OPTIONS /tpost
8	Good	OPTIONS /api/v1/apitest
9	Good	OPTIONS /slow
10	Good	OPTIONS /*
11	Good	OPTIONS /api/v1/apitest/static
12	Good	POST /api/v1/apitest
13	Good	GET /api/v1/apitest
14	Good	GET /api/v1/apitest/get/abc/123
15	Good	GET /api/v1/apitest/3.14/List
16	Good	GET /api/v1/apitest/static
17	Good	POST /api/v1/apitest/static
18	Good	GET /api/v1/apitest/get/111
19	Good	GET /api/v1/handle11/11/2 2/?p3=3 x
20	Good	GET /api/v1/handle2/111/222
21	Good	GET /api/v1/handle4/444/333/111
22	Good	GET /index.html
23	Good	GET /index.html
24	Good	GET /drogon.jpg
25	Good	GET /../../drogon.jpg
26	Good	GET /customctrl/antao
27	Good	GET /absolute/123
28	Good	POST /api/v1/apitest/form
29	Good	GET /api/attachment/download
30	Good	POST /api/attachment/upload
31	Good	GET /slow
32	Good	GET /drogon.jpg
33	Good	GET /slow	(https)
34	Good	GET /api/v1/apitest/get/111	(https)
35	Good	POST /api/v1/apitest/json	(https)
36	Good	GET /	(https)
37	Good	GET /tpost	(https)
38	Good	POST /tpost	(https)
39	Good	OPTIONS /tpost	(https)
40	Good	OPTIONS /api/v1/apitest	(https)
41	Good	OPTIONS /slow	(https)
42	Good	OPTIONS /*	(https)
43	Good	OPTIONS /api/v1/apitest/static	(https)
44	Good	POST /api/v1/apitest	(https)
45	Good	GET /api/v1/apitest	(https)
46	Good	GET /api/v1/apitest/get/abc/123	(https)
47	Good	GET /api/v1/apitest/3.14/List	(https)
48	Good	GET /api/v1/apitest/static	(https)
49	Good	POST /api/v1/apitest/static	(https)
50	Good	GET /api/v1/apitest/get/111	(https)
51	Good	GET /api/v1/handle11/11/2 2/?p3=3 x	(https)
52	Good	GET /api/v1/handle2/111/222	(https)
53	Good	GET /api/v1/handle4/444/333/111	(https)
54	Good	GET /index.html	(https)
55	Good	GET /index.html	(https)
56	Good	GET /drogon.jpg	(https)
57	Good	GET /../../drogon.jpg	(https)
58	Good	GET /customctrl/antao	(https)
59	Good	GET /absolute/123	(https)
60	Good	POST /api/v1/apitest/form	(https)
61	Good	GET /api/attachment/download	(https)
62	Good	POST /api/attachment/upload	(https)
63	Good	GET /slow	(https)
64	Good	GET /drogon.jpg	(https)
Test the WebSocket
20190610 15:00:50.168176 UTC 26149 INFO  Start to run... - HttpAppFrameworkImpl.cc:242
ws connected!
new message:haha!!!
new message:
recv a pong
Test the pipelining
20190610 15:00:52.195653 UTC 26151 INFO  Start to run... - HttpAppFrameworkImpl.cc:242
20190610 15:00:53.205546 UTC 26151 DEBUG [operator()] Good! - HttpPipeliningTest.cc:36
Test the drogon_ctl
create a project named drogon_test
create a http simple controller:Test::SimpleCtrl
create a http controller:Test::HttpCtrl
create a websocket controller:Test::WebsockCtrl
create a http filter:Test::TestFilter
create a plugin:Test::TestPlugin
-- The C compiler identification is GNU 7.3.0
-- The CXX compiler identification is GNU 7.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- This is gcc version:: 7.3.0
-- c++17
-- Found jsoncpp: /usr/local/include
-- Found UUID: /usr/lib/aarch64-linux-gnu/libuuid.so
-- Found OpenSSL: /home/linuxbrew/.linuxbrew/Cellar/openssl/1.0.2r/lib/libcrypto.so (found version "1.0.2r")
-- Found ZLIB: /usr/lib/aarch64-linux-gnu/libz.so (found version "1.2.11")
-- Could NOT find PostgreSQL (missing: PostgreSQL_LIBRARY PostgreSQL_INCLUDE_DIR PostgreSQL_TYPE_INCLUDE_DIR)
-- Could NOT find SQLITE3 (missing: SQLITE3_LIBRARY SQLITE3_INCLUDE_DIR)
-- Configuring done
-- Generating done
-- Build files have been written to: /home/vinay/dev/drogon/build/examples/drogon_test/build
Scanning dependencies of target drogon_test
[ 14%] Building CXX object CMakeFiles/drogon_test.dir/main.cc.o
[ 28%] Building CXX object CMakeFiles/drogon_test.dir/controllers/Test_HttpCtrl.cc.o
[ 42%] Building CXX object CMakeFiles/drogon_test.dir/controllers/Test_SimpleCtrl.cc.o
[ 57%] Building CXX object CMakeFiles/drogon_test.dir/controllers/Test_WebsockCtrl.cc.o
[ 71%] Building CXX object CMakeFiles/drogon_test.dir/filters/Test_TestFilter.cc.o
[ 85%] Building CXX object CMakeFiles/drogon_test.dir/plugins/Test_TestPlugin.cc.o
[100%] Linking CXX executable drogon_test
[100%] Built target drogon_test
Everything is ok!

新需求: 能否同时使用 DbClient 和 FastDbClient

现在的情况:

  1. 我这边的基本架构已经写成全异步的了
  2. 我需要dbclient 的execSqlSync来同步(递归)获取数据,同时对比另外一个数据库的籹据,加载到内存当中
  3. 已经写成的全异步框架,又想利用 fastdbclient 的便利性。。。

虽然web是数据库不敏感的, 但,我想能有多快就提多快。

so, 有没有办法,让我同时可以使用 dbclient 和 fastdbclient ?

sqlite3 connection leak if query contains error

Describe the bug
sqlite3 connection is not excuting any query if previous contains error.

To Reproduce
Steps to reproduce the behavior:

  1. execSqlAsync an incorrect query
  2. then execSqlAsync any query, no result callback or error callback called. http request is blocked.

Expected behavior
when error, reset the connection or create a new one. the next query should not be blocked forever.

Versions:

  • OS: OSX 10.14.6
  • Drogon: 543d1a8@master

How to specify custom paths in HttpController?

Thanks for helping with previous enquiry. But now I have new problem.

I have just super basic class for testing:

class TestCtrl: public HttpController<TestCtrl, false>
{
    std::string text;
public:

   static void
   initPathRouting()
   {
       registerMethod(&TestCtrl::main, "/", {Get});
   }
   
   TestCtrl(std::string const& a) : text {a} 
   {} 

   virtual void
   main(HttpRequestPtr const& req,
        std::function<void (const HttpResponsePtr &)> const& callback);
     
};

The problem is that I expected that going to 127.0.0.1:8848/ would call main method. But instead I have to go to 127.0.0.1:8848/testctrl/ to do this?

I see that this is hardcoded in https://github.com/an-tao/drogon/blob/master/lib/inc/drogon/HttpController.h#L58

But is there other way than using registerMethod of specifying absolute paths in HttpController?

Error while building: undefined reference to symbol 'inflateEnd'

Describe the bug
I'm trying to build a release version of drogon but I keep getting this:

[ 51%] Linking CXX executable multiple_ws_test
/usr/bin/ld: ../libdrogon.a(Utilities.cc.o): undefined reference to symbol 'inflateEnd'
//lib/x86_64-linux-gnu/libz.so.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
examples/CMakeFiles/multiple_ws_test.dir/build.make:104: recipe for target 'examples/multiple_ws_test' failed
make[2]: *** [examples/multiple_ws_test] Error 1
CMakeFiles/Makefile2:223: recipe for target 'examples/CMakeFiles/multiple_ws_test.dir/all' failed
make[1]: *** [examples/CMakeFiles/multiple_ws_test.dir/all] Error 2
Makefile:129: recipe for target 'all' failed
make: *** [all] Error 2

Steps to reproduce

cd $WORK_PATH
git clone https://github.com/an-tao/drogon
cd drogon
git submodule update --init
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release .. 
make
OS (WSL) Ubuntu 18.04.3 LTS
Kernel 4.4.0-18362-Microsoft
Processor 64-bit
Lib Version
cmake 3.10.2
gcc 7.4.0
libjsoncpp-dev 1.7.4-3
openssl 1.1.1
libssl-dev 1.1.1
zlib1g-dev 1.2.11
libboost-all-dev 1.65.1
Lib Version
postgresql-all 10+190
postgresql-server-dev-all 190
libmariadbclient-dev 10.1.41
libsqlite3-dev 3.22.0

Please create tagged versions and changelog

Thanks for creating this wonderful project. I am now integrating it with my own project.

Please create tagged version, e.g. 0.1.0, and changelog so that dependent projects (e.g. mine) can choose which tagged version they prefer to use. The dependencies, e.g. Trantor, should also be tagged similarly.

Websocket connection closes with code 1006

I started getting this issue just in last few days. I just tested your example ws_test.html and it has same issue: it errors out in about 1 minute after establishing connection. I tested in both Chrome and Firefox and both browsers exhibit same behavior.

I slightly modified onclose in ws_test.html to show the code and evt object.

ws.onclose = function(evt) {
    log('DISCONNECT with code: ' + evt.code);
    console.log(evt)
  };

I'm pretty sure I did not have this problem right after websocket controller was fixed. At the time I could have websocket connection open for long. So I think maybe there have been some new changes made in the last week that broke something?

p.s.
The issue can be circumvent using PING messages (as tested using websocat). But from what I read browsers dont have API to send PING nor PONG messages.

There is no usage example for the websockets

Hi

Trying to test the websockets as shown in the example https://github.com/an-tao/drogon/blob/master/examples/simple_example/WebSocketTest.cc

But I dont now know to call it? Your example test dont cover the ws controller: https://github.com/an-tao/drogon/tree/master/examples/simple_example_test

I tried using https://github.com/vi/websocat but still nothing. Is there some example how to use the ws controller? maybe something similar to this (https://github.com/Corvusoft/restbed/blob/master/documentation/example/WEB_SOCKET.md#client) would be valuable.

Segmentation Fault testing views with csp file

Describe the bug
I was following the wiki to create a csp file. Although I am getting a segmentation fault when I make a request to the endpoint.

To Reproduce
Steps to reproduce the behavior:

  1. Create a Controller, register path
  2. Create csp file and its respective source files
  3. Build
  4. go to localhost/my_path/p1=a&p2=b&p3=c

Expected behavior
Expected html as seen in wiki with a table of parameters

Screenshots
image

Segmentation Fault when request happens:
image

Desktop (please complete the following information):

  • OS: Ubuntu 18 Docker image

Controller Source files:

demo_v1_user.h:

#pragma once
#include <drogon/HttpController.h>
using namespace drogon;
namespace demo
{
    namespace v1
    {
        class User:public drogon::HttpController<User>
        {
        public:
            METHOD_LIST_BEGIN
            //use METHOD_ADD to add your custom processing function here;
            //METHOD_ADD(User::get,"/get/{2}/{1}",Get);//path is /demo/v1/User/get/{arg2}/{arg1}
            //METHOD_ADD(User::your_method_name,"/{1}/{2}/list",Get);//path is /demo/v1/User/{arg1}/{arg2}/list
            //ADD_METHOD_TO(User::your_method_name,"/absolute/path/{1}/{2}/list",Get);//path is /demo/v1//absolute/path/{arg1}/{arg2}/list
            METHOD_ADD(User::getParameters,"list_para",Get);
            METHOD_LIST_END
            //your declaration of processing function maybe like this:
            //void get(const HttpRequestPtr& req,std::function<void (const HttpResponsePtr &)> &&callback,int p1,std::string p2);
            //void your_method_name(const HttpRequestPtr& req,std::function<void (const HttpResponsePtr &)> &&callback,double p1,int p2) const;
            void getParameters(const HttpRequestPtr &req,
                                   std::function<void (const HttpResponsePtr &)> &&callback);
                               
        };
    }
}

demo_v1_user.cc:

#include "demo_v1_User.h"
using namespace demo::v1;
//add definition of your processing function here
void User::getParameters(const HttpRequestPtr &req,
                                   std::function<void (const HttpResponsePtr &)> &&callback)
{
    auto para = req->getParameters();
    HttpViewData data;
    data.insert("title","ListParameters");
    data.insert("parameters",para);
    auto resp=HttpResponse::newHttpViewResponse("ListParameters.csp",data);
    callback(resp);
};

Csp file:

<!DOCTYPE html>
<html>
<%c++
    auto para=@@.get<std::map<std::string,std::string>>("parameters");
%>
<head>
    <meta charset="UTF-8">
    <title>[[ title ]]</title>
</head>
<body>
    <%c++ if(para.size()>0){%>
    <H1>Parameters</H1>
    <table border="1">
      <tr>
        <th>name</th>
        <th>value</th>
      </tr>
      <%c++ for(auto iter:para){%>
      <tr>
        <td>{%iter.first%}</td>
        <td><%c++ $$<<iter.second;%></td>
      </tr>
      <%c++}%>
    </table>
    <%c++ }else{%>
    <H1>no parameter</H1>
    <%c++}%>
</body>
</html>

小建议 drogon/lib/src/Utilities.cc

drogon/lib/src/Utilities.cc

is_base64 这个方法,也其他的不对照出啊, 这个是 小写_小写, 这样样式的,其他的都是 小写大写 样式的.

另外,是否考虑,工具类,这一块,分为几个文件,几个类,每个类有各自的类型的工作处理函数

How do you provide custom constructors (or initialize) controllers?

Hi

I'm looking at the examples code and your recommendations of using controllers by inheriting from HttpSimpleController<> or HttpController<>. This is nice, but how do you initialize them? How do I provide custom constructor to inject other objects or set up some initial values in such controllers?

For instance, in this example: https://github.com/an-tao/drogon/blob/master/examples/simple_example/main.cc#L62

How would I provide non-default constructor and how should I call it?

From the code it seems to me that only default contractors are called: https://github.com/an-tao/drogon/blob/master/lib/inc/drogon/DrObject.h#L79

For now I can only see that one would have to use static global objects and variables to customize the controllers?

最新版本无法编译

由于没有了config.h,导致lib/src/SharedLibManager.cc出现编译错误。COMPILER_COMMAND等宏都没有定义。

CMakeLists.txt 关于jsoncpp定位的问题

Describe the bug
CMakeLists.txt 关于jsoncpp定位的问题

To Reproduce
Steps to reproduce the behavior:

  1. 执行 build.sh
  2. 提示json版本太老, 而无法执行
  3. 实际上, /usr/include/jsoncpp 是存在的, 脚本里判断的是 /usr/include/json/version.h

Expected behavior
判断位置: /usr/include/json/version.h
实际位置: /usr/include/jsoncpp/json/version

Desktop (please complete the following information):

  • OS: Ubuntu 18.04

Additional context
不知道别的系统是不是这个问题,

目前的解决办法:
安装之前:
如果提示json太老,

  1. 将 /usr/include/jsoncpp/json 做个链接到 /usr/include/json
  2. 删除 /usr/local/include/json
    安装之后,如果编辑器提示, 找找不到 json头文件
  3. 将 /usr/include/jsoncpp/json 做个链接到 /usr/local/include

莫非是我的系统的问题? 不知道 linuxmit 是不是都是这个样子

Debian 10 drogon::DrClassMap::demangle[abi:cxx11](char const*) issue

Hello, I'm using Debian 10 and g++ with std17 and can't compile very first example.

I've installed every library in installation tutorial.
Here is the compiler output.

sudo g++ -std=c++17 /home/us3r/Documents/wrk/Untitled-1.cpp
/usr/bin/ld: /tmp/ccMLPNve.o: in function `drogon::DrClassMap::demangle[abi:cxx11](char const*)':
Untitled-1.cpp:(.text._ZN6drogon10DrClassMap8demangleB5cxx11EPKc[_ZN6drogon10DrClassMap8demangleB5cxx11EPKc]+0x104): undefined reference to `trantor::Logger::Logger(trantor::Logger::SourceFile, int, trantor::Logger::LogLevel)'
/usr/bin/ld: Untitled-1.cpp:(.text._ZN6drogon10DrClassMap8demangleB5cxx11EPKc[_ZN6drogon10DrClassMap8demangleB5cxx11EPKc]+0x113): undefined reference to `trantor::Logger::stream()'
/usr/bin/ld: Untitled-1.cpp:(.text._ZN6drogon10DrClassMap8demangleB5cxx11EPKc[_ZN6drogon10DrClassMap8demangleB5cxx11EPKc]+0x131): undefined reference to `trantor::Logger::~Logger()'
/usr/bin/ld: Untitled-1.cpp:(.text._ZN6drogon10DrClassMap8demangleB5cxx11EPKc[_ZN6drogon10DrClassMap8demangleB5cxx11EPKc]+0x19a): undefined reference to `trantor::Logger::~Logger()'
/usr/bin/ld: /tmp/ccMLPNve.o: in function `drogon::IntranetIpFilter::IntranetIpFilter()':
Untitled-1.cpp:(.text._ZN6drogon16IntranetIpFilterC1Ev[_ZN6drogon16IntranetIpFilterC1Ev]+0x1f): undefined reference to `VTT for drogon::IntranetIpFilter'
/usr/bin/ld: Untitled-1.cpp:(.text._ZN6drogon16IntranetIpFilterC1Ev[_ZN6drogon16IntranetIpFilterC1Ev]+0x31): undefined reference to `vtable for drogon::IntranetIpFilter'
/usr/bin/ld: Untitled-1.cpp:(.text._ZN6drogon16IntranetIpFilterC1Ev[_ZN6drogon16IntranetIpFilterC1Ev]+0x3f): undefined reference to `vtable for drogon::IntranetIpFilter'
/usr/bin/ld: Untitled-1.cpp:(.text._ZN6drogon16IntranetIpFilterC1Ev[_ZN6drogon16IntranetIpFilterC1Ev]+0x4d): undefined reference to `vtable for drogon::IntranetIpFilter'
/usr/bin/ld: /tmp/ccMLPNve.o: in function `drogon::LocalHostFilter::LocalHostFilter()':
Untitled-1.cpp:(.text._ZN6drogon15LocalHostFilterC1Ev[_ZN6drogon15LocalHostFilterC1Ev]+0x1f): undefined reference to `VTT for drogon::LocalHostFilter'
/usr/bin/ld: Untitled-1.cpp:(.text._ZN6drogon15LocalHostFilterC1Ev[_ZN6drogon15LocalHostFilterC1Ev]+0x31): undefined reference to `vtable for drogon::LocalHostFilter'
/usr/bin/ld: Untitled-1.cpp:(.text._ZN6drogon15LocalHostFilterC1Ev[_ZN6drogon15LocalHostFilterC1Ev]+0x3f): undefined reference to `vtable for drogon::LocalHostFilter'
/usr/bin/ld: Untitled-1.cpp:(.text._ZN6drogon15LocalHostFilterC1Ev[_ZN6drogon15LocalHostFilterC1Ev]+0x4d): undefined reference to `vtable for drogon::LocalHostFilter'
/usr/bin/ld: /tmp/ccMLPNve.o: in function `drogon::NotFound::NotFound()':
Untitled-1.cpp:(.text._ZN6drogon8NotFoundC1Ev[_ZN6drogon8NotFoundC1Ev]+0x20): undefined reference to `VTT for drogon::NotFound'
/usr/bin/ld: Untitled-1.cpp:(.text._ZN6drogon8NotFoundC1Ev[_ZN6drogon8NotFoundC1Ev]+0x32): undefined reference to `vtable for drogon::NotFound'
/usr/bin/ld: Untitled-1.cpp:(.text._ZN6drogon8NotFoundC1Ev[_ZN6drogon8NotFoundC1Ev]+0x40): undefined reference to `vtable for drogon::NotFound'
/usr/bin/ld: Untitled-1.cpp:(.text._ZN6drogon8NotFoundC1Ev[_ZN6drogon8NotFoundC1Ev]+0x4e): undefined reference to `vtable for drogon::NotFound'
/usr/bin/ld: /tmp/ccMLPNve.o: in function `drogon::app()':
Untitled-1.cpp:(.text._ZN6drogon3appEv[_ZN6drogon3appEv]+0x5): undefined reference to `drogon::HttpAppFramework::instance()'
/usr/bin/ld: /tmp/ccMLPNve.o: in function `drogon::DrObject<drogon::NotFound>::DrAllocator::className[abi:cxx11]() const':
Untitled-1.cpp:(.text._ZNK6drogon8DrObjectINS_8NotFoundEE11DrAllocator9classNameB5cxx11Ev[_ZNK6drogon8DrObjectINS_8NotFoundEE11DrAllocator9classNameB5cxx11Ev]+0x3d): undefined reference to `typeinfo for drogon::NotFound'
/usr/bin/ld: /tmp/ccMLPNve.o: in function `drogon::DrObject<drogon::LocalHostFilter>::DrAllocator::className[abi:cxx11]() const':
Untitled-1.cpp:(.text._ZNK6drogon8DrObjectINS_15LocalHostFilterEE11DrAllocator9classNameB5cxx11Ev[_ZNK6drogon8DrObjectINS_15LocalHostFilterEE11DrAllocator9classNameB5cxx11Ev]+0x3d): undefined reference to `typeinfo for drogon::LocalHostFilter'
/usr/bin/ld: /tmp/ccMLPNve.o: in function `drogon::DrObject<drogon::IntranetIpFilter>::DrAllocator::className[abi:cxx11]() const':
Untitled-1.cpp:(.text._ZNK6drogon8DrObjectINS_16IntranetIpFilterEE11DrAllocator9classNameB5cxx11Ev[_ZNK6drogon8DrObjectINS_16IntranetIpFilterEE11DrAllocator9classNameB5cxx11Ev]+0x3d): undefined reference to `typeinfo for drogon::IntranetIpFilter'
/usr/bin/ld: /tmp/ccMLPNve.o: in function `std::enable_if<std::is_default_constructible<drogon::NotFound>::value, void>::type drogon::DrObject<drogon::NotFound>::DrAllocator::registerClass<drogon::NotFound>()':
Untitled-1.cpp:(.text._ZN6drogon8DrObjectINS_8NotFoundEE11DrAllocator13registerClassIS1_EENSt9enable_ifIXsrSt24is_default_constructibleIT_E5valueEvE4typeEv[_ZN6drogon8DrObjectINS_8NotFoundEE11DrAllocator13registerClassIS1_EENSt9enable_ifIXsrSt24is_default_constructibleIT_E5valueEvE4typeEv]+0x33): undefined reference to `drogon::DrClassMap::registerClass(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<drogon::DrObjectBase* ()> const&)'
/usr/bin/ld: /tmp/ccMLPNve.o: in function `std::enable_if<std::is_default_constructible<drogon::LocalHostFilter>::value, void>::type drogon::DrObject<drogon::LocalHostFilter>::DrAllocator::registerClass<drogon::LocalHostFilter>()':
Untitled-1.cpp:(.text._ZN6drogon8DrObjectINS_15LocalHostFilterEE11DrAllocator13registerClassIS1_EENSt9enable_ifIXsrSt24is_default_constructibleIT_E5valueEvE4typeEv[_ZN6drogon8DrObjectINS_15LocalHostFilterEE11DrAllocator13registerClassIS1_EENSt9enable_ifIXsrSt24is_default_constructibleIT_E5valueEvE4typeEv]+0x33): undefined reference to `drogon::DrClassMap::registerClass(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<drogon::DrObjectBase* ()> const&)'
/usr/bin/ld: /tmp/ccMLPNve.o: in function `std::enable_if<std::is_default_constructible<drogon::IntranetIpFilter>::value, void>::type drogon::DrObject<drogon::IntranetIpFilter>::DrAllocator::registerClass<drogon::IntranetIpFilter>()':
Untitled-1.cpp:(.text._ZN6drogon8DrObjectINS_16IntranetIpFilterEE11DrAllocator13registerClassIS1_EENSt9enable_ifIXsrSt24is_default_constructibleIT_E5valueEvE4typeEv[_ZN6drogon8DrObjectINS_16IntranetIpFilterEE11DrAllocator13registerClassIS1_EENSt9enable_ifIXsrSt24is_default_constructibleIT_E5valueEvE4typeEv]+0x33): undefined reference to `drogon::DrClassMap::registerClass(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<drogon::DrObjectBase* ()> const&)'
collect2: error: ld returned 1 exit status
```

Fresh install inside Docker container compilation errors

Describe the bug
Created a container and shared a volume to be able to develop locally since I am on Windows. Encountered compilation errors on a fresh install.

To Reproduce
Steps to reproduce the behavior:

cd $WORK_PATH
git clone https://github.com/an-tao/drogon
cd drogon
git submodule update --init
mkdir build
cd build
cmake ..

Expected behavior
Successful Compilation

Screenshots
If applicable, add screenshots to help explain your problem.
image

Desktop (please complete the following information):

  • OS: Docker Container (from Ubuntu 18.04) Engine 19.03.2

Additional context
Dockerfile

FROM ubuntu:18.04

RUN apt-get update -yqq \
    && apt-get install -yqq --no-install-recommends software-properties-common \
    sudo curl wget cmake locales git gcc-8 g++-8 \
    openssl libssl-dev libjsoncpp-dev uuid-dev zlib1g-dev \
    postgresql-server-dev-all libmariadbclient-dev libsqlite3-dev \
    && rm -rf /var/lib/apt/lists/* \
    && locale-gen en_US.UTF-8

ENV LANG=en_US.UTF-8 \
    LANGUAGE=en_US:en \
    LC_ALL=en_US.UTF-8 \
    CC=gcc-8 \
    CXX=g++-8 \
    AR=gcc-ar-8 \
    RANLIB=gcc-ranlib-8 \
    IROOT=/install

Also tried to run ./build.sh to the same following error:
image

CMakeOutput.log
https://pastebin.com/EntKKUsZ

[question] Getting websocket connection request headers.

I cant find a way to get websocket connection headers. For example whey I connect using browser, the following request headers are sent to drogon.

Host: 127.0.0.1:8848
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: http://127.0.0.1:9100
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Key: wXg3wPvLUZNJklC5+uuMrQ==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

How do I access them? For example how to get value of Sec-WebSocket-Key? I found that ppl use Sec-WebSocket-Key as a way to identify and compare web-socket connection.

Recommended Orm Relational Access

I'd like to know what's the recommended way to access pivot tables and related records with the ORM, if there is one and if not the recommended way of doing so in the most performant way as intended by drogon.

要求可以自定义Header信息中的Server字段!

主要是为了对web服务器进行保密,或者对外部攻击者进行误导。

比如现在的头信息中,Server 是 drogon ,我想改成 IIS/6.5 - Powered-By: Asp/Vbscript,让人以为这个是是asp代码写的网站。

现在的情况下,如果使用 addHeader方法添加头信息,会生成2个头信息
Server: xxx
server: xxx
就是后来添加的,变成了小写

希望能,自定义一些头信息,如果addHeader 之后,覆盖原有的键,而不是新增键

Change JsonCpp to nlohmann/json

Is your feature request related to a problem? Please describe.
JsonCpp has some loose typing
example If we try to get int from a value and its not present it return 0.

Describe the solution you'd like
change to nlohmann/json, its strict typing. dont allow unproper things. well designed library. its api is almost same as jsoncpp. its also fast then jsoncpp and we need some less code to type and its very well documented and more features.

i think existing users can change to nlohmann/json very easily.its header only library. json.hpp is the single required file.

Compiling with c++ 14

Hi

We are not able to compile our project with c++17 because of some other library dependencies, (c++17 and related gcc is installed on the machine but in our cmake file we define our compiler as c++14)
However I install the drogon with following the installation wiki and add it to our project
But when I try to compile our application it gives the following error. Which seems to be related with c++17, how can we solve this problem, how can we build drogon with c++14

In file included from /usr/local/include/drogon/config.h:2:0,
                 from /usr/local/include/drogon/drogon.h:17,
                 from /tmp/tmp.KuZgKPJZbr/WebService/WSManager.cpp:7:
/usr/local/include/trantor/utils/config.h:6:12: error: ‘std::any’ has not been declared
 using std::any;
            ^~~
/usr/local/include/trantor/utils/config.h:7:12: error: ‘std::any_cast’ has not been declared
 using std::any_cast;
            ^~~~~~~~
In file included from /usr/local/include/drogon/config.h:2:0,
                 from /usr/local/include/drogon/drogon.h:17,
                 from /tmp/tmp.KuZgKPJZbr/WebService/WSManager.cpp:7:
/usr/local/include/trantor/utils/config.h:10:14: error: ‘string_view’ in namespace ‘std’ does not name a type
 typedef std::string_view string_view;

关于Model的使用问题

目前的 model 是自动生成的, 生成之后,如果有代码变动的情况下

  1. 下一次添加新表,需要新的生成
  2. 某个表加了很多字段,需要重新生成

为了不破坏原有的结构

  1. 生成的model不动, 另写一个类,继承这个model
  2. 另外写一套 数据操作模型, model 仅做为基本操作

目前我这边是写的新的一几个东西, 不知道,这些,做者是怎么考量的。

如何在加载配置之后,run()之前,加载一些数据库数据到内存当中

    drogon::app().loadConfigFile("config.json"); //加载配置
    sleep(5); //不起作用

    //加载数据到内存当中
    try { 
        Cache::loadAdminRoles(); //加载一些数据到内存当中
    } catch (std::exception& err) { 
        std::cout << err.what() << std::endl;
        return 1;
    }

    drogon::app().run(); //框架运行

我想在 loadConfigFile() 和 run() 之间,加载一些数据库信息到内存当中, 如何实现

Cmake Build Error: "TMP_INS" "MATCHES" ";../drogon/trantor;"

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behaviour:

  1. Clone repo
  2. Generate build files with cmake ..
  3. Error

...
...
File:../drogon/drogon_ctl/templates/plugin_h.csp
-- view classname:plugin_h
RegularExpression::compile(): Nested *?+.
RegularExpression::compile(): Error in compile.
CMake Error at CMakeLists.txt:179 (if):
if given arguments:

"TMP_INS" "MATCHES" ";../drogon/trantor;"

Regular expression
";..//drogon/trantor;"
cannot compile

-- Configuring incomplete, errors occurred!
See also ".../drogon/build/CMakeFiles/CMakeOutput.log".

Expected behavior
Generating done

Desktop (please complete the following information):

  • OS: Ubuntu 19.04
  • CMake 3.13.4

加载配置文件时, 无法过滤为空或无效的参数

Describe the bug
load 配置文件时, 如果我在配置文件当中:

  1. 如果某个项前面加上 /* */ 或 // 注释掉部分内容,会加载错误
  2. 如果某个项 ,比如 filters: [] ,设置成空值, 会加载错误

To Reproduce
Steps to reproduce the behavior:

  1. 将config.json 中的某个项前面或后面,加上注释
  2. 将config.json 中的某个项,设为空值,

Expected behavior
应该是跳过无效的项吧。。。

Desktop (please complete the following information):

  • OS: Linux Ubuntu 18.04

Additional context
建议先过滤掉空的,或无效的json配置,

The project does not seem to be C++14 compatible.

Hi

I tried to compile it using C++14, and there are multiple errors. In your code you use, for instance, std::string_view, std::any which are C++17 features only.

I don't see how one could use drogon in C++14 only project?

If this is the case, they your description C++14/C++17 is confusing and it would be better to change it to C++17.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.