├── _config.yml ├── drogon.jpg ├── .gitmodules ├── examples ├── simple_example │ ├── header.csp │ ├── index.html.gz │ ├── DoNothingPlugin.cc │ ├── TestViewCtl.cc │ ├── TestView.csp │ ├── CustomCtrl.cc │ ├── ForwardCtrl.cc │ ├── ForwardCtrl.h │ ├── PipeliningTest.h │ ├── ListParaCtl.cc │ ├── TimeFilter.h │ ├── ListParaCtl.h │ ├── JsonTestController.h │ ├── TestViewCtl.h │ ├── CustomHeaderFilter.cc │ ├── CustomHeaderFilter.h │ ├── DoNothingPlugin.h │ ├── TestController.cc │ ├── ListParaView.csp │ ├── JsonTestController.cc │ ├── TestPlugin.h │ ├── CustomCtrl.h │ ├── WebSocketTest.h │ ├── TestPlugin.cc │ ├── WebSocketTest.cc │ ├── TestController.h │ ├── api_Attachment.h │ ├── DigestAuthFilter.h │ ├── TimeFilter.cc │ ├── PipeliningTest.cc │ └── api_Attachment.cc ├── simple_reverse_proxy │ ├── README.md │ ├── main.cc │ ├── .gitignore │ ├── plugins │ │ └── SimpleReverseProxy.h │ └── CMakeLists.txt ├── benchmark │ ├── JsonCtrl.cc │ ├── BenchmarkCtrl.cc │ ├── BenchmarkCtrl.h │ ├── JsonCtrl.h │ └── main.cc ├── simple_example_test │ ├── ws_test.html │ ├── MultipleWsTest.cc │ └── WebSocketTest.cc ├── README.md └── client_example │ └── main.cc ├── third_party └── mman-win32 │ ├── UpgradeLog.htm │ ├── README.md │ └── mman.h ├── cmake ├── tests │ ├── normal_uuid_lib_test.cc │ ├── ossp_uuid_lib_test.cc │ └── test_libpq_batch_mode.cc └── templates │ ├── version.h.in │ ├── config.h.in │ └── DrogonConfig.cmake.in ├── orm_lib ├── tests │ ├── mysql │ │ └── model.json │ ├── sqlite3 │ │ └── model.json │ ├── CMakeLists.txt │ └── postgresql │ │ └── model.json ├── src │ ├── mysql_impl │ │ ├── test │ │ │ └── CMakeLists.txt │ │ └── MysqlResultImpl.cc │ ├── sqlite3_impl │ │ ├── test │ │ │ └── CMakeLists.txt │ │ ├── Sqlite3ResultImpl.h │ │ └── Sqlite3ResultImpl.cc │ ├── postgresql_impl │ │ ├── test │ │ │ └── CMakeLists.txt │ │ ├── PostgreSQLResultImpl.h │ │ └── PostgreSQLResultImpl.cc │ ├── ResultImpl.h │ ├── DbClient.cc │ ├── RestfulController.cc │ └── DbClientLockFree.h └── inc │ └── drogon │ └── orm │ └── ArrayParser.h ├── format.sh ├── lib ├── tests │ ├── MainLoopTest.cc │ ├── HttpFullDateTest.cc │ ├── CookiesTest.cc │ ├── MainLoopTest2.cc │ ├── HttpViewDataTest.cc │ ├── ClassNameTest.cc │ ├── UrlCodecTest.cc │ ├── CMakeLists.txt │ └── CacheMapTest2.cc ├── src │ ├── ssl_funcs │ │ ├── Sha1.h │ │ └── Md5.h │ ├── LocalHostFilter.cc │ ├── IntranetIpFilter.cc │ ├── ConfigLoader.h │ ├── HttpFileUploadRequest.cc │ ├── HttpFileUploadRequest.h │ ├── PluginsManager.h │ ├── FiltersFunction.h │ ├── DrTemplateBase.cc │ ├── SessionManager.h │ ├── HttpViewData.cc │ ├── CacheFile.h │ ├── Cookie.cc │ ├── AOPAdvice.h │ ├── SharedLibManager.h │ ├── HttpUtils.h │ ├── DbClientManagerSkipped.cc │ ├── HttpResponseParser.h │ ├── NotFound.cc │ ├── CacheFile.cc │ ├── impl_forwards.h │ ├── SpinLock.h │ ├── DbClientManager.h │ ├── ListenerManager.h │ ├── SessionManager.cc │ ├── FiltersFunction.cc │ └── SecureSSLRedirector.cc └── inc │ └── drogon │ ├── DrTemplate.h │ ├── utils │ ├── any.h │ ├── HttpConstraint.h │ └── string_view.h │ ├── NotFound.h │ ├── LocalHostFilter.h │ ├── IntranetIpFilter.h │ ├── drogon_callbacks.h │ ├── drogon.h │ ├── DrTemplateBase.h │ ├── UploadFile.h │ ├── plugins │ └── SecureSSLRedirector.h │ └── HttpFilter.h ├── drogon_ctl ├── CopyDlls.cmake ├── templates │ ├── demoMain.csp │ ├── gitignore.csp │ ├── plugin_cc.csp │ ├── filter_cc.csp │ ├── filter_h.csp │ ├── plugin_h.csp │ ├── restful_controller_cc.csp │ ├── cmake.csp │ ├── restful_controller_custom_cc.csp │ └── restful_controller_base_h.csp ├── cmd.h ├── help.h ├── create_filter.h ├── create_plugin.h ├── CommandHandler.h ├── create_project.h ├── version.h ├── create.h ├── main.cc ├── create_view.h ├── cmd.cc ├── press.h ├── version.cc ├── create.cc ├── help.cc ├── create_controller.h └── CMakeLists.txt ├── unittest ├── MD5Unittest.cpp ├── SHA1Unittest.cpp ├── PubSubServiceUnittest.cpp ├── GzipUnittest.cpp ├── BrotliUnittest.cpp ├── HttpDateUnittest.cpp ├── DrObjectUnittest.cpp ├── HttpHeaderUnittest.cpp ├── OStringStreamUnitttest.cpp ├── CMakeLists.txt ├── Base64Unittest.cpp └── MsgBufferUnittest.cpp ├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── FUNDING.yml ├── Dockerfile ├── cmake_modules ├── Findcoz-profiler.cmake ├── Findpg.cmake ├── FindSQLite3.cmake └── FindBrotli.cmake ├── LICENSE ├── .appveyor.yml └── .travis.yml /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /drogon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imos/drogon/master/drogon.jpg -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "trantor"] 2 | path = trantor 3 | url = https://github.com/an-tao/trantor.git 4 | 5 | -------------------------------------------------------------------------------- /examples/simple_example/header.csp: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/simple_example/index.html.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imos/drogon/master/examples/simple_example/index.html.gz -------------------------------------------------------------------------------- /third_party/mman-win32/UpgradeLog.htm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imos/drogon/master/third_party/mman-win32/UpgradeLog.htm -------------------------------------------------------------------------------- /cmake/tests/normal_uuid_lib_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | uuid_t uu; 5 | uuid_generate(uu); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /cmake/tests/ossp_uuid_lib_test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | uuid_t *uuid; 5 | uuid_create(&uuid); 6 | uuid_make(uuid, UUID_MAKE_V1); 7 | return 0; 8 | } -------------------------------------------------------------------------------- /orm_lib/tests/mysql/model.json: -------------------------------------------------------------------------------- 1 | { 2 | "rdbms":"mysql", 3 | "host":"localhost", 4 | "port":3306, 5 | "dbname":"drogonTestMysql", 6 | "user":"root", 7 | "tables":["users"] 8 | } 9 | -------------------------------------------------------------------------------- /examples/simple_reverse_proxy/README.md: -------------------------------------------------------------------------------- 1 | ### A Example showing how to use drogon as a http reverse proxy with a simple round robin. 2 | 3 | This project is created by drogon_ctl command, please compile it after installing drogon. -------------------------------------------------------------------------------- /format.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #find lib orm_lib examples drogon_ctl -name *.h -o -name *.cc -exec dos2unix {} \; 4 | find lib orm_lib examples drogon_ctl -name *.h -o -name *.cc|xargs clang-format -i -style=file 5 | -------------------------------------------------------------------------------- /cmake/templates/version.h.in: -------------------------------------------------------------------------------- 1 | #define MAJOR @DROGON_MAJOR_VERSION@ 2 | #define MINOR @DROGON_MINOR_VERSION@ 3 | #define PATCH @DROGON_PATCH_VERSION@ 4 | #define DROGON_VERSION "@DROGON_VERSION_STRING@" 5 | #define DROGON_VERSION_SHA1 "@GIT_SHA1@" -------------------------------------------------------------------------------- /lib/tests/MainLoopTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | std::thread([]() { 7 | drogon::app().getLoop()->runEvery(1, []() { 8 | std::cout << "!" << std::endl; 9 | }); 10 | }).detach(); 11 | drogon::app().run(); 12 | } -------------------------------------------------------------------------------- /cmake/tests/test_libpq_batch_mode.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | PQisInBatchMode(NULL); 6 | PQbatchIsAborted(NULL); 7 | PQqueriesInBatch(NULL); 8 | PQbeginBatchMode(NULL); 9 | PQendBatchMode(NULL); 10 | PQsendEndBatch(NULL); 11 | PQgetNextQuery(NULL); 12 | } 13 | -------------------------------------------------------------------------------- /examples/simple_reverse_proxy/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | // Set HTTP listener address and port 5 | drogon::app().loadConfigFile("../config.json"); 6 | // Run HTTP framework,the method will block in the internal event loop 7 | drogon::app().run(); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /orm_lib/src/mysql_impl/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | link_libraries(${PROJECT_NAME}) 2 | 3 | add_executable(mysql_test1 test1.cc) 4 | 5 | set_property(TARGET mysql_test1 PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD}) 6 | set_property(TARGET mysql_test1 PROPERTY CXX_STANDARD_REQUIRED ON) 7 | set_property(TARGET mysql_test1 PROPERTY CXX_EXTENSIONS OFF) 8 | -------------------------------------------------------------------------------- /orm_lib/tests/sqlite3/model.json: -------------------------------------------------------------------------------- 1 | { 2 | "rdbms":"sqlite3", 3 | "filename":"drogonTestSqlite", 4 | "name": "", 5 | "host": "127.0.0.1", 6 | "port": 5432, 7 | "dbname": "test", 8 | "user": "", 9 | "passwd": "", 10 | "is_fast": false, 11 | "connection_number": 1, 12 | "tables":["users"] 13 | } 14 | -------------------------------------------------------------------------------- /lib/tests/HttpFullDateTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace drogon; 5 | int main() 6 | { 7 | auto str = utils::getHttpFullDate(); 8 | std::cout << str << std::endl; 9 | auto date = utils::getHttpDate(str); 10 | std::cout << utils::getHttpFullDate(date) << std::endl; 11 | } -------------------------------------------------------------------------------- /drogon_ctl/CopyDlls.cmake: -------------------------------------------------------------------------------- 1 | make_directory("${INSTALL_BIN_DIR}") 2 | get_filename_component(CTL_PATH ${CTL_FILE} DIRECTORY) 3 | file(GLOB DLL_FILES ${CTL_PATH}/*.dll) 4 | file(COPY ${DLL_FILES} DESTINATION ${INSTALL_BIN_DIR}) 5 | file(COPY ${CTL_FILE} DESTINATION ${INSTALL_BIN_DIR}) 6 | file(RENAME ${INSTALL_BIN_DIR}/drogon_ctl.exe ${INSTALL_BIN_DIR}/dg_ctl.exe) -------------------------------------------------------------------------------- /third_party/mman-win32/README.md: -------------------------------------------------------------------------------- 1 | mman-win32 2 | ========== 3 | 4 | mman library for Windows. mirror of https://code.google.com/p/mman-win32/ 5 | 6 | A light implementation of the mmap functions for MinGW. 7 | 8 | The mmap-win32 library implements a wrapper for mmap functions around the memory mapping Windows API. 9 | 10 | License: MIT License 11 | -------------------------------------------------------------------------------- /examples/benchmark/JsonCtrl.cc: -------------------------------------------------------------------------------- 1 | #include "JsonCtrl.h" 2 | void JsonCtrl::asyncHandleHttpRequest( 3 | const HttpRequestPtr &req, 4 | std::function &&callback) 5 | { 6 | Json::Value ret; 7 | ret["message"] = "Hello, World!"; 8 | auto resp = HttpResponse::newHttpJsonResponse(ret); 9 | callback(resp); 10 | } -------------------------------------------------------------------------------- /orm_lib/src/sqlite3_impl/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | link_libraries(${PROJECT_NAME}) 2 | 3 | add_executable(sqlite3_test1 test1.cc Groups.cc) 4 | 5 | set_property(TARGET sqlite3_test1 PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD}) 6 | set_property(TARGET sqlite3_test1 PROPERTY CXX_STANDARD_REQUIRED ON) 7 | set_property(TARGET sqlite3_test1 PROPERTY CXX_EXTENSIONS OFF) 8 | -------------------------------------------------------------------------------- /drogon_ctl/templates/demoMain.csp: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | //Set HTTP listener address and port 4 | drogon::app().addListener("0.0.0.0",80); 5 | //Load config file 6 | //drogon::app().loadConfigFile("../config.json"); 7 | //Run HTTP framework,the method will block in the internal event loop 8 | drogon::app().run(); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /examples/simple_example/DoNothingPlugin.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * DoNothingPlugin.cc 4 | * 5 | */ 6 | 7 | #include "DoNothingPlugin.h" 8 | 9 | using namespace drogon; 10 | 11 | void DoNothingPlugin::initAndStart(const Json::Value &config) 12 | { 13 | /// Initialize and start the plugin 14 | } 15 | 16 | void DoNothingPlugin::shutdown() 17 | { 18 | /// Shutdown the plugin 19 | } 20 | -------------------------------------------------------------------------------- /orm_lib/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | link_libraries(${PROJECT_NAME}) 2 | 3 | add_executable(db_test 4 | db_test.cc 5 | postgresql/Users.cc 6 | mysql/Users.cc 7 | sqlite3/Users.cc 8 | ) 9 | 10 | set_property(TARGET db_test PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD}) 11 | set_property(TARGET db_test PROPERTY CXX_STANDARD_REQUIRED ON) 12 | set_property(TARGET db_test PROPERTY CXX_EXTENSIONS OFF) 13 | -------------------------------------------------------------------------------- /orm_lib/src/postgresql_impl/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | link_libraries(${PROJECT_NAME}) 2 | 3 | add_executable(pg_test1 test1.cc) 4 | add_executable(pg_test2 test2.cc) 5 | 6 | set_property(TARGET pg_test1 pg_test2 7 | PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD}) 8 | set_property(TARGET pg_test1 pg_test2 PROPERTY CXX_STANDARD_REQUIRED ON) 9 | set_property(TARGET pg_test1 pg_test2 PROPERTY CXX_EXTENSIONS OFF) 10 | -------------------------------------------------------------------------------- /examples/benchmark/BenchmarkCtrl.cc: -------------------------------------------------------------------------------- 1 | #include "BenchmarkCtrl.h" 2 | void BenchmarkCtrl::asyncHandleHttpRequest( 3 | const HttpRequestPtr &req, 4 | std::function &&callback) 5 | { 6 | // write your application logic here 7 | auto resp = HttpResponse::newHttpResponse(); 8 | resp->setBody("

Hello, world!

"); 9 | resp->setExpiredTime(0); 10 | callback(resp); 11 | } 12 | -------------------------------------------------------------------------------- /orm_lib/tests/postgresql/model.json: -------------------------------------------------------------------------------- 1 | { 2 | //rdbms:server type, postgresql 3 | "rdbms":"postgresql", 4 | //host:server address,localhost by default; 5 | "host":"127.0.0.1", 6 | //port:server port, 5432 by default; 7 | "port":5432, 8 | //dbname:Database name; 9 | "dbname":"postgres", 10 | "user":"postgres", 11 | "passwd":"", 12 | //"tables":["group_users"] 13 | "tables":["users"] 14 | } 15 | -------------------------------------------------------------------------------- /examples/simple_example/TestViewCtl.cc: -------------------------------------------------------------------------------- 1 | #include "TestViewCtl.h" 2 | void TestViewCtl::asyncHandleHttpRequest( 3 | const HttpRequestPtr &req, 4 | std::function &&callback) 5 | { 6 | // write your application logic here 7 | drogon::HttpViewData data; 8 | data.insert("title", std::string("TestView")); 9 | auto res = drogon::HttpResponse::newHttpViewResponse("TestView", data); 10 | callback(res); 11 | } 12 | -------------------------------------------------------------------------------- /examples/benchmark/BenchmarkCtrl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace drogon; 4 | class BenchmarkCtrl : public drogon::HttpSimpleController 5 | { 6 | public: 7 | virtual void asyncHandleHttpRequest( 8 | const HttpRequestPtr &req, 9 | std::function &&callback) override; 10 | PATH_LIST_BEGIN 11 | PATH_ADD("/benchmark", Get); 12 | PATH_LIST_END 13 | }; 14 | -------------------------------------------------------------------------------- /examples/simple_example/TestView.csp: -------------------------------------------------------------------------------- 1 | <%inc 2 | #include 3 | %> 4 | <%c++ 5 | std::cout<<"this is a Http backend rendering Test"< 7 | 8 | 9 | <%c++ std::string title=@@.get("title");%> 10 | 11 | 12 | <%c++ $$<<title;%> 13 | 14 | 15 |
16 | CopyRight@2017 All Rights Reserved 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/simple_example/CustomCtrl.cc: -------------------------------------------------------------------------------- 1 | #include "CustomCtrl.h" 2 | // add definition of your processing function here 3 | 4 | void CustomCtrl::hello(const HttpRequestPtr &req, 5 | std::function &&callback, 6 | const std::string &userName) const 7 | { 8 | auto resp = HttpResponse::newHttpResponse(); 9 | resp->setBody("

" + greetings_ + ", " + userName + "

"); 10 | callback(resp); 11 | } 12 | -------------------------------------------------------------------------------- /cmake/templates/config.h.in: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #cmakedefine01 USE_POSTGRESQL 4 | #cmakedefine01 LIBPQ_SUPPORTS_BATCH_MODE 5 | #cmakedefine01 USE_MYSQL 6 | #cmakedefine01 USE_SQLITE3 7 | #cmakedefine OpenSSL_FOUND 8 | #cmakedefine Boost_FOUND 9 | 10 | #cmakedefine COMPILATION_FLAGS "@COMPILATION_FLAGS@@DROGON_CXX_STANDARD@" 11 | #cmakedefine COMPILER_COMMAND "@COMPILER_COMMAND@" 12 | #cmakedefine COMPILER_ID "@COMPILER_ID@" 13 | 14 | #cmakedefine INCLUDING_DIRS "@INCLUDING_DIRS@" 15 | -------------------------------------------------------------------------------- /examples/simple_example/ForwardCtrl.cc: -------------------------------------------------------------------------------- 1 | #include "ForwardCtrl.h" 2 | void ForwardCtrl::asyncHandleHttpRequest( 3 | const HttpRequestPtr &req, 4 | std::function &&callback) 5 | { 6 | req->setPath("/repos/an-tao/drogon/git/refs/heads/master"); 7 | app().forward( 8 | req, 9 | [callback = std::move(callback)](const HttpResponsePtr &resp) { 10 | callback(resp); 11 | }, 12 | "https://api.github.com"); 13 | } -------------------------------------------------------------------------------- /examples/benchmark/JsonCtrl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace drogon; 4 | class JsonCtrl : public drogon::HttpSimpleController 5 | { 6 | public: 7 | virtual void asyncHandleHttpRequest( 8 | const HttpRequestPtr &req, 9 | std::function &&callback) override; 10 | PATH_LIST_BEGIN 11 | // list path definitions here; 12 | PATH_ADD("/json", Get); 13 | PATH_LIST_END 14 | }; 15 | -------------------------------------------------------------------------------- /drogon_ctl/templates/gitignore.csp: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | build 35 | cmake-build-debug 36 | .idea 37 | -------------------------------------------------------------------------------- /examples/simple_reverse_proxy/.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | build 35 | cmake-build-debug 36 | .idea 37 | -------------------------------------------------------------------------------- /examples/simple_example/ForwardCtrl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace drogon; 4 | class ForwardCtrl : public drogon::HttpSimpleController 5 | { 6 | public: 7 | virtual void asyncHandleHttpRequest( 8 | const HttpRequestPtr &req, 9 | std::function &&callback) override; 10 | PATH_LIST_BEGIN 11 | // list path definitions here; 12 | PATH_ADD("/forward", Get); 13 | PATH_LIST_END 14 | }; 15 | -------------------------------------------------------------------------------- /examples/simple_example/PipeliningTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace drogon; 4 | class PipeliningTest : public drogon::HttpSimpleController 5 | { 6 | public: 7 | virtual void asyncHandleHttpRequest( 8 | const HttpRequestPtr &req, 9 | std::function &&callback) override; 10 | PATH_LIST_BEGIN 11 | // list path definitions here; 12 | PATH_ADD("/pipe", Get); 13 | PATH_LIST_END 14 | }; 15 | -------------------------------------------------------------------------------- /lib/tests/CookiesTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() 4 | { 5 | drogon::Cookie cookie1("test", "1"); 6 | std::cout << cookie1.cookieString(); 7 | drogon::Cookie cookie2("test", "2"); 8 | cookie2.setSecure(true); 9 | std::cout << cookie2.cookieString(); 10 | drogon::Cookie cookie3("test", "3"); 11 | cookie3.setDomain("drogon.org"); 12 | cookie3.setExpiresDate(trantor::Date::date().after(3600 * 24)); 13 | std::cout << cookie3.cookieString(); 14 | } 15 | -------------------------------------------------------------------------------- /drogon_ctl/templates/plugin_cc.csp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * [[filename]].cc 4 | * 5 | */ 6 | 7 | #include "[[filename]].h" 8 | 9 | using namespace drogon; 10 | <%c++auto namespaceStr=@@.get("namespaceString"); 11 | if(!namespaceStr.empty()) 12 | $$<<"using namespace "< 14 | 15 | void [[className]]::initAndStart(const Json::Value &config) 16 | { 17 | /// Initialize and start the plugin 18 | } 19 | 20 | void [[className]]::shutdown() 21 | { 22 | /// Shutdown the plugin 23 | } 24 | -------------------------------------------------------------------------------- /examples/simple_example/ListParaCtl.cc: -------------------------------------------------------------------------------- 1 | #include "ListParaCtl.h" 2 | void ListParaCtl::asyncHandleHttpRequest( 3 | const HttpRequestPtr &req, 4 | std::function &&callback) 5 | { 6 | // write your application logic here 7 | HttpViewData data; 8 | data.insert("title", "list parameters"); 9 | data.insert("parameters", req->getParameters()); 10 | auto res = 11 | drogon::HttpResponse::newHttpViewResponse("ListParaView.csp", data); 12 | callback(res); 13 | } 14 | -------------------------------------------------------------------------------- /drogon_ctl/cmd.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * cmd.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | #define ARGS_ERROR_STR "args error!use help command to get usage!" 21 | void exeCommand(std::vector ¶meters); 22 | -------------------------------------------------------------------------------- /examples/simple_example/TimeFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by antao on 2018/5/22. 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | using namespace drogon; 9 | 10 | class TimeFilter : public drogon::HttpFilter 11 | { 12 | public: 13 | virtual void doFilter(const HttpRequestPtr &req, 14 | FilterCallback &&cb, 15 | FilterChainCallback &&ccb) override; 16 | TimeFilter() 17 | { 18 | LOG_DEBUG << "TimeFilter constructor"; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /lib/src/ssl_funcs/Sha1.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Sha1.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | 19 | #define SHA_DIGEST_LENGTH 20 20 | 21 | unsigned char *SHA1(const unsigned char *dataIn, 22 | size_t dataLen, 23 | unsigned char *dataOut); 24 | -------------------------------------------------------------------------------- /examples/simple_example/ListParaCtl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace drogon; 4 | class ListParaCtl : public drogon::HttpSimpleController 5 | { 6 | public: 7 | virtual void asyncHandleHttpRequest( 8 | const HttpRequestPtr &req, 9 | std::function &&callback) override; 10 | PATH_LIST_BEGIN 11 | // list path definations here; 12 | // PATH_ADD("/path","filter1","filter2",...); 13 | PATH_ADD("/listpara", Get); 14 | PATH_LIST_END 15 | }; 16 | -------------------------------------------------------------------------------- /examples/simple_example/JsonTestController.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | using namespace drogon; 5 | 6 | class JsonTestController 7 | : public drogon::HttpSimpleController 8 | { 9 | public: 10 | // TestController(){} 11 | virtual void asyncHandleHttpRequest( 12 | const HttpRequestPtr &req, 13 | std::function &&callback) override; 14 | 15 | PATH_LIST_BEGIN 16 | PATH_ADD("/json", Get, "drogon::LocalHostFilter"); 17 | PATH_LIST_END 18 | }; 19 | -------------------------------------------------------------------------------- /lib/tests/MainLoopTest2.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * @brief This test program tests to call the app().run() in another thread. 7 | * 8 | */ 9 | int main() 10 | { 11 | std::thread([]() { 12 | drogon::app().getLoop()->runEvery(1, []() { 13 | std::cout << "!" << std::endl; 14 | }); 15 | }).detach(); 16 | 17 | std::thread l([]() { drogon::app().run(); }); 18 | std::this_thread::sleep_for(std::chrono::seconds(1)); 19 | trantor::EventLoop loop; 20 | l.join(); 21 | } -------------------------------------------------------------------------------- /examples/simple_example/TestViewCtl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace drogon; 4 | class TestViewCtl : public drogon::HttpSimpleController 5 | { 6 | public: 7 | virtual void asyncHandleHttpRequest( 8 | const HttpRequestPtr &req, 9 | std::function &&callback) override; 10 | PATH_LIST_BEGIN 11 | // list path definations here; 12 | // PATH_ADD("/path","filter1","filter2",...); 13 | PATH_ADD("/view"); 14 | PATH_ADD("/", Post); 15 | PATH_LIST_END 16 | }; 17 | -------------------------------------------------------------------------------- /lib/tests/HttpViewDataTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() 4 | { 5 | drogon::HttpViewData data; 6 | std::cout << (data.insert("1", 1), data.get("1")) << std::endl; 7 | std::cout << (data.insertAsString("2", 2.0), data.get("2")) 8 | << std::endl; 9 | std::cout << (data.insertFormattedString("3", "third value is %d", 3), 10 | data.get("3")) 11 | << std::endl; 12 | std::cout << (data.insertAsString("4", "4"), data.get("4")) 13 | << std::endl; 14 | } 15 | -------------------------------------------------------------------------------- /lib/tests/ClassNameTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | namespace api 4 | { 5 | namespace v1 6 | { 7 | template 8 | class handler : public drogon::DrObject 9 | { 10 | public: 11 | static void p() 12 | { 13 | std::cout << handler::classTypeName() << std::endl; 14 | } 15 | }; 16 | class hh : public handler 17 | { 18 | }; 19 | } // namespace v1 20 | } // namespace api 21 | int main() 22 | { 23 | api::v1::hh h; 24 | std::cout << h.className() << std::endl; 25 | std::cout << api::v1::hh::classTypeName() << std::endl; 26 | h.p(); 27 | } 28 | -------------------------------------------------------------------------------- /lib/tests/UrlCodecTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | std::string input = "k1=1&k2=安"; 8 | auto output = drogon::utils::urlEncode(input); 9 | std::cout << output << std::endl; 10 | auto output2 = drogon::utils::urlDecode(output); 11 | std::cout << output2 << std::endl; 12 | std::cout << drogon::utils::urlEncode("k2=安&k1=1") << std::endl; 13 | std::cout << drogon::utils::urlDecode( 14 | drogon::string_view("k2%3D%E5%AE%89&k1%3D1")) 15 | << std::endl; 16 | return 0; 17 | } -------------------------------------------------------------------------------- /unittest/MD5Unittest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | TEST(Md5Test, md5) 6 | { 7 | EXPECT_EQ(drogon::utils::getMd5( 8 | "123456789012345678901234567890123456789012345" 9 | "678901234567890123456789012345678901234567890" 10 | "1234567890"), 11 | "49CB3608E2B33FAD6B65DF8CB8F49668"); 12 | EXPECT_EQ(drogon::utils::getMd5("1"), "C4CA4238A0B923820DCC509A6F75849B"); 13 | } 14 | 15 | int main(int argc, char **argv) 16 | { 17 | testing::InitGoogleTest(&argc, argv); 18 | return RUN_ALL_TESTS(); 19 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | build 35 | cmake-build-debug 36 | .idea 37 | lib/inc/drogon/version.h 38 | html/ 39 | latex/ 40 | .vscode 41 | *.kdev4 42 | .cproject 43 | .project 44 | .settings/ 45 | .vs/ 46 | CMakeSettings.json 47 | install 48 | -------------------------------------------------------------------------------- /lib/inc/drogon/DrTemplate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * DrTemplate.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | namespace drogon 20 | { 21 | template 22 | class DrTemplate : public DrObject, public DrTemplateBase 23 | { 24 | protected: 25 | DrTemplate() 26 | { 27 | } 28 | }; 29 | 30 | } // namespace drogon 31 | -------------------------------------------------------------------------------- /examples/simple_example/CustomHeaderFilter.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * CustomHeaderFilter.cc 4 | * 5 | */ 6 | 7 | #include "CustomHeaderFilter.h" 8 | 9 | using namespace drogon; 10 | 11 | void CustomHeaderFilter::doFilter(const HttpRequestPtr &req, 12 | FilterCallback &&fcb, 13 | FilterChainCallback &&fccb) 14 | { 15 | if (req->getHeader(field_) == value_) 16 | { 17 | // Passed 18 | fccb(); 19 | return; 20 | } 21 | // Check failed 22 | auto res = drogon::HttpResponse::newHttpResponse(); 23 | res->setStatusCode(k500InternalServerError); 24 | fcb(res); 25 | } 26 | -------------------------------------------------------------------------------- /examples/simple_example_test/ws_test.html: -------------------------------------------------------------------------------- 1 | 2 |

 3 | 
24 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
 1 | ---
 2 | name: Feature request
 3 | about: Suggest an idea for this project
 4 | labels: 
 5 | 
 6 | ---
 7 | 
 8 | **Is your feature request related to a problem? Please describe.**
 9 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
10 | 
11 | **Describe the solution you'd like**
12 | A clear and concise description of what you want to happen.
13 | 
14 | **Describe alternatives you've considered**
15 | A clear and concise description of any alternative solutions or features you've considered.
16 | 
17 | **Additional context**
18 | Add any other context or screenshots about the feature request here.
19 | 


--------------------------------------------------------------------------------
/examples/simple_example/CustomHeaderFilter.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  *
 3 |  *  CustomHeaderFilter.h
 4 |  *
 5 |  */
 6 | 
 7 | #pragma once
 8 | 
 9 | #include 
10 | using namespace drogon;
11 | 
12 | class CustomHeaderFilter : public HttpFilter
13 | {
14 |   public:
15 |     CustomHeaderFilter(const std::string &field, const std::string &value)
16 |         : field_(field), value_(value)
17 |     {
18 |     }
19 |     virtual void doFilter(const HttpRequestPtr &req,
20 |                           FilterCallback &&fcb,
21 |                           FilterChainCallback &&fccb) override;
22 | 
23 |   private:
24 |     std::string field_;
25 |     std::string value_;
26 | };
27 | 


--------------------------------------------------------------------------------
/examples/simple_example/DoNothingPlugin.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  *
 3 |  *  DoNothingPlugin.h
 4 |  *
 5 |  */
 6 | 
 7 | #pragma once
 8 | 
 9 | #include 
10 | using namespace drogon;
11 | 
12 | class DoNothingPlugin : public Plugin
13 | {
14 |   public:
15 |     DoNothingPlugin()
16 |     {
17 |     }
18 |     /// This method must be called by drogon to initialize and start the plugin.
19 |     /// It must be implemented by the user.
20 |     virtual void initAndStart(const Json::Value &config) override;
21 | 
22 |     /// This method must be called by drogon to shutdown the plugin.
23 |     /// It must be implemented by the user.
24 |     virtual void shutdown() override;
25 | };
26 | 


--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
 1 | # These are supported funding model platforms
 2 | 
 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
 4 | patreon: # Replace with a single Patreon username
 5 | open_collective: # Replace with a single Open Collective username
 6 | ko_fi: # Replace with a single Ko-fi username
 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
 9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: ['https://paypal.me/antao2019']
13 | 


--------------------------------------------------------------------------------
/lib/inc/drogon/utils/any.h:
--------------------------------------------------------------------------------
 1 | /**
 2 |  *
 3 |  *  any.h
 4 |  *  An Tao
 5 |  *
 6 |  *  Copyright 2018, An Tao.  All rights reserved.
 7 |  *  https://github.com/an-tao/drogon
 8 |  *  Use of this source code is governed by a MIT license
 9 |  *  that can be found in the License file.
10 |  *
11 |  *  Drogon
12 |  *
13 |  */
14 | 
15 | #pragma once
16 | #if __cplusplus >= 201703L || (defined _MSC_VER && _MSC_VER > 1900)
17 | #include 
18 | #else
19 | #include 
20 | #endif
21 | 
22 | namespace drogon
23 | {
24 | #if __cplusplus >= 201703L || (defined _MSC_VER && _MSC_VER > 1900)
25 | using std::any;
26 | using std::any_cast;
27 | #else
28 | using boost::any;
29 | using boost::any_cast;
30 | #endif
31 | }  // namespace drogon
32 | 


--------------------------------------------------------------------------------
/examples/benchmark/main.cc:
--------------------------------------------------------------------------------
 1 | #include 
 2 | 
 3 | using namespace drogon;
 4 | int main()
 5 | {
 6 |     app()
 7 |         .setLogPath("./")
 8 |         .setLogLevel(trantor::Logger::kWarn)
 9 |         .addListener("0.0.0.0", 7770)
10 |         .setThreadNum(0)
11 |         .registerSyncAdvice([](const HttpRequestPtr &req) -> HttpResponsePtr {
12 |             const auto &path = req->path();
13 |             if (path.length() == 1 && path[0] == '/')
14 |             {
15 |                 auto response = HttpResponse::newHttpResponse();
16 |                 response->setBody("

Hello, world!

"); 17 | return response; 18 | } 19 | return nullptr; 20 | }) 21 | .run(); 22 | } 23 | -------------------------------------------------------------------------------- /examples/simple_example/TestController.cc: -------------------------------------------------------------------------------- 1 | #include "TestController.h" 2 | using namespace example; 3 | void TestController::asyncHandleHttpRequest( 4 | const HttpRequestPtr &req, 5 | std::function &&callback) 6 | { 7 | // write your application logic here 8 | LOG_WARN << req->matchedPathPatternData(); 9 | LOG_DEBUG << "index=" << threadIndex_.getThreadData(); 10 | ++(threadIndex_.getThreadData()); 11 | auto resp = HttpResponse::newHttpResponse(); 12 | resp->setContentTypeCodeAndCustomString(CT_TEXT_PLAIN, 13 | "Content-Type: plaintext\r\n"); 14 | resp->setBody("

Hello, world!

"); 15 | resp->setExpiredTime(20); 16 | callback(resp); 17 | } 18 | -------------------------------------------------------------------------------- /examples/simple_example/ListParaView.csp: -------------------------------------------------------------------------------- 1 | 2 | 3 | <%c++ 4 | auto para=@@.get>("parameters"); 5 | %> 6 | 7 | 8 | [[ title ]] 9 | 10 | 11 | <%view header %> 12 | <%c++ if(para.size()>0){%> 13 |

Parameters

14 | 15 | 16 | 17 | 18 | 19 | <%c++ for(auto iter:para){%> 20 | 21 | 22 | 23 | 24 | <%c++}%> 25 |
namevalue
{%iter.first%}<%c++ $$<
26 | <%c++ }else{%> 27 |

no parameter

28 | <%c++}%> 29 | 30 | 31 | -------------------------------------------------------------------------------- /examples/simple_example/JsonTestController.cc: -------------------------------------------------------------------------------- 1 | #include "JsonTestController.h" 2 | #include 3 | void JsonTestController::asyncHandleHttpRequest( 4 | const HttpRequestPtr &req, 5 | std::function &&callback) 6 | { 7 | Json::Value json; 8 | json["path"] = "json"; 9 | json["name"] = "json test"; 10 | Json::Value array; 11 | for (int i = 0; i < 5; ++i) 12 | { 13 | Json::Value user; 14 | user["id"] = i; 15 | user["name"] = "none"; 16 | user["c_name"] = "张三"; 17 | array.append(user); 18 | } 19 | json["rows"] = array; 20 | auto resp = HttpResponse::newHttpJsonResponse(json); 21 | assert(resp->jsonObject().get()); 22 | callback(resp); 23 | } 24 | -------------------------------------------------------------------------------- /drogon_ctl/templates/filter_cc.csp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * [[filename]].cc 4 | * 5 | */ 6 | 7 | #include "[[filename]].h" 8 | 9 | using namespace drogon; 10 | <%c++auto namespaceStr=@@.get("namespaceString"); 11 | if(!namespaceStr.empty()) 12 | $$<<"using namespace "< 14 | 15 | void [[className]]::doFilter(const HttpRequestPtr &req, 16 | FilterCallback &&fcb, 17 | FilterChainCallback &&fccb) 18 | { 19 | //Edit your logic here 20 | if (1) 21 | { 22 | //Passed 23 | fccb(); 24 | return; 25 | } 26 | //Check failed 27 | auto res = drogon::HttpResponse::newHttpResponse(); 28 | res->setStatusCode(k500InternalServerError); 29 | fcb(res); 30 | } 31 | -------------------------------------------------------------------------------- /examples/simple_example/TestPlugin.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * TestPlugin.h 4 | * 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | using namespace drogon; 11 | 12 | class TestPlugin : public Plugin 13 | { 14 | public: 15 | TestPlugin() 16 | { 17 | } 18 | /// This method must be called by drogon to initialize and start the plugin. 19 | /// It must be implemented by the user. 20 | virtual void initAndStart(const Json::Value &config) override; 21 | 22 | /// This method must be called by drogon to shutdown the plugin. 23 | /// It must be implemented by the user. 24 | virtual void shutdown() override; 25 | 26 | private: 27 | std::thread workThread_; 28 | bool stop_{false}; 29 | int interval_; 30 | }; 31 | -------------------------------------------------------------------------------- /drogon_ctl/templates/filter_h.csp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * [[filename]].h 4 | * 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | using namespace drogon; 11 | <%c++ 12 | auto namespaceVector=@@.get>("namespaceVector"); 13 | if(namespaceVector.empty()) 14 | $$<<"\n"; 15 | for(auto &namespaceName:namespaceVector){%> 16 | namespace {%namespaceName%} 17 | 18 | { 19 | <%c++} 20 | $$<<"\n";%> 21 | class [[className]] : public HttpFilter<[[className]]> 22 | { 23 | public: 24 | [[className]]() {} 25 | virtual void doFilter(const HttpRequestPtr &req, 26 | FilterCallback &&fcb, 27 | FilterChainCallback &&fccb) override; 28 | }; 29 | 30 | <%c++for(size_t i=0;i 31 | } 32 | <%c++}%> -------------------------------------------------------------------------------- /lib/src/LocalHostFilter.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * LocalHostFilter.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "HttpResponseImpl.h" 16 | #include 17 | using namespace drogon; 18 | void LocalHostFilter::doFilter(const HttpRequestPtr &req, 19 | FilterCallback &&fcb, 20 | FilterChainCallback &&fccb) 21 | { 22 | if (req->peerAddr().isLoopbackIp()) 23 | { 24 | fccb(); 25 | return; 26 | } 27 | auto res = drogon::HttpResponse::newNotFoundResponse(); 28 | fcb(res); 29 | } 30 | -------------------------------------------------------------------------------- /unittest/SHA1Unittest.cpp: -------------------------------------------------------------------------------- 1 | #include "../lib/src/ssl_funcs/Sha1.h" 2 | #include 3 | #include 4 | 5 | TEST(SHA1Test, sha1) 6 | { 7 | unsigned char in[] = 8 | "1234567890123456789012345678901234567890123456789012345" 9 | "678901234567890123456789012345678901234567890"; 10 | unsigned char out[SHA_DIGEST_LENGTH] = {0}; 11 | SHA1(in, strlen((const char *)in), out); 12 | std::string outStr; 13 | outStr.resize(SHA_DIGEST_LENGTH * 2); 14 | for (int i = 0; i < SHA_DIGEST_LENGTH; ++i) 15 | sprintf((char *)(outStr.data() + i * 2), "%02x", out[i]); 16 | EXPECT_EQ(outStr, "fecfd28bbc9345891a66d7c1b8ff46e60192d284"); 17 | } 18 | 19 | int main(int argc, char **argv) 20 | { 21 | testing::InitGoogleTest(&argc, argv); 22 | return RUN_ALL_TESTS(); 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/IntranetIpFilter.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * IntranetIpFilter.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "HttpResponseImpl.h" 16 | #include 17 | using namespace drogon; 18 | void IntranetIpFilter::doFilter(const HttpRequestPtr &req, 19 | FilterCallback &&fcb, 20 | FilterChainCallback &&fccb) 21 | { 22 | if (req->peerAddr().isIntranetIp()) 23 | { 24 | fccb(); 25 | return; 26 | } 27 | auto res = drogon::HttpResponse::newNotFoundResponse(); 28 | fcb(res); 29 | } 30 | -------------------------------------------------------------------------------- /lib/inc/drogon/NotFound.h: -------------------------------------------------------------------------------- 1 | // this file is generated by program automatically,don't modify it! 2 | 3 | /** 4 | * 5 | * NotFound.h 6 | * An Tao 7 | * 8 | * Copyright 2018, An Tao. All rights reserved. 9 | * https://github.com/an-tao/drogon 10 | * Use of this source code is governed by a MIT license 11 | * that can be found in the License file. 12 | * 13 | * Drogon 14 | * 15 | */ 16 | 17 | #include 18 | namespace drogon 19 | { 20 | /** 21 | * @brief This class is used by the drogon to generate the 404 page. Users don't 22 | * use this class directly. 23 | */ 24 | class NotFound : public drogon::DrTemplate 25 | { 26 | public: 27 | NotFound(){}; 28 | virtual ~NotFound(){}; 29 | virtual std::string genText(const drogon::HttpViewData &) override; 30 | }; 31 | } // namespace drogon 32 | -------------------------------------------------------------------------------- /examples/simple_example/CustomCtrl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace drogon; 4 | class CustomCtrl : public drogon::HttpController 5 | { 6 | public: 7 | METHOD_LIST_BEGIN 8 | // use METHOD_ADD to add your custom processing function here; 9 | METHOD_ADD(CustomCtrl::hello, 10 | "/{userName}", 11 | Get, 12 | "CustomHeaderFilter"); // path is /customctrl/{arg1} 13 | METHOD_LIST_END 14 | 15 | explicit CustomCtrl(const std::string &greetings) : greetings_(greetings) 16 | { 17 | } 18 | 19 | void hello(const HttpRequestPtr &req, 20 | std::function &&callback, 21 | const std::string &userName) const; 22 | 23 | private: 24 | std::string greetings_; 25 | }; 26 | -------------------------------------------------------------------------------- /lib/inc/drogon/LocalHostFilter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * LocalHostFilter.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | 19 | namespace drogon 20 | { 21 | /** 22 | * @brief A filter that prohibit access from other hosts. 23 | */ 24 | class LocalHostFilter : public HttpFilter 25 | { 26 | public: 27 | LocalHostFilter() 28 | { 29 | } 30 | virtual void doFilter(const HttpRequestPtr &req, 31 | FilterCallback &&fcb, 32 | FilterChainCallback &&fccb) override; 33 | }; 34 | } // namespace drogon 35 | -------------------------------------------------------------------------------- /lib/inc/drogon/IntranetIpFilter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * IntranetIpFilter.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | 19 | namespace drogon 20 | { 21 | /** 22 | * @brief A filter that prohibit access from external networks 23 | */ 24 | class IntranetIpFilter : public HttpFilter 25 | { 26 | public: 27 | IntranetIpFilter() 28 | { 29 | } 30 | virtual void doFilter(const HttpRequestPtr &req, 31 | FilterCallback &&fcb, 32 | FilterChainCallback &&fccb) override; 33 | }; 34 | } // namespace drogon 35 | -------------------------------------------------------------------------------- /drogon_ctl/help.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * help.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include "CommandHandler.h" 19 | using namespace drogon; 20 | namespace drogon_ctl 21 | { 22 | class help : public DrObject, public CommandHandler 23 | { 24 | public: 25 | virtual void handleCommand(std::vector ¶meters) override; 26 | virtual std::string script() override 27 | { 28 | return "display this message"; 29 | } 30 | virtual bool isTopCommand() override 31 | { 32 | return true; 33 | } 34 | }; 35 | } // namespace drogon_ctl 36 | -------------------------------------------------------------------------------- /drogon_ctl/create_filter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * create_filter.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include "CommandHandler.h" 19 | using namespace drogon; 20 | namespace drogon_ctl 21 | { 22 | class create_filter : public DrObject, public CommandHandler 23 | { 24 | public: 25 | virtual void handleCommand(std::vector ¶meters) override; 26 | virtual std::string script() override 27 | { 28 | return "create filter class files"; 29 | } 30 | 31 | protected: 32 | std::string outputPath_{"."}; 33 | }; 34 | } // namespace drogon_ctl 35 | -------------------------------------------------------------------------------- /drogon_ctl/create_plugin.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * create_plugin.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include "CommandHandler.h" 19 | using namespace drogon; 20 | namespace drogon_ctl 21 | { 22 | class create_plugin : public DrObject, public CommandHandler 23 | { 24 | public: 25 | virtual void handleCommand(std::vector ¶meters) override; 26 | virtual std::string script() override 27 | { 28 | return "create plugin class files"; 29 | } 30 | 31 | protected: 32 | std::string outputPath_{"."}; 33 | }; 34 | } // namespace drogon_ctl 35 | -------------------------------------------------------------------------------- /examples/simple_example/WebSocketTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace drogon; 4 | namespace example 5 | { 6 | class WebSocketTest : public drogon::WebSocketController 7 | { 8 | public: 9 | virtual void handleNewMessage(const WebSocketConnectionPtr &, 10 | std::string &&, 11 | const WebSocketMessageType &) override; 12 | virtual void handleConnectionClosed( 13 | const WebSocketConnectionPtr &) override; 14 | virtual void handleNewConnection(const HttpRequestPtr &, 15 | const WebSocketConnectionPtr &) override; 16 | WS_PATH_LIST_BEGIN 17 | // list path definations here; 18 | WS_PATH_ADD("/chat", "drogon::LocalHostFilter", Get); 19 | WS_PATH_LIST_END 20 | }; 21 | } // namespace example 22 | -------------------------------------------------------------------------------- /lib/src/ConfigLoader.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * ConfigLoader.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | namespace drogon 22 | { 23 | class ConfigLoader : public trantor::NonCopyable 24 | { 25 | public: 26 | explicit ConfigLoader(const std::string &configFile); 27 | ~ConfigLoader(); 28 | const Json::Value &jsonValue() const 29 | { 30 | return configJsonRoot_; 31 | } 32 | void load(); 33 | 34 | private: 35 | std::string configFile_; 36 | Json::Value configJsonRoot_; 37 | }; 38 | } // namespace drogon 39 | -------------------------------------------------------------------------------- /examples/simple_example/TestPlugin.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * TestPlugin.cc 4 | * 5 | */ 6 | 7 | #include "TestPlugin.h" 8 | #include 9 | #include 10 | using namespace std::chrono_literals; 11 | 12 | using namespace drogon; 13 | 14 | void TestPlugin::initAndStart(const Json::Value &config) 15 | { 16 | /// Initialize and start the plugin 17 | if (config.isNull()) 18 | LOG_DEBUG << "Configuration not defined"; 19 | interval_ = config.get("heartbeat_interval", 1).asInt(); 20 | workThread_ = std::thread([this]() { 21 | while (!stop_) 22 | { 23 | LOG_DEBUG << "TestPlugin heartbeat!"; 24 | std::this_thread::sleep_for(std::chrono::seconds(interval_)); 25 | } 26 | }); 27 | } 28 | 29 | void TestPlugin::shutdown() 30 | { 31 | /// Shutdown the plugin 32 | stop_ = true; 33 | workThread_.join(); 34 | } 35 | -------------------------------------------------------------------------------- /unittest/PubSubServiceUnittest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | TEST(PubSubServiceTest, normal) 7 | { 8 | drogon::PubSubService service; 9 | auto id=service.subscribe("topic1", 10 | [](const std::string &topic, const std::string &message) { 11 | EXPECT_STREQ(topic.c_str(), "topic1"); 12 | EXPECT_STREQ(message.c_str(), "hello world"); 13 | }); 14 | service.publish("topic1", "hello world"); 15 | service.publish("topic2", "hello world"); 16 | EXPECT_EQ(service.size(), 1); 17 | service.unsubscribe("topic1", id); 18 | EXPECT_EQ(service.size(), 0); 19 | } 20 | 21 | int main(int argc, char **argv) 22 | { 23 | testing::InitGoogleTest(&argc, argv); 24 | return RUN_ALL_TESTS(); 25 | } -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | 3 | RUN apt-get update -yqq \ 4 | && apt-get install -yqq --no-install-recommends software-properties-common \ 5 | sudo curl wget cmake pkg-config locales git gcc-8 g++-8 \ 6 | openssl libssl-dev libjsoncpp-dev uuid-dev zlib1g-dev libc-ares-dev\ 7 | postgresql-server-dev-all libmariadbclient-dev libsqlite3-dev \ 8 | && rm -rf /var/lib/apt/lists/* \ 9 | && locale-gen en_US.UTF-8 10 | 11 | ENV LANG=en_US.UTF-8 \ 12 | LANGUAGE=en_US:en \ 13 | LC_ALL=en_US.UTF-8 \ 14 | CC=gcc-8 \ 15 | CXX=g++-8 \ 16 | AR=gcc-ar-8 \ 17 | RANLIB=gcc-ranlib-8 \ 18 | IROOT=/install 19 | 20 | ENV DROGON_ROOT="$IROOT/drogon" 21 | 22 | ADD https://api.github.com/repos/an-tao/drogon/git/refs/heads/master $IROOT/version.json 23 | RUN git clone https://github.com/an-tao/drogon $DROGON_ROOT 24 | 25 | WORKDIR $DROGON_ROOT 26 | 27 | RUN ./build.sh 28 | -------------------------------------------------------------------------------- /drogon_ctl/CommandHandler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * CommandHandler.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | class CommandHandler : public virtual drogon::DrObjectBase 22 | { 23 | public: 24 | virtual void handleCommand(std::vector ¶meters) = 0; 25 | virtual bool isTopCommand() 26 | { 27 | return false; 28 | } 29 | virtual std::string script() 30 | { 31 | return ""; 32 | } 33 | virtual std::string detail() 34 | { 35 | return ""; 36 | } 37 | virtual ~CommandHandler() 38 | { 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /drogon_ctl/create_project.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * create_project.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | #pragma once 15 | 16 | #include 17 | #include "CommandHandler.h" 18 | using namespace drogon; 19 | namespace drogon_ctl 20 | { 21 | class create_project : public DrObject, public CommandHandler 22 | { 23 | public: 24 | virtual void handleCommand(std::vector ¶meters) override; 25 | virtual std::string script() override 26 | { 27 | return "create a project"; 28 | } 29 | 30 | protected: 31 | std::string outputPath_{"."}; 32 | void createProject(const std::string &projectName); 33 | }; 34 | } // namespace drogon_ctl 35 | -------------------------------------------------------------------------------- /examples/simple_example/WebSocketTest.cc: -------------------------------------------------------------------------------- 1 | #include "WebSocketTest.h" 2 | using namespace example; 3 | void WebSocketTest::handleNewMessage(const WebSocketConnectionPtr &wsConnPtr, 4 | std::string &&message, 5 | const WebSocketMessageType &type) 6 | { 7 | // write your application logic here 8 | LOG_DEBUG << "new websocket message:" << message; 9 | if (type == WebSocketMessageType::Ping) 10 | { 11 | LOG_DEBUG << "recv a ping"; 12 | } 13 | } 14 | 15 | void WebSocketTest::handleConnectionClosed(const WebSocketConnectionPtr &) 16 | { 17 | LOG_DEBUG << "websocket closed!"; 18 | } 19 | 20 | void WebSocketTest::handleNewConnection(const HttpRequestPtr &, 21 | const WebSocketConnectionPtr &conn) 22 | { 23 | LOG_DEBUG << "new websocket connection!"; 24 | conn->send("haha!!!"); 25 | } 26 | -------------------------------------------------------------------------------- /drogon_ctl/version.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * version.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include "CommandHandler.h" 19 | using namespace drogon; 20 | namespace drogon_ctl 21 | { 22 | class version : public DrObject, public CommandHandler 23 | { 24 | public: 25 | virtual void handleCommand(std::vector ¶meters) override; 26 | virtual std::string script() override 27 | { 28 | return "display version of this tool"; 29 | } 30 | virtual bool isTopCommand() override 31 | { 32 | return true; 33 | } 34 | version() 35 | { 36 | } 37 | }; 38 | } // namespace drogon_ctl 39 | -------------------------------------------------------------------------------- /cmake_modules/Findcoz-profiler.cmake: -------------------------------------------------------------------------------- 1 | find_path(COZ_INCLUDE_DIRS NAMES coz.h) 2 | 3 | find_library(COZ_LIBRARIES NAMES coz PATH_SUFFIXES coz-profiler) 4 | 5 | include(FindPackageHandleStandardArgs) 6 | find_package_handle_standard_args(coz-profiler 7 | DEFAULT_MSG 8 | COZ_LIBRARIES 9 | COZ_INCLUDE_DIRS) 10 | 11 | if(COZ-PROFILER_FOUND) 12 | add_library(coz::coz INTERFACE IMPORTED) 13 | set_target_properties(coz::coz 14 | PROPERTIES INTERFACE_INCLUDE_DIRECTORIES 15 | ${COZ_INCLUDE_DIRS} 16 | INTERFACE_LINK_LIBRARIES 17 | ${COZ_LIBRARIES}) 18 | else(COZ-PROFILER_FOUND) 19 | set(COZ_LIBRARIES) 20 | set(COZ_INCLUDE_DIRS) 21 | endif(COZ-PROFILER_FOUND) 22 | 23 | mark_as_advanced(COZ_INCLUDE_DIRS COZ_LIBRARIES) 24 | -------------------------------------------------------------------------------- /lib/src/HttpFileUploadRequest.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * HttpFileUploadRequest.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "HttpFileUploadRequest.h" 16 | #include 17 | #include 18 | 19 | using namespace drogon; 20 | 21 | HttpFileUploadRequest::HttpFileUploadRequest( 22 | const std::vector &files) 23 | : HttpRequestImpl(nullptr), 24 | boundary_(utils::genRandomString(32)), 25 | files_(files) 26 | { 27 | setMethod(drogon::Post); 28 | setVersion(drogon::Version::kHttp11); 29 | setContentType("Content-Type: multipart/form-data; boundary=" + boundary_ + 30 | "\r\n"); 31 | contentType_ = CT_MULTIPART_FORM_DATA; 32 | } -------------------------------------------------------------------------------- /examples/simple_example/TestController.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | using namespace drogon; 5 | namespace example 6 | { 7 | class TestController : public drogon::HttpSimpleController 8 | { 9 | public: 10 | virtual void asyncHandleHttpRequest( 11 | const HttpRequestPtr &req, 12 | std::function &&callback) override; 13 | PATH_LIST_BEGIN 14 | // list path definations here; 15 | // PATH_ADD("/path","filter1","filter2",...); 16 | PATH_ADD("/", Get); 17 | PATH_ADD("/Test", "nonFilter"); 18 | PATH_ADD("/tpost", Post, Options); 19 | PATH_ADD("/slow", "TimeFilter", Get); 20 | PATH_LIST_END 21 | TestController() 22 | { 23 | LOG_DEBUG << "TestController constructor"; 24 | } 25 | 26 | private: 27 | drogon::IOThreadStorage threadIndex_; 28 | }; 29 | } // namespace example 30 | -------------------------------------------------------------------------------- /lib/src/HttpFileUploadRequest.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * HttpFileUploadRequest.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | #include "HttpRequestImpl.h" 17 | #include 18 | #include 19 | 20 | namespace drogon 21 | { 22 | class HttpFileUploadRequest : public HttpRequestImpl 23 | { 24 | public: 25 | const std::string &boundary() const 26 | { 27 | return boundary_; 28 | } 29 | const std::vector &files() const 30 | { 31 | return files_; 32 | } 33 | explicit HttpFileUploadRequest(const std::vector &files); 34 | 35 | private: 36 | std::string boundary_; 37 | std::vector files_; 38 | }; 39 | 40 | } // namespace drogon 41 | -------------------------------------------------------------------------------- /unittest/GzipUnittest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace drogon::utils; 6 | TEST(GzipTest, shortText) 7 | { 8 | std::string source{"123中文顶替要枯械"}; 9 | auto compressed = gzipCompress(source.data(), source.length()); 10 | auto decompressed = gzipDecompress(compressed.data(), compressed.length()); 11 | EXPECT_EQ(source, decompressed); 12 | } 13 | 14 | TEST(GzipTest, longText) 15 | { 16 | std::string source; 17 | for (size_t i = 0; i < 100000; i++) 18 | { 19 | source.append(std::to_string(i)); 20 | } 21 | auto compressed = gzipCompress(source.data(), source.length()); 22 | auto decompressed = gzipDecompress(compressed.data(), compressed.length()); 23 | EXPECT_EQ(source, decompressed); 24 | } 25 | 26 | int main(int argc, char **argv) 27 | { 28 | testing::InitGoogleTest(&argc, argv); 29 | return RUN_ALL_TESTS(); 30 | } -------------------------------------------------------------------------------- /drogon_ctl/templates/plugin_h.csp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * [[filename]].h 4 | * 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | <%c++ 11 | auto namespaceVector=@@.get>("namespaceVector"); 12 | if(namespaceVector.empty()) 13 | $$<<"\n"; 14 | for(auto &namespaceName:namespaceVector){%> 15 | namespace {%namespaceName%} 16 | 17 | { 18 | <%c++} 19 | $$<<"\n";%> 20 | class [[className]] : public drogon::Plugin<[[className]]> 21 | { 22 | public: 23 | [[className]]() {} 24 | /// This method must be called by drogon to initialize and start the plugin. 25 | /// It must be implemented by the user. 26 | virtual void initAndStart(const Json::Value &config) override; 27 | 28 | /// This method must be called by drogon to shutdown the plugin. 29 | /// It must be implemented by the user. 30 | virtual void shutdown() override; 31 | }; 32 | 33 | <%c++for(size_t i=0;i 34 | } 35 | <%c++}%> -------------------------------------------------------------------------------- /lib/src/PluginsManager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * PluginsManager.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | #include 17 | #include 18 | 19 | namespace drogon 20 | { 21 | using PluginBasePtr = std::unique_ptr; 22 | 23 | class PluginsManager : trantor::NonCopyable 24 | { 25 | public: 26 | void initializeAllPlugins( 27 | const Json::Value &configs, 28 | const std::function &forEachCallback); 29 | 30 | PluginBase *getPlugin(const std::string &pluginName); 31 | ~PluginsManager(); 32 | 33 | private: 34 | std::map pluginsMap_; 35 | std::vector initializedPlugins_; 36 | }; 37 | 38 | } // namespace drogon 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | labels: 5 | 6 | --- 7 | 8 | **Describe the bug** 9 | A clear and concise description of what the bug is. 10 | 11 | **To Reproduce** 12 | Steps to reproduce the behavior: 13 | 1. Go to '...' 14 | 2. Click on '....' 15 | 3. Scroll down to '....' 16 | 4. See error 17 | 18 | **Expected behavior** 19 | A clear and concise description of what you expected to happen. 20 | 21 | **Screenshots** 22 | If applicable, add screenshots to help explain your problem. 23 | 24 | **Desktop (please complete the following information):** 25 | - OS: [e.g. iOS] 26 | - Browser [e.g. chrome, safari] 27 | - Version [e.g. 22] 28 | 29 | **Smartphone (please complete the following information):** 30 | - Device: [e.g. iPhone6] 31 | - OS: [e.g. iOS8.1] 32 | - Browser [e.g. stock browser, safari] 33 | - Version [e.g. 22] 34 | 35 | **Additional context** 36 | Add any other context about the problem here. 37 | -------------------------------------------------------------------------------- /lib/src/FiltersFunction.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * FiltersFunction.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include "impl_forwards.h" 18 | #include 19 | #include 20 | #include 21 | 22 | namespace drogon 23 | { 24 | namespace filters_function 25 | { 26 | std::vector> createFilters( 27 | const std::vector &filterNames); 28 | void doFilters( 29 | const std::vector> &filters, 30 | const HttpRequestImplPtr &req, 31 | const std::shared_ptr> 32 | &callbackPtr, 33 | std::function &&missCallback); 34 | 35 | } // namespace filters_function 36 | } // namespace drogon 37 | -------------------------------------------------------------------------------- /drogon_ctl/create.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * create.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include "CommandHandler.h" 19 | using namespace drogon; 20 | namespace drogon_ctl 21 | { 22 | class create : public DrObject, public CommandHandler 23 | { 24 | public: 25 | virtual void handleCommand(std::vector ¶meters) override; 26 | virtual std::string script() override 27 | { 28 | return "create some source files(Use 'drogon_ctl help create' for more " 29 | "information)"; 30 | } 31 | virtual bool isTopCommand() override 32 | { 33 | return true; 34 | } 35 | virtual std::string detail() override; 36 | }; 37 | } // namespace drogon_ctl 38 | -------------------------------------------------------------------------------- /unittest/BrotliUnittest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace drogon::utils; 6 | TEST(BrotliTest, shortText) 7 | { 8 | std::string source{"123中文顶替要枯械"}; 9 | auto compressed = brotliCompress(source.data(), source.length()); 10 | auto decompressed = 11 | brotliDecompress(compressed.data(), compressed.length()); 12 | EXPECT_EQ(source, decompressed); 13 | } 14 | 15 | TEST(BrotliTest, longText) 16 | { 17 | std::string source; 18 | for (size_t i = 0; i < 100000; i++) 19 | { 20 | source.append(std::to_string(i)); 21 | } 22 | auto compressed = brotliCompress(source.data(), source.length()); 23 | auto decompressed = 24 | brotliDecompress(compressed.data(), compressed.length()); 25 | EXPECT_EQ(source, decompressed); 26 | } 27 | 28 | int main(int argc, char **argv) 29 | { 30 | testing::InitGoogleTest(&argc, argv); 31 | return RUN_ALL_TESTS(); 32 | } -------------------------------------------------------------------------------- /examples/simple_example/api_Attachment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace drogon; 4 | namespace api 5 | { 6 | class Attachment : public drogon::HttpController 7 | { 8 | public: 9 | METHOD_LIST_BEGIN 10 | // use METHOD_ADD to add your custom processing function here; 11 | METHOD_ADD(Attachment::get, "", Get); // Path is '/api/attachment' 12 | METHOD_ADD(Attachment::upload, "/upload", Post); 13 | METHOD_ADD(Attachment::download, "/download", Get); 14 | METHOD_LIST_END 15 | // your declaration of processing function maybe like this: 16 | void get(const HttpRequestPtr &req, 17 | std::function &&callback); 18 | void upload(const HttpRequestPtr &req, 19 | std::function &&callback); 20 | void download(const HttpRequestPtr &req, 21 | std::function &&callback); 22 | }; 23 | } // namespace api 24 | -------------------------------------------------------------------------------- /lib/inc/drogon/drogon_callbacks.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * drogon_callbacks.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | namespace drogon 22 | { 23 | class HttpResponse; 24 | using HttpResponsePtr = std::shared_ptr; 25 | class HttpRequest; 26 | using HttpRequestPtr = std::shared_ptr; 27 | using AdviceCallback = std::function; 28 | using AdviceChainCallback = std::function; 29 | using FilterCallback = std::function; 30 | using FilterChainCallback = std::function; 31 | using HttpReqCallback = std::function; 32 | } // namespace drogon 33 | -------------------------------------------------------------------------------- /lib/src/DrTemplateBase.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * DrTemplateBase.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace drogon; 21 | 22 | std::shared_ptr DrTemplateBase::newTemplate( 23 | std::string templateName) 24 | { 25 | LOG_TRACE << "http view name=" << templateName; 26 | auto pos = templateName.find(".csp"); 27 | if (pos != std::string::npos) 28 | { 29 | if (pos == templateName.length() - 4) 30 | { 31 | templateName = templateName.substr(0, pos); 32 | } 33 | } 34 | return std::shared_ptr(dynamic_cast( 35 | drogon::DrClassMap::newObject(templateName))); 36 | } 37 | -------------------------------------------------------------------------------- /lib/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | link_libraries(${PROJECT_NAME}) 2 | 3 | add_executable(cache_map_test CacheMapTest.cc) 4 | add_executable(cache_map_test2 CacheMapTest2.cc) 5 | add_executable(cookies_test CookiesTest.cc) 6 | add_executable(class_name_test ClassNameTest.cc) 7 | add_executable(view_data_test HttpViewDataTest.cc) 8 | add_executable(http_full_date_test HttpFullDateTest.cc) 9 | add_executable(gzip_test GzipTest.cc) 10 | add_executable(url_codec_test UrlCodecTest.cc) 11 | add_executable(main_loop_test MainLoopTest.cc) 12 | add_executable(main_loop_test2 MainLoopTest2.cc) 13 | 14 | set(test_targets 15 | cache_map_test 16 | cache_map_test2 17 | cookies_test 18 | class_name_test 19 | view_data_test 20 | http_full_date_test 21 | gzip_test 22 | url_codec_test 23 | main_loop_test 24 | main_loop_test2) 25 | 26 | set_property(TARGET ${test_targets} 27 | PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD}) 28 | set_property(TARGET ${test_targets} PROPERTY CXX_STANDARD_REQUIRED ON) 29 | set_property(TARGET ${test_targets} PROPERTY CXX_EXTENSIONS OFF) 30 | -------------------------------------------------------------------------------- /drogon_ctl/main.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * main.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "cmd.h" 16 | #include 17 | #include 18 | #include 19 | 20 | int main(int argc, char *argv[]) 21 | { 22 | if (argc < 2) 23 | { 24 | std::vector args = {"help"}; 25 | exeCommand(args); 26 | return 0; 27 | } 28 | std::vector args; 29 | for (int i = 1; i < argc; ++i) 30 | { 31 | args.push_back(argv[i]); 32 | } 33 | if (args.size() > 0) 34 | { 35 | auto &arg = args[0]; 36 | if (arg == "-h" || arg == "--help") 37 | { 38 | arg = "help"; 39 | } 40 | else if (arg == "-v" || arg == "--version") 41 | { 42 | arg = "version"; 43 | } 44 | } 45 | 46 | exeCommand(args); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /unittest/HttpDateUnittest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace drogon; 4 | 5 | TEST(HttpDate, rfc850) 6 | { 7 | auto date = utils::getHttpDate("Fri, 05-Jun-20 09:19:38 GMT"); 8 | EXPECT_EQ(date.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC, 1591348778); 9 | } 10 | 11 | TEST(HttpDate, redditFormat) 12 | { 13 | auto date = utils::getHttpDate("Fri, 05-Jun-2020 09:19:38 GMT"); 14 | EXPECT_EQ(date.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC, 1591348778); 15 | } 16 | 17 | TEST(HttpDate, invalidFormat) 18 | { 19 | auto date = utils::getHttpDate("Fri, this format is invalid"); 20 | EXPECT_EQ(date.microSecondsSinceEpoch(), (std::numeric_limits::max)()); 21 | } 22 | 23 | TEST(HttpDate, asctimeFormat) 24 | { 25 | auto epoch = time(nullptr); 26 | auto str = asctime(gmtime(&epoch)); 27 | auto date = utils::getHttpDate(str); 28 | EXPECT_EQ(date.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC, epoch); 29 | } 30 | 31 | int main(int argc, char **argv) 32 | { 33 | testing::InitGoogleTest(&argc, argv); 34 | return RUN_ALL_TESTS(); 35 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2020 An Tao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/src/SessionManager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * SessionManager.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace drogon 26 | { 27 | class SessionManager : public trantor::NonCopyable 28 | { 29 | public: 30 | SessionManager(trantor::EventLoop *loop, size_t timeout); 31 | ~SessionManager() 32 | { 33 | sessionMapPtr_.reset(); 34 | } 35 | SessionPtr getSession(const std::string &sessionID, bool needToSet); 36 | void changeSessionId(const SessionPtr &sessionPtr); 37 | 38 | private: 39 | std::unique_ptr> sessionMapPtr_; 40 | std::mutex mapMutex_; 41 | trantor::EventLoop *loop_; 42 | size_t timeout_; 43 | }; 44 | } // namespace drogon 45 | -------------------------------------------------------------------------------- /lib/src/HttpViewData.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * HttpViewData.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include 16 | 17 | using namespace drogon; 18 | 19 | std::string HttpViewData::htmlTranslate(const char *str, size_t length) 20 | { 21 | std::string ret; 22 | ret.reserve(length + 64); 23 | auto end = str + length; 24 | while (str != end) 25 | { 26 | switch (*str) 27 | { 28 | case '"': 29 | ret.append(""", 6); 30 | break; 31 | case '&': 32 | ret.append("&", 5); 33 | break; 34 | case '<': 35 | ret.append("<", 4); 36 | break; 37 | case '>': 38 | ret.append(">", 4); 39 | break; 40 | default: 41 | ret.push_back(*str); 42 | break; 43 | } 44 | ++str; 45 | } 46 | return ret; 47 | } -------------------------------------------------------------------------------- /cmake_modules/Findpg.cmake: -------------------------------------------------------------------------------- 1 | # Find PostgreSQL 2 | # 3 | # Find the PostgreSQL includes and library 4 | # 5 | # This module defines PG_INCLUDE_DIRS, where to find header, etc. PG_LIBRARIES, 6 | # the libraries needed to use PostgreSQL. pg_FOUND, If false, do not try to use 7 | # PostgreSQL. 8 | # pg_lib - The imported target library. 9 | 10 | find_package(PostgreSQL) 11 | if(PostgreSQL_FOUND) 12 | set(PG_LIBRARIES ${PostgreSQL_LIBRARIES}) 13 | set(PG_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIRS}) 14 | message(STATUS "pg inc: " ${PostgreSQL_INCLUDE_DIRS}) 15 | add_library(pg_lib INTERFACE IMPORTED) 16 | set_target_properties(pg_lib 17 | PROPERTIES INTERFACE_INCLUDE_DIRECTORIES 18 | "${PostgreSQL_INCLUDE_DIRS}" 19 | INTERFACE_LINK_LIBRARIES 20 | "${PostgreSQL_LIBRARIES}") 21 | mark_as_advanced(PG_INCLUDE_DIRS PG_LIBRARIES) 22 | endif(PostgreSQL_FOUND) 23 | include(FindPackageHandleStandardArgs) 24 | find_package_handle_standard_args(pg 25 | DEFAULT_MSG 26 | PG_LIBRARIES 27 | PG_INCLUDE_DIRS) 28 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.0.{build} 2 | configuration: 3 | - Release 4 | - Debug 5 | 6 | environment: 7 | matrix: 8 | - GENERATOR: Visual Studio 15 2017 9 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 10 | ARCH: Win32 11 | 12 | - GENERATOR: Visual Studio 15 2017 13 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 14 | ARCH: x64 15 | 16 | init: 17 | - cmake --version 18 | install: 19 | - cd C:\Tools\vcpkg 20 | - git pull 21 | - .\bootstrap-vcpkg.bat 22 | - vcpkg install jsoncpp:x86-windows 23 | - vcpkg install jsoncpp:x64-windows 24 | - vcpkg install zlib:x86-windows 25 | - vcpkg install zlib:x64-windows 26 | - vcpkg install libpq:x86-windows 27 | - vcpkg install libpq:x64-windows 28 | - vcpkg integrate install 29 | - cd %APPVEYOR_BUILD_FOLDER% 30 | before_build: 31 | - git submodule update --init 32 | - md build 33 | - cd build 34 | - cmake --config "%CONFIGURATION%" -G "%GENERATOR%" -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake .. 35 | build_script: 36 | - cmake --build . --config "%CONFIGURATION%" 37 | build: 38 | project: build\ALL_BUILD.vcxproj 39 | verbosity: minimal 40 | cache: 41 | - c:\tools\vcpkg\installed\ -------------------------------------------------------------------------------- /drogon_ctl/create_view.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * create_view.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include "CommandHandler.h" 19 | using namespace drogon; 20 | namespace drogon_ctl 21 | { 22 | class create_view : public DrObject, public CommandHandler 23 | { 24 | public: 25 | virtual void handleCommand(std::vector ¶meters) override; 26 | virtual std::string script() override 27 | { 28 | return "create view class files"; 29 | } 30 | 31 | protected: 32 | std::string outputPath_{"."}; 33 | void createViewFiles(std::vector &cspFileNames); 34 | int createViewFile(const std::string &script_filename); 35 | void newViewHeaderFile(std::ofstream &file, const std::string &className); 36 | void newViewSourceFile(std::ofstream &file, 37 | const std::string &className, 38 | std::ifstream &infile); 39 | }; 40 | } // namespace drogon_ctl 41 | -------------------------------------------------------------------------------- /lib/inc/drogon/drogon.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * drogon.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | /** 38 | * @mainpage 39 | * ### Overview 40 | * Drogon is a C++14/17-based HTTP application framework. Drogon can be used to 41 | * easily build various types of web application server programs using C++. 42 | */ 43 | -------------------------------------------------------------------------------- /unittest/DrObjectUnittest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace drogon; 7 | class TestA : public DrObject 8 | { 9 | }; 10 | namespace test 11 | { 12 | class TestB : public DrObject 13 | { 14 | }; 15 | } // namespace test 16 | TEST(DrObjectTest, creationTest) 17 | { 18 | auto obj = DrClassMap::newObject("TestA"); 19 | EXPECT_NE(obj, nullptr); 20 | 21 | auto objPtr = DrClassMap::getSingleInstance("TestA"); 22 | EXPECT_NE(objPtr.get(), nullptr); 23 | 24 | auto objPtr2 = DrClassMap::getSingleInstance(); 25 | EXPECT_NE(objPtr2.get(), nullptr); 26 | EXPECT_EQ(objPtr, objPtr2); 27 | } 28 | 29 | TEST(DrObjectTest, namespaceTest) 30 | { 31 | auto obj = DrClassMap::newObject("test::TestB"); 32 | EXPECT_NE(obj, nullptr); 33 | 34 | auto objPtr = DrClassMap::getSingleInstance("test::TestB"); 35 | EXPECT_NE(objPtr.get(), nullptr); 36 | 37 | auto objPtr2 = DrClassMap::getSingleInstance(); 38 | EXPECT_NE(objPtr2.get(), nullptr); 39 | EXPECT_EQ(objPtr, objPtr2); 40 | } 41 | 42 | int main(int argc, char **argv) 43 | { 44 | testing::InitGoogleTest(&argc, argv); 45 | return RUN_ALL_TESTS(); 46 | } -------------------------------------------------------------------------------- /lib/src/CacheFile.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * CacheFile.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace drogon 23 | { 24 | class CacheFile : public trantor::NonCopyable 25 | { 26 | public: 27 | explicit CacheFile(const std::string &path, bool autoDelete = true); 28 | ~CacheFile(); 29 | void append(const std::string &data) 30 | { 31 | append(data.data(), data.length()); 32 | } 33 | void append(const char *data, size_t length); 34 | string_view getStringView() 35 | { 36 | if (data()) 37 | return string_view(data_, dataLength_); 38 | return string_view(); 39 | } 40 | 41 | private: 42 | char *data(); 43 | size_t length(); 44 | FILE *file_{nullptr}; 45 | bool autoDelete_{true}; 46 | const std::string path_; 47 | char *data_{nullptr}; 48 | size_t dataLength_{0}; 49 | }; 50 | } // namespace drogon 51 | -------------------------------------------------------------------------------- /lib/src/Cookie.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Cookie.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include 16 | #include 17 | using namespace drogon; 18 | std::string Cookie::cookieString() const 19 | { 20 | std::string ret = "Set-Cookie: "; 21 | ret.append(key_).append("= ").append(value_).append("; "); 22 | if (expiresDate_.microSecondsSinceEpoch() != 23 | (std::numeric_limits::max)() && 24 | expiresDate_.microSecondsSinceEpoch() >= 0) 25 | { 26 | ret.append("Expires= ") 27 | .append(utils::getHttpFullDate(expiresDate_)) 28 | .append("; "); 29 | } 30 | if (!domain_.empty()) 31 | { 32 | ret.append("Domain= ").append(domain_).append("; "); 33 | } 34 | if (!path_.empty()) 35 | { 36 | ret.append("Path= ").append(path_).append("; "); 37 | } 38 | if (secure_) 39 | { 40 | ret.append("Secure; "); 41 | } 42 | if (httpOnly_) 43 | { 44 | ret.append("HttpOnly; "); 45 | } 46 | ret.resize(ret.length() - 2); // delete last semicolon 47 | ret.append("\r\n"); 48 | return ret; 49 | } 50 | -------------------------------------------------------------------------------- /examples/simple_example/DigestAuthFilter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | using namespace drogon; 5 | 6 | typedef std::pair HttpAttribute; 7 | typedef std::vector HttpAttributeList; 8 | typedef std::map 9 | CredentialsMap; 10 | 11 | class DigestAuthFilter : public drogon::HttpFilter 12 | { 13 | const std::map credentials; 14 | const std::string realm; 15 | const std::string opaque; 16 | 17 | static bool isEndOfAttributeName(size_t pos, size_t len, const char *data); 18 | static void httpParseAttributes(const char *data, 19 | size_t len, 20 | HttpAttributeList &attributes); 21 | 22 | static bool httpHasAttribute(const HttpAttributeList &attributes, 23 | const std::string &name, 24 | std::string *value); 25 | 26 | public: 27 | explicit DigestAuthFilter(const CredentialsMap &credentials, 28 | const std::string &realm, 29 | const std::string &opaque); 30 | virtual void doFilter(const HttpRequestPtr &req, 31 | FilterCallback &&cb, 32 | FilterChainCallback &&ccb) override; 33 | }; -------------------------------------------------------------------------------- /examples/simple_reverse_proxy/plugins/SimpleReverseProxy.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @file SimpleReverseProxy.h 4 | * 5 | */ 6 | 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | namespace my_plugin 15 | { 16 | class SimpleReverseProxy : public drogon::Plugin 17 | { 18 | public: 19 | SimpleReverseProxy() 20 | { 21 | } 22 | /// This method must be called by drogon to initialize and start the plugin. 23 | /// It must be implemented by the user. 24 | virtual void initAndStart(const Json::Value &config) override; 25 | 26 | /// This method must be called by drogon to shutdown the plugin. 27 | /// It must be implemented by the user. 28 | virtual void shutdown() override; 29 | 30 | private: 31 | // Create 'connectionFactor_' HTTP clients for every backend in every IO 32 | // event loop. 33 | drogon::IOThreadStorage> clients_; 34 | drogon::IOThreadStorage clientIndex_{0}; 35 | std::vector backendAddrs_; 36 | bool sameClientToSameBackend_{false}; 37 | size_t pipeliningDepth_{0}; 38 | void preRouting(const drogon::HttpRequestPtr &, 39 | drogon::AdviceCallback &&, 40 | drogon::AdviceChainCallback &&); 41 | size_t connectionFactor_{1}; 42 | }; 43 | } // namespace my_plugin 44 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Drogon Examples 2 | 3 | The following examples can help you understand how to use Drogon: 4 | 5 | 1. [benchmark](https://github.com/an-tao/drogon/tree/master/examples/benchmark) - Basic benchmark example. see [wiki benchmarks](https://github.com/an-tao/drogon/wiki/13-Benchmarks) 6 | 2. [client_example](https://github.com/an-tao/drogon/tree/master/examples/client_example/main.cc) - A client example. 7 | 3. [simple_example](https://github.com/an-tao/drogon/tree/master/examples/simple_example) - A simple example showing how to create a web application using Drogon. 8 | 4. [simple_example_test](https://github.com/an-tao/drogon/tree/master/examples/simple_example_test) - Some tests for the `simple_example`. 9 | 5. [simple_reverse_proxy](https://github.com/an-tao/drogon/tree/master/examples/simple_reverse_proxy) - A Example showing how to use drogon as a http reverse proxy with a simple round robin. 10 | 11 | ### [TechEmpower Framework Benchmarks](https://github.com/TechEmpower/FrameworkBenchmarks) test suite 12 | 13 | I created a benchmark suite for the `tfb`, see [here](https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/C%2B%2B/drogon) for details. 14 | 15 | ### Another test suite 16 | 17 | I also created a test suite for another web frameworks benchmark repository, see [here](https://github.com/the-benchmarker/web-frameworks/tree/master/cpp/drogon), in this project, drogon is used as a sub-module (locally include in the project). -------------------------------------------------------------------------------- /lib/src/AOPAdvice.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * AOPAdvice.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | #include "impl_forwards.h" 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace drogon 24 | { 25 | void doAdvicesChain( 26 | const std::vector> &advices, 29 | size_t index, 30 | const HttpRequestImplPtr &req, 31 | const std::shared_ptr> 32 | &callbackPtr, 33 | std::function &&missCallback); 34 | void doAdvicesChain( 35 | const std::deque> &advices, 38 | size_t index, 39 | const HttpRequestImplPtr &req, 40 | const std::shared_ptr> 41 | &callbackPtr, 42 | std::function &&missCallback); 43 | } // namespace drogon 44 | -------------------------------------------------------------------------------- /lib/src/SharedLibManager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * SharedLibManager.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace drogon 24 | { 25 | class SharedLibManager : public trantor::NonCopyable 26 | { 27 | public: 28 | SharedLibManager(const std::vector &libPaths, 29 | const std::string &outputPath); 30 | ~SharedLibManager(); 31 | 32 | private: 33 | void managerLibs(); 34 | std::vector libPaths_; 35 | std::string outputPath_; 36 | struct DLStat 37 | { 38 | void *handle{nullptr}; 39 | struct timespec mTime = {0}; 40 | }; 41 | std::unordered_map dlMap_; 42 | void *compileAndLoadLib(const std::string &sourceFile, void *oldHld); 43 | void *loadLib(const std::string &soFile, void *oldHld); 44 | bool shouldCompileLib(const std::string &soFile, 45 | const struct stat &sourceStat); 46 | trantor::TimerId timeId_; 47 | trantor::EventLoopThread workingThread_; 48 | }; 49 | } // namespace drogon 50 | -------------------------------------------------------------------------------- /examples/simple_example/TimeFilter.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Created by antao on 2018/5/22. 3 | // 4 | 5 | #include "TimeFilter.h" 6 | #define VDate "visitDate" 7 | void TimeFilter::doFilter(const HttpRequestPtr &req, 8 | FilterCallback &&cb, 9 | FilterChainCallback &&ccb) 10 | { 11 | trantor::Date now = trantor::Date::date(); 12 | if (!req->session()) 13 | { 14 | // no session support by framework,pls enable session 15 | auto resp = HttpResponse::newNotFoundResponse(); 16 | cb(resp); 17 | return; 18 | } 19 | if (req->session()->find(VDate)) 20 | { 21 | auto lastDate = req->session()->get(VDate); 22 | LOG_TRACE << "last:" << lastDate.toFormattedString(false); 23 | req->session()->insert(VDate, now); 24 | LOG_TRACE << "update visitDate"; 25 | if (now > lastDate.after(10)) 26 | { 27 | // 10 sec later can visit again; 28 | ccb(); 29 | return; 30 | } 31 | else 32 | { 33 | Json::Value json; 34 | json["result"] = "error"; 35 | json["message"] = "Access interval should be at least 10 seconds"; 36 | auto res = HttpResponse::newHttpJsonResponse(json); 37 | cb(res); 38 | return; 39 | } 40 | } 41 | LOG_TRACE << "first visit,insert visitDate"; 42 | req->session()->insert(VDate, now); 43 | ccb(); 44 | } -------------------------------------------------------------------------------- /unittest/HttpHeaderUnittest.cpp: -------------------------------------------------------------------------------- 1 | #include "../lib/src/HttpRequestImpl.h" 2 | #include "../lib/src/HttpResponseImpl.h" 3 | #include 4 | using namespace drogon; 5 | 6 | TEST(HttpHeader, Request) 7 | { 8 | auto req = std::dynamic_pointer_cast( 9 | HttpRequest::newHttpRequest()); 10 | req->addHeader("Abc", "abc"); 11 | EXPECT_STREQ("abc", req->getHeader("Abc").c_str()); 12 | EXPECT_STREQ("abc", req->getHeader("abc").c_str()); 13 | req->removeHeader("Abc"); 14 | EXPECT_STREQ("", req->getHeader("abc").c_str()); 15 | } 16 | TEST(HttpHeader, Response) 17 | { 18 | auto resp = std::dynamic_pointer_cast( 19 | HttpResponse::newHttpResponse()); 20 | resp->addHeader("Abc", "abc"); 21 | EXPECT_STREQ("abc", resp->getHeader("Abc").c_str()); 22 | EXPECT_STREQ("abc", resp->getHeader("abc").c_str()); 23 | resp->makeHeaderString(); 24 | auto buffer = resp->renderToBuffer(); 25 | auto str = std::string{buffer->peek(), buffer->readableBytes()}; 26 | EXPECT_TRUE(str.find("abc") != std::string::npos); 27 | resp->removeHeader("Abc"); 28 | buffer = resp->renderToBuffer(); 29 | str = std::string{buffer->peek(), buffer->readableBytes()}; 30 | EXPECT_TRUE(str.find("abc") == std::string::npos); 31 | EXPECT_STREQ("", resp->getHeader("abc").c_str()); 32 | } 33 | 34 | int main(int argc, char **argv) 35 | { 36 | testing::InitGoogleTest(&argc, argv); 37 | return RUN_ALL_TESTS(); 38 | } -------------------------------------------------------------------------------- /lib/inc/drogon/utils/HttpConstraint.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * HttpConstraint.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | namespace drogon 20 | { 21 | namespace internal 22 | { 23 | enum class ConstraintType 24 | { 25 | None, 26 | HttpMethod, 27 | HttpFilter 28 | }; 29 | 30 | class HttpConstraint 31 | { 32 | public: 33 | HttpConstraint(HttpMethod method) 34 | : type_(ConstraintType::HttpMethod), method_(method) 35 | { 36 | } 37 | HttpConstraint(const std::string &filterName) 38 | : type_(ConstraintType::HttpFilter), filterName_(filterName) 39 | { 40 | } 41 | HttpConstraint(const char *filterName) 42 | : type_(ConstraintType::HttpFilter), filterName_(filterName) 43 | { 44 | } 45 | ConstraintType type() const 46 | { 47 | return type_; 48 | } 49 | HttpMethod getHttpMethod() const 50 | { 51 | return method_; 52 | } 53 | const std::string &getFilterName() const 54 | { 55 | return filterName_; 56 | } 57 | 58 | private: 59 | ConstraintType type_{ConstraintType::None}; 60 | HttpMethod method_; 61 | std::string filterName_; 62 | }; 63 | } // namespace internal 64 | } // namespace drogon 65 | -------------------------------------------------------------------------------- /unittest/OStringStreamUnitttest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | TEST(OStringStreamTest, interger) 7 | { 8 | drogon::OStringStream ss; 9 | ss << 12; 10 | ss << 345L; 11 | EXPECT_EQ(ss.str(), "12345"); 12 | } 13 | 14 | TEST(OStringStreamTest, float_number) 15 | { 16 | drogon::OStringStream ss; 17 | ss << 3.14f; 18 | ss << 3.1416; 19 | EXPECT_EQ(ss.str(), "3.143.1416"); 20 | } 21 | 22 | TEST(OStringStreamTest, literal_string) 23 | { 24 | drogon::OStringStream ss; 25 | ss << "hello"; 26 | ss << " world"; 27 | EXPECT_EQ(ss.str(), "hello world"); 28 | } 29 | 30 | TEST(OStringStreamTest, string_view) 31 | { 32 | drogon::OStringStream ss; 33 | ss << drogon::string_view("hello"); 34 | ss << drogon::string_view(" world"); 35 | EXPECT_EQ(ss.str(), "hello world"); 36 | } 37 | 38 | TEST(OStringStreamTest, std_string) 39 | { 40 | drogon::OStringStream ss; 41 | ss << std::string("hello"); 42 | ss << std::string(" world"); 43 | EXPECT_EQ(ss.str(), "hello world"); 44 | } 45 | 46 | TEST(OStringStreamTest, mix) 47 | { 48 | drogon::OStringStream ss; 49 | ss << std::string("hello"); 50 | ss << drogon::string_view(" world"); 51 | ss << "!"; 52 | ss << 123; 53 | ss << 3.14f; 54 | 55 | EXPECT_EQ(ss.str(), "hello world!1233.14"); 56 | } 57 | 58 | int main(int argc, char **argv) 59 | { 60 | testing::InitGoogleTest(&argc, argv); 61 | return RUN_ALL_TESTS(); 62 | } 63 | -------------------------------------------------------------------------------- /examples/client_example/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace drogon; 6 | 7 | int main() 8 | { 9 | trantor::Logger::setLogLevel(trantor::Logger::kTrace); 10 | { 11 | int count = 0; 12 | auto client = HttpClient::newHttpClient("http://www.baidu.com"); 13 | auto req = HttpRequest::newHttpRequest(); 14 | req->setMethod(drogon::Get); 15 | req->setPath("/s"); 16 | req->setParameter("wd", "wx"); 17 | req->setParameter("oq", "wx"); 18 | 19 | for (int i = 0; i < 10; ++i) 20 | { 21 | client->sendRequest( 22 | req, 23 | [&count](ReqResult result, const HttpResponsePtr &response) { 24 | std::cout << "receive response!" << std::endl; 25 | // auto headers=response. 26 | ++count; 27 | std::cout << response->getBody() << std::endl; 28 | auto cookies = response->cookies(); 29 | for (auto const &cookie : cookies) 30 | { 31 | std::cout << cookie.first << "=" 32 | << cookie.second.value() 33 | << ":domain=" << cookie.second.domain() 34 | << std::endl; 35 | } 36 | std::cout << "count=" << count << std::endl; 37 | }); 38 | } 39 | } 40 | 41 | app().run(); 42 | } 43 | -------------------------------------------------------------------------------- /drogon_ctl/cmd.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * cmd.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "cmd.h" 16 | #include "CommandHandler.h" 17 | #include 18 | #include 19 | using namespace drogon; 20 | 21 | void exeCommand(std::vector ¶meters) 22 | { 23 | if (parameters.empty()) 24 | { 25 | std::cout << "incomplete command!use help command to get usage!" 26 | << std::endl; 27 | return; 28 | } 29 | std::string command = parameters[0]; 30 | 31 | std::string handlerName = std::string("drogon_ctl::").append(command); 32 | 33 | parameters.erase(parameters.begin()); 34 | 35 | // new command handler to do cmd 36 | auto obj = std::shared_ptr( 37 | drogon::DrClassMap::newObject(handlerName)); 38 | if (obj) 39 | { 40 | auto ctl = std::dynamic_pointer_cast(obj); 41 | if (ctl) 42 | { 43 | ctl->handleCommand(parameters); 44 | } 45 | else 46 | { 47 | std::cout << "command not found!use help command to get usage!" 48 | << std::endl; 49 | } 50 | } 51 | else 52 | { 53 | std::cout << "command error!use help command to get usage!" 54 | << std::endl; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /unittest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(drogon_msgbuffer_unittest MsgBufferUnittest.cpp) 2 | add_executable(drobject_unittest DrObjectUnittest.cpp) 3 | add_executable(gzip_unittest GzipUnittest.cpp) 4 | add_executable(md5_unittest MD5Unittest.cpp) 5 | add_executable(sha1_unittest SHA1Unittest.cpp ../lib/src/ssl_funcs/Sha1.cc) 6 | add_executable(ostringstream_unittest OStringStreamUnitttest.cpp) 7 | add_executable(base64_unittest Base64Unittest.cpp) 8 | add_executable(pubsubservice_unittest PubSubServiceUnittest.cpp) 9 | add_executable(httpdate_unittest HttpDateUnittest.cpp) 10 | add_executable(httpheader_unittest HttpHeaderUnittest.cpp) 11 | if(Brotli_FOUND) 12 | add_executable(brotli_unittest BrotliUnittest.cpp) 13 | endif() 14 | 15 | set(UNITTEST_TARGETS 16 | drogon_msgbuffer_unittest 17 | drobject_unittest 18 | gzip_unittest 19 | md5_unittest 20 | sha1_unittest 21 | ostringstream_unittest 22 | base64_unittest 23 | pubsubservice_unittest 24 | httpdate_unittest 25 | httpheader_unittest) 26 | if(Brotli_FOUND) 27 | set(UNITTEST_TARGETS ${UNITTEST_TARGETS} brotli_unittest) 28 | endif() 29 | 30 | set_property(TARGET ${UNITTEST_TARGETS} 31 | PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD}) 32 | set_property(TARGET ${UNITTEST_TARGETS} PROPERTY CXX_STANDARD_REQUIRED ON) 33 | set_property(TARGET ${UNITTEST_TARGETS} PROPERTY CXX_EXTENSIONS OFF) 34 | 35 | include(GoogleTest) 36 | foreach(T ${UNITTEST_TARGETS}) 37 | target_link_libraries(${T} PRIVATE drogon GTest::GTest) 38 | gtest_discover_tests(${T}) 39 | endforeach() 40 | -------------------------------------------------------------------------------- /orm_lib/src/postgresql_impl/PostgreSQLResultImpl.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * PostgreSQLResultImpl.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include "../ResultImpl.h" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | namespace drogon 24 | { 25 | namespace orm 26 | { 27 | class PostgreSQLResultImpl : public ResultImpl 28 | { 29 | public: 30 | PostgreSQLResultImpl(const std::shared_ptr &r) noexcept 31 | : result_(r) 32 | { 33 | } 34 | virtual SizeType size() const noexcept override; 35 | virtual RowSizeType columns() const noexcept override; 36 | virtual const char *columnName(RowSizeType number) const override; 37 | virtual SizeType affectedRows() const noexcept override; 38 | virtual RowSizeType columnNumber(const char colName[]) const override; 39 | virtual const char *getValue(SizeType row, 40 | RowSizeType column) const override; 41 | virtual bool isNull(SizeType row, RowSizeType column) const override; 42 | virtual FieldSizeType getLength(SizeType row, 43 | RowSizeType column) const override; 44 | virtual int oid(RowSizeType column) const override; 45 | 46 | private: 47 | std::shared_ptr result_; 48 | }; 49 | 50 | } // namespace orm 51 | } // namespace drogon 52 | -------------------------------------------------------------------------------- /cmake/templates/DrogonConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # - Config file for the Drogon package 2 | # It defines the following variables 3 | # DROGON_INCLUDE_DIRS - include directories for Drogon 4 | # DROGON_LIBRARIES - libraries to link against 5 | # DROGON_EXECUTABLE - the drogon_ctl executable 6 | # Drogon_FOUND 7 | # This module defines the following IMPORTED target: 8 | # Drogon::Drogon 9 | 10 | @PACKAGE_INIT@ 11 | 12 | include(CMakeFindDependencyMacro) 13 | list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) 14 | 15 | find_dependency(Jsoncpp REQUIRED) 16 | find_dependency(Trantor REQUIRED) 17 | if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" AND NOT WIN32) 18 | find_dependency(UUID REQUIRED) 19 | endif(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" AND NOT WIN32) 20 | find_dependency(ZLIB REQUIRED) 21 | if(@pg_FOUND@) 22 | find_dependency(pg) 23 | endif() 24 | if(@SQLite3_FOUND@) 25 | find_dependency(SQLite3) 26 | endif() 27 | if(@MySQL_FOUND@) 28 | find_dependency(MySQL) 29 | endif() 30 | if(@Boost_FOUND@) 31 | find_dependency(Boost) 32 | endif() 33 | if(@Brotli_FOUND@) 34 | find_dependency(Brotli) 35 | endif() 36 | if(@COZ-PROFILER_FOUND@) 37 | find_dependency(coz-profiler) 38 | endif() 39 | 40 | # Our library dependencies (contains definitions for IMPORTED targets) 41 | 42 | get_filename_component(DROGON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 43 | if(NOT TARGET Drogon::Drogon) 44 | include("${DROGON_CMAKE_DIR}/DrogonTargets.cmake") 45 | endif() 46 | 47 | get_target_property(DROGON_INCLUDE_DIRS Drogon::Drogon INTERFACE_INCLUDE_DIRECTORIES) 48 | set(DROGON_LIBRARIES Drogon::Drogon) 49 | set(DROGON_EXECUTABLE drogon_ctl) 50 | -------------------------------------------------------------------------------- /orm_lib/src/ResultImpl.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * ResultImpl.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | namespace drogon 20 | { 21 | namespace orm 22 | { 23 | class ResultImpl : public trantor::NonCopyable 24 | { 25 | public: 26 | ResultImpl() = default; 27 | using SizeType = Result::SizeType; 28 | using RowSizeType = Result::RowSizeType; 29 | using FieldSizeType = Result::FieldSizeType; 30 | virtual SizeType size() const noexcept = 0; 31 | virtual RowSizeType columns() const noexcept = 0; 32 | virtual const char *columnName(RowSizeType Number) const = 0; 33 | virtual SizeType affectedRows() const noexcept = 0; 34 | virtual RowSizeType columnNumber(const char colName[]) const = 0; 35 | virtual const char *getValue(SizeType row, RowSizeType column) const = 0; 36 | virtual bool isNull(SizeType row, RowSizeType column) const = 0; 37 | virtual FieldSizeType getLength(SizeType row, RowSizeType column) const = 0; 38 | 39 | virtual unsigned long long insertId() const noexcept 40 | { 41 | return 0; 42 | } 43 | virtual int oid(RowSizeType column) const 44 | { 45 | (void)column; 46 | return 0; 47 | } 48 | virtual ~ResultImpl() 49 | { 50 | } 51 | }; 52 | 53 | } // namespace orm 54 | } // namespace drogon 55 | -------------------------------------------------------------------------------- /lib/src/HttpUtils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * HttpUtils.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace drogon 23 | { 24 | ContentType parseContentType(const string_view &contentType); 25 | const string_view &webContentTypeToString(ContentType contenttype); 26 | const string_view &statusCodeToString(int code); 27 | ContentType getContentType(const std::string &fileName); 28 | template 29 | inline constexpr const char *contentLengthFormatString() 30 | { 31 | return "Content-Length: %d\r\n"; 32 | } 33 | template <> 34 | inline constexpr const char *contentLengthFormatString() 35 | { 36 | return "Content-Length: %u\r\n"; 37 | } 38 | template <> 39 | inline constexpr const char *contentLengthFormatString() 40 | { 41 | return "Content-Length: %ld\r\n"; 42 | } 43 | template <> 44 | inline constexpr const char *contentLengthFormatString() 45 | { 46 | return "Content-Length: %lu\r\n"; 47 | } 48 | template <> 49 | inline constexpr const char *contentLengthFormatString() 50 | { 51 | return "Content-Length: %lld\r\n"; 52 | } 53 | template <> 54 | inline constexpr const char *contentLengthFormatString() 55 | { 56 | return "Content-Length: %llu\r\n"; 57 | } 58 | } // namespace drogon 59 | -------------------------------------------------------------------------------- /examples/simple_example/PipeliningTest.cc: -------------------------------------------------------------------------------- 1 | #include "PipeliningTest.h" 2 | #include 3 | #include 4 | 5 | void PipeliningTest::asyncHandleHttpRequest( 6 | const HttpRequestPtr &req, 7 | std::function &&callback) 8 | { 9 | static std::atomic counter{0}; 10 | int c = counter.fetch_add(1); 11 | if (c % 3 == 1) 12 | { 13 | auto resp = HttpResponse::newHttpResponse(); 14 | auto str = utils::formattedString("

the %dth response

", c); 15 | resp->addHeader("counter", utils::formattedString("%d", c)); 16 | resp->setBody(std::move(str)); 17 | callback(resp); 18 | return; 19 | } 20 | double delay = ((double)(10 - (c % 10))) / 10.0; 21 | if (c % 3 == 2) 22 | { 23 | // call the callback in another thread. 24 | drogon::app().getLoop()->runAfter(delay, [c, callback]() { 25 | auto resp = HttpResponse::newHttpResponse(); 26 | auto str = utils::formattedString("

the %dth response

", c); 27 | resp->addHeader("counter", utils::formattedString("%d", c)); 28 | resp->setBody(std::move(str)); 29 | callback(resp); 30 | }); 31 | return; 32 | } 33 | trantor::EventLoop::getEventLoopOfCurrentThread()->runAfter( 34 | delay, [c, callback]() { 35 | auto resp = HttpResponse::newHttpResponse(); 36 | auto str = utils::formattedString("

the %dth response

", c); 37 | resp->addHeader("counter", utils::formattedString("%d", c)); 38 | resp->setBody(std::move(str)); 39 | callback(resp); 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /lib/inc/drogon/DrTemplateBase.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * DrTemplateBase.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace drogon 23 | { 24 | using DrTemplateData = HttpViewData; 25 | 26 | /// The templating engine class 27 | /** 28 | * This class can generate a text string from the template file and template 29 | * data. 30 | * For more details on the template file, see the wiki site (the 'View' section) 31 | */ 32 | class DrTemplateBase : public virtual DrObjectBase 33 | { 34 | public: 35 | /// Create an object of the implementation class 36 | /** 37 | * @param templateName represents the name of the template file. A template 38 | * file is a description file with a special format. Its extension is 39 | * usually .csp. The user should preprocess the template file with the 40 | * drogon_ctl tool to create c++ source files. 41 | */ 42 | static std::shared_ptr newTemplate( 43 | std::string templateName); 44 | 45 | /// Generate the text string 46 | /** 47 | * @param data represents data rendered in the string in a format 48 | * according to the template file. 49 | */ 50 | virtual std::string genText( 51 | const DrTemplateData &data = DrTemplateData()) = 0; 52 | 53 | virtual ~DrTemplateBase(){}; 54 | DrTemplateBase(){}; 55 | }; 56 | 57 | } // namespace drogon 58 | -------------------------------------------------------------------------------- /drogon_ctl/templates/restful_controller_cc.csp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * [[fileName]].cc 4 | * This file is generated by drogon_ctl 5 | * 6 | */ 7 | 8 | #include "[[fileName]].h" 9 | #include 10 | 11 | <%c++ 12 | auto namespaceVector=@@.get>("namespaceVector"); 13 | std::string namespaceStr; 14 | for(auto &name:namespaceVector) 15 | { 16 | namespaceStr.append(name); 17 | namespaceStr.append("::"); 18 | } 19 | if(!namespaceStr.empty()) 20 | { 21 | namespaceStr.resize(namespaceStr.length()-2); 22 | $$<<"using namespace "<("className").length(), ' '); 25 | %> 26 | 27 | void [[className]]::getOne(const HttpRequestPtr &req, 28 | {%indentStr%} std::function &&callback, 29 | {%indentStr%} std::string &&id) 30 | { 31 | } 32 | 33 | void [[className]]::get(const HttpRequestPtr &req, 34 | {%indentStr%} std::function &&callback) 35 | { 36 | } 37 | void [[className]]::create(const HttpRequestPtr &req, 38 | {%indentStr%} std::function &&callback) 39 | { 40 | } 41 | void [[className]]::updateOne(const HttpRequestPtr &req, 42 | {%indentStr%} std::function &&callback, 43 | {%indentStr%} std::string &&id) 44 | { 45 | } 46 | 47 | /* 48 | void [[className]]::update(const HttpRequestPtr &req, 49 | {%indentStr%} std::function &&callback) 50 | { 51 | 52 | }*/ 53 | 54 | void [[className]]::deleteOne(const HttpRequestPtr &req, 55 | {%indentStr%} std::function &&callback, 56 | {%indentStr%} std::string &&id) 57 | { 58 | } 59 | -------------------------------------------------------------------------------- /orm_lib/src/sqlite3_impl/Sqlite3ResultImpl.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Sqlite3ResultImpl.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include "../ResultImpl.h" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace drogon 26 | { 27 | namespace orm 28 | { 29 | class Sqlite3ResultImpl : public ResultImpl 30 | { 31 | public: 32 | Sqlite3ResultImpl() = default; 33 | virtual SizeType size() const noexcept override; 34 | virtual RowSizeType columns() const noexcept override; 35 | virtual const char *columnName(RowSizeType number) const override; 36 | virtual SizeType affectedRows() const noexcept override; 37 | virtual RowSizeType columnNumber(const char colName[]) const override; 38 | virtual const char *getValue(SizeType row, 39 | RowSizeType column) const override; 40 | virtual bool isNull(SizeType row, RowSizeType column) const override; 41 | virtual FieldSizeType getLength(SizeType row, 42 | RowSizeType column) const override; 43 | virtual unsigned long long insertId() const noexcept override; 44 | 45 | private: 46 | friend class Sqlite3Connection; 47 | std::vector>> result_; 48 | std::string query_; 49 | std::vector columnNames_; 50 | std::unordered_map columnNamesMap_; 51 | size_t affectedRows_{0}; 52 | size_t insertId_{0}; 53 | }; 54 | } // namespace orm 55 | } // namespace drogon -------------------------------------------------------------------------------- /lib/src/DbClientManagerSkipped.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * DbClientManagerSkipped.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "DbClientManager.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | using namespace drogon::orm; 22 | using namespace drogon; 23 | 24 | void DbClientManager::createDbClients( 25 | const std::vector &ioloops) 26 | { 27 | return; 28 | } 29 | 30 | void DbClientManager::createDbClient(const std::string &dbType, 31 | const std::string &host, 32 | const unsigned short port, 33 | const std::string &databaseName, 34 | const std::string &userName, 35 | const std::string &password, 36 | const size_t connectionNum, 37 | const std::string &filename, 38 | const std::string &name, 39 | const bool isFast, 40 | const std::string &characterSet) 41 | { 42 | LOG_FATAL << "No database is supported by drogon, please install the " 43 | "database development library first."; 44 | abort(); 45 | } 46 | 47 | bool DbClientManager::areAllDbClientsAvailable() const noexcept 48 | { 49 | LOG_FATAL << "No database is supported by drogon, please install the " 50 | "database development library first."; 51 | abort(); 52 | } -------------------------------------------------------------------------------- /lib/src/HttpResponseParser.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * HttpResponseParser.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include "impl_forwards.h" 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | namespace drogon 25 | { 26 | class HttpResponseParser : public trantor::NonCopyable 27 | { 28 | public: 29 | enum class HttpResponseParseStatus 30 | { 31 | kExpectResponseLine, 32 | kExpectHeaders, 33 | kExpectBody, 34 | kExpectChunkLen, 35 | kExpectChunkBody, 36 | kExpectLastEmptyChunk, 37 | kExpectClose, 38 | kGotAll, 39 | }; 40 | 41 | HttpResponseParser(); 42 | 43 | // default copy-ctor, dtor and assignment are fine 44 | 45 | // return false if any error 46 | bool parseResponse(trantor::MsgBuffer *buf); 47 | 48 | bool gotAll() const 49 | { 50 | return status_ == HttpResponseParseStatus::kGotAll; 51 | } 52 | 53 | void setForHeadMethod() 54 | { 55 | parseResponseForHeadMethod_ = true; 56 | } 57 | 58 | void reset(); 59 | 60 | const HttpResponseImplPtr &responseImpl() const 61 | { 62 | return responsePtr_; 63 | } 64 | 65 | private: 66 | bool processResponseLine(const char *begin, const char *end); 67 | 68 | HttpResponseParseStatus status_; 69 | HttpResponseImplPtr responsePtr_; 70 | bool parseResponseForHeadMethod_{false}; 71 | size_t leftBodyLength_{0}; 72 | size_t currentChunkLength_{0}; 73 | }; 74 | 75 | } // namespace drogon 76 | -------------------------------------------------------------------------------- /unittest/Base64Unittest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | TEST(Base64, base64) 6 | { 7 | std::string in{"drogon framework"}; 8 | auto out = drogon::utils::base64Encode((const unsigned char *)in.data(), 9 | in.length()); 10 | auto out2 = drogon::utils::base64Decode(out); 11 | EXPECT_EQ(out, "ZHJvZ29uIGZyYW1ld29yaw=="); 12 | EXPECT_EQ(out2, in); 13 | } 14 | 15 | TEST(Base64, base64_long_string) 16 | { 17 | std::string in; 18 | for (int i = 0; i < 100000; ++i) 19 | { 20 | in.append(1, char(i)); 21 | } 22 | auto out = drogon::utils::base64Encode((const unsigned char *)in.data(), 23 | in.length()); 24 | auto out2 = drogon::utils::base64Decode(out); 25 | EXPECT_EQ(out2, in); 26 | } 27 | 28 | TEST(Base64, base64_url) 29 | { 30 | std::string in{"drogon framework"}; 31 | auto out = drogon::utils::base64Encode((const unsigned char *)in.data(), 32 | in.length(), 33 | true); 34 | auto out2 = drogon::utils::base64Decode(out); 35 | EXPECT_EQ(out, "ZHJvZ29uIGZyYW1ld29yaw=="); 36 | EXPECT_EQ(out2, in); 37 | } 38 | 39 | TEST(Base64, base64_long_string_url) 40 | { 41 | std::string in; 42 | for (int i = 0; i < 100000; ++i) 43 | { 44 | in.append(1, char(i)); 45 | } 46 | auto out = drogon::utils::base64Encode((const unsigned char *)in.data(), 47 | in.length(), 48 | true); 49 | auto out2 = drogon::utils::base64Decode(out); 50 | EXPECT_EQ(out2, in); 51 | } 52 | 53 | int main(int argc, char **argv) 54 | { 55 | testing::InitGoogleTest(&argc, argv); 56 | return RUN_ALL_TESTS(); 57 | } 58 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | matrix: 2 | include: 3 | - os: linux 4 | dist: xenial 5 | - os: osx 6 | osx_image: xcode11.2 7 | 8 | sudo: required 9 | 10 | language: cpp 11 | 12 | addons: 13 | apt: 14 | sources: 15 | - xenial 16 | - sourceline: 'deb http://archive.ubuntu.com/ubuntu xenial main' 17 | - sourceline: 'ppa:mhier/libboost-latest' 18 | packages: 19 | - gcc 20 | - g++ 21 | - libjsoncpp-dev 22 | - uuid-dev 23 | - zlib1g-dev 24 | - postgresql-server-dev-10 25 | - openssl 26 | - libssl-dev 27 | - libsqlite3-dev 28 | - mariadb-client 29 | - mariadb-server 30 | - build-essential 31 | - cmake 32 | - boost1.67 33 | - libbrotli-dev 34 | homebrew: 35 | packages: 36 | - jsoncpp 37 | - ossp-uuid 38 | - openssl 39 | - cmake 40 | - libtool 41 | - lz4 42 | - mariadb 43 | - sqlite3 44 | update: true 45 | mariadb: '10.0' 46 | 47 | before_install: 48 | - wget https://github.com/google/googletest/archive/release-1.10.0.tar.gz 49 | - tar xf release-1.10.0.tar.gz 50 | - cd googletest-release-1.10.0 51 | - cmake . 52 | - make 53 | - sudo make install 54 | - cd - 55 | 56 | before_script: 57 | - if [ "$TRAVIS_OS_NAME" = "osx" ]; then 58 | brew tap homebrew/services; 59 | brew services restart postgresql; 60 | brew services start mariadb; 61 | sleep 2; 62 | mariadb -e "CREATE USER 'root'@'localhost' IDENTIFIED BY ''"; 63 | mariadb -e "SET PASSWORD FOR 'root'@'localhost' = PASSWORD('')"; 64 | mariadb -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost'"; 65 | mariadb -e "FLUSH PRIVILEGES"; 66 | sleep 2; 67 | brew services restart mariadb; 68 | psql -c 'create user postgres superuser;' postgres; 69 | fi 70 | 71 | services: 72 | - postgresql 73 | - mysql 74 | 75 | script: 76 | - ./build.sh -t 77 | - ./test.sh -t 78 | -------------------------------------------------------------------------------- /examples/simple_example_test/MultipleWsTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using namespace drogon; 9 | using namespace std::chrono_literals; 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | std::array wsClients; 14 | for (size_t i = 0; i < wsClients.size(); ++i) 15 | { 16 | auto &wsPtr = wsClients[i]; 17 | wsPtr = WebSocketClient::newWebSocketClient("127.0.0.1", 8848); 18 | auto req = HttpRequest::newHttpRequest(); 19 | 20 | req->setPath("/chat"); 21 | wsPtr->setMessageHandler([](const std::string &message, 22 | const WebSocketClientPtr &wsPtr, 23 | const WebSocketMessageType &type) { 24 | std::cout << "new message:" << message << std::endl; 25 | if (type == WebSocketMessageType::Pong) 26 | { 27 | std::cout << "recv a pong" << std::endl; 28 | } 29 | }); 30 | wsPtr->setConnectionClosedHandler([](const WebSocketClientPtr &wsPtr) { 31 | std::cout << "ws closed!" << std::endl; 32 | }); 33 | wsPtr->connectToServer( 34 | req, 35 | [](ReqResult r, 36 | const HttpResponsePtr &resp, 37 | const WebSocketClientPtr &wsPtr) { 38 | if (r == ReqResult::Ok) 39 | { 40 | std::cout << "ws connected!" << std::endl; 41 | wsPtr->getConnection()->setPingMessage("", 2s); 42 | wsPtr->getConnection()->send("hello!"); 43 | } 44 | else 45 | { 46 | std::cout << "ws failed!" << std::endl; 47 | } 48 | }); 49 | } 50 | app().run(); 51 | } -------------------------------------------------------------------------------- /lib/tests/CacheMapTest2.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() 11 | { 12 | trantor::Logger::setLogLevel(trantor::Logger::kTrace); 13 | trantor::EventLoopThread loopThread; 14 | loopThread.run(); 15 | 16 | auto loop = loopThread.getLoop(); 17 | std::shared_ptr> main_cachePtr; 18 | auto now = trantor::Date::date(); 19 | loop->runAt(now.after(1).roundSecond(), [=, &main_cachePtr]() { 20 | std::shared_ptr> cachePtr = 21 | std::make_shared>(loop, 22 | 0.1, 23 | 3, 24 | 50); 25 | main_cachePtr = cachePtr; 26 | LOG_DEBUG << "insert :usecount=" << main_cachePtr.use_count(); 27 | cachePtr->insert("1", "1", 3, [=]() { 28 | LOG_DEBUG << "timeout!erase 1!"; 29 | }); 30 | cachePtr->insert("2", "2", 10, []() { LOG_DEBUG << "2 timeout"; }); 31 | }); 32 | trantor::EventLoop mainLoop; 33 | mainLoop.runAt(now.after(3).roundSecond().after(0.0013), [&]() { 34 | (*main_cachePtr)["new"] = "new"; 35 | if (main_cachePtr->find("1")) 36 | { 37 | LOG_DEBUG << "find item 1:" << (*main_cachePtr)["1"]; 38 | (*main_cachePtr)["1"] = "22"; 39 | LOG_DEBUG << (*main_cachePtr)["1"]; 40 | } 41 | else 42 | { 43 | LOG_DEBUG << "can't find item 1"; 44 | } 45 | }); 46 | mainLoop.runAfter(8, [&]() { mainLoop.quit(); }); 47 | mainLoop.loop(); 48 | } 49 | -------------------------------------------------------------------------------- /cmake_modules/FindSQLite3.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2009 LuaDist. Created by Peter Kapec 2 | # Redistribution and use of this file is allowed according to the terms of the 3 | # MIT license. For details see the COPYRIGHT file distributed with LuaDist. 4 | # Note: Searching headers and libraries is very simple and is NOT as powerful as 5 | # scripts distributed with CMake, because LuaDist defines directories to search 6 | # for. Everyone is encouraged to contact the author with improvements. Maybe 7 | # this file becomes part of CMake distribution sometimes. 8 | 9 | # * Find sqlite3 Find the native SQLITE3 headers and libraries. 10 | # 11 | # SQLITE3_INCLUDE_DIRS - where to find sqlite3.h, etc. 12 | # SQLITE3_LIBRARIES - List of libraries when using sqlite. 13 | # SQLite3_FOUND - True if sqlite3 found. 14 | # SQLite3_lib - The imported target library. 15 | 16 | # Look for the header file. 17 | find_path(SQLITE3_INCLUDE_DIRS NAMES sqlite3.h) 18 | 19 | # Look for the library. 20 | find_library(SQLITE3_LIBRARIES NAMES sqlite3) 21 | 22 | # Handle the QUIETLY and REQUIRED arguments and set SQLite3_FOUND to TRUE if all 23 | # listed variables are TRUE. 24 | include(FindPackageHandleStandardArgs) 25 | find_package_handle_standard_args(SQLite3 26 | DEFAULT_MSG 27 | SQLITE3_LIBRARIES 28 | SQLITE3_INCLUDE_DIRS) 29 | 30 | # Copy the results to the output variables. 31 | if(SQLite3_FOUND) 32 | add_library(SQLite3_lib INTERFACE IMPORTED) 33 | set_target_properties(SQLite3_lib 34 | PROPERTIES INTERFACE_INCLUDE_DIRECTORIES 35 | "${SQLITE3_INCLUDE_DIRS}" 36 | INTERFACE_LINK_LIBRARIES 37 | "${SQLITE3_LIBRARIES}") 38 | else(SQLite3_FOUND) 39 | set(SQLITE3_LIBRARIES) 40 | set(SQLITE3_INCLUDE_DIRS) 41 | endif(SQLite3_FOUND) 42 | 43 | mark_as_advanced(SQLITE3_INCLUDE_DIRS SQLITE3_LIBRARIES) 44 | -------------------------------------------------------------------------------- /orm_lib/src/DbClient.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * DbClient.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "DbClientImpl.h" 16 | #include 17 | #include 18 | using namespace drogon::orm; 19 | using namespace drogon; 20 | 21 | internal::SqlBinder DbClient::operator<<(const std::string &sql) 22 | { 23 | return internal::SqlBinder(sql, *this, type_); 24 | } 25 | 26 | internal::SqlBinder DbClient::operator<<(std::string &&sql) 27 | { 28 | return internal::SqlBinder(std::move(sql), *this, type_); 29 | } 30 | 31 | std::shared_ptr DbClient::newPgClient(const std::string &connInfo, 32 | const size_t connNum) 33 | { 34 | #if USE_POSTGRESQL 35 | return std::make_shared(connInfo, 36 | connNum, 37 | ClientType::PostgreSQL); 38 | #else 39 | LOG_FATAL << "PostgreSQL is not supported!"; 40 | exit(1); 41 | #endif 42 | } 43 | 44 | std::shared_ptr DbClient::newMysqlClient(const std::string &connInfo, 45 | const size_t connNum) 46 | { 47 | #if USE_MYSQL 48 | return std::make_shared(connInfo, connNum, ClientType::Mysql); 49 | #else 50 | LOG_FATAL << "Mysql is not supported!"; 51 | exit(1); 52 | #endif 53 | } 54 | 55 | std::shared_ptr DbClient::newSqlite3Client( 56 | const std::string &connInfo, 57 | const size_t connNum) 58 | { 59 | #if USE_SQLITE3 60 | return std::make_shared(connInfo, 61 | connNum, 62 | ClientType::Sqlite3); 63 | #else 64 | LOG_FATAL << "Sqlite3 is not supported!"; 65 | exit(1); 66 | #endif 67 | } 68 | -------------------------------------------------------------------------------- /lib/inc/drogon/UploadFile.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * UploadFile.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | #include 17 | 18 | namespace drogon 19 | { 20 | /** 21 | * This class represents an upload file which will be transferred to the server 22 | * via the multipart/form-data format 23 | */ 24 | class UploadFile 25 | { 26 | public: 27 | /// Constructor 28 | /** 29 | * @param filePath The file location on local host, including file name. 30 | * @param fileName The file name provided to the server. If it is empty by 31 | * default, the file name in the @param filePath 32 | * is provided to the server. 33 | * @param itemName The item name on the browser form. 34 | */ 35 | explicit UploadFile(const std::string &filePath, 36 | const std::string &fileName = "", 37 | const std::string &itemName = "file") 38 | : path_(filePath), itemName_(itemName) 39 | { 40 | if (!fileName.empty()) 41 | { 42 | fileName_ = fileName; 43 | } 44 | else 45 | { 46 | auto pos = filePath.rfind('/'); 47 | if (pos != std::string::npos) 48 | { 49 | fileName_ = filePath.substr(pos + 1); 50 | } 51 | else 52 | { 53 | fileName_ = filePath; 54 | } 55 | } 56 | } 57 | const std::string &path() const 58 | { 59 | return path_; 60 | } 61 | const std::string &fileName() const 62 | { 63 | return fileName_; 64 | } 65 | const std::string &itemName() const 66 | { 67 | return itemName_; 68 | } 69 | 70 | private: 71 | std::string path_; 72 | std::string fileName_; 73 | std::string itemName_; 74 | }; 75 | } // namespace drogon 76 | -------------------------------------------------------------------------------- /lib/src/NotFound.cc: -------------------------------------------------------------------------------- 1 | // this file is generated by program automatically,don't modify it! 2 | 3 | /** 4 | * 5 | * NotFound.cc 6 | * An Tao 7 | * 8 | * Copyright 2018, An Tao. All rights reserved. 9 | * https://github.com/an-tao/drogon 10 | * Use of this source code is governed by a MIT license 11 | * that can be found in the License file. 12 | * 13 | * Drogon 14 | * 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace drogon; 25 | 26 | std::string NotFound::genText(const HttpViewData &NotFound_view_data) 27 | { 28 | std::stringstream NotFound_tmp_stream; 29 | NotFound_tmp_stream << "\n"; 30 | NotFound_tmp_stream << "404 Not Found\n"; 31 | NotFound_tmp_stream << "\n"; 32 | NotFound_tmp_stream << "

404 Not Found

\n"; 33 | NotFound_tmp_stream << "
drogon/"; 34 | NotFound_tmp_stream << NotFound_view_data.get("version"); 35 | NotFound_tmp_stream << "
\n"; 36 | NotFound_tmp_stream << "\n"; 37 | NotFound_tmp_stream << "\n"; 38 | NotFound_tmp_stream << "\n"; 40 | NotFound_tmp_stream << "\n"; 42 | NotFound_tmp_stream << "\n"; 44 | NotFound_tmp_stream << "\n"; 46 | NotFound_tmp_stream << "\n"; 48 | NotFound_tmp_stream << "\n"; 50 | return NotFound_tmp_stream.str(); 51 | } 52 | -------------------------------------------------------------------------------- /lib/src/CacheFile.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * CacheFile.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "CacheFile.h" 16 | #include 17 | #ifdef _WIN32 18 | #include 19 | #else 20 | #include 21 | #include 22 | #endif 23 | 24 | using namespace drogon; 25 | 26 | CacheFile::CacheFile(const std::string &path, bool autoDelete) 27 | : autoDelete_(autoDelete), path_(path) 28 | { 29 | #ifndef _MSC_VER 30 | file_ = fopen(path_.data(), "wb+"); 31 | #else 32 | if (fopen_s(&file_, path_.data(), "wb+") != 0) 33 | { 34 | file_ = nullptr; 35 | } 36 | #endif 37 | } 38 | 39 | CacheFile::~CacheFile() 40 | { 41 | if (data_) 42 | { 43 | munmap(data_, dataLength_); 44 | } 45 | if (autoDelete_ && file_) 46 | { 47 | fclose(file_); 48 | #ifdef _WIN32 49 | _unlink(path_.data()); 50 | #else 51 | unlink(path_.data()); 52 | #endif 53 | } 54 | else if (file_) 55 | { 56 | fclose(file_); 57 | } 58 | } 59 | 60 | void CacheFile::append(const char *data, size_t length) 61 | { 62 | if (file_) 63 | fwrite(data, length, 1, file_); 64 | } 65 | 66 | size_t CacheFile::length() 67 | { 68 | if (file_) 69 | return ftell(file_); 70 | return 0; 71 | } 72 | 73 | char *CacheFile::data() 74 | { 75 | if (!file_) 76 | return nullptr; 77 | if (!data_) 78 | { 79 | fflush(file_); 80 | #ifdef _WIN32 81 | auto fd = _fileno(file_); 82 | #else 83 | auto fd = fileno(file_); 84 | #endif 85 | dataLength_ = length(); 86 | data_ = static_cast( 87 | mmap(nullptr, dataLength_, PROT_READ, MAP_SHARED, fd, 0)); 88 | if (data_ == MAP_FAILED) 89 | { 90 | data_ = nullptr; 91 | LOG_SYSERR << "mmap:"; 92 | } 93 | } 94 | return data_; 95 | } 96 | -------------------------------------------------------------------------------- /lib/inc/drogon/plugins/SecureSSLRedirector.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * drogon_plugin_SecureSSLRedirector.h 4 | * 5 | */ 6 | 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | 12 | namespace drogon 13 | { 14 | namespace plugin 15 | { 16 | /** 17 | * @brief This plugin is used to redirect all non-HTTPS requests to HTTPS 18 | * (except for those URLs matching a regular expression listed in 19 | * the 'ssl_redirect_exempt' list). 20 | * 21 | * The json configuration is as follows: 22 | * 23 | * @code 24 | { 25 | "name": "drogon::plugin::SecureSSLRedirector", 26 | "dependencies": [], 27 | "config": { 28 | "ssl_redirect_exempt": ["^/.*\\.jpg", ...], 29 | "secure_ssl_host": "localhost:8849" 30 | } 31 | } 32 | @endcode 33 | * 34 | * ssl_redirect_exempt: a regular expression (for matching the path of a 35 | * request) list for URLs that don't have to be redirected. 36 | * secure_ssl_host: If this string is not empty, all SSL redirects 37 | * will be directed to this host rather than the originally-requested host. 38 | * 39 | * Enable the plugin by adding the configuration to the list of plugins in the 40 | * configuration file. 41 | * 42 | */ 43 | class SecureSSLRedirector : public drogon::Plugin 44 | { 45 | public: 46 | SecureSSLRedirector() 47 | { 48 | } 49 | /// This method must be called by drogon to initialize and start the plugin. 50 | /// It must be implemented by the user. 51 | virtual void initAndStart(const Json::Value &config) override; 52 | 53 | /// This method must be called by drogon to shutdown the plugin. 54 | /// It must be implemented by the user. 55 | virtual void shutdown() override; 56 | 57 | private: 58 | HttpResponsePtr redirectingAdvice(const HttpRequestPtr &) const; 59 | HttpResponsePtr redirectToSSL(const HttpRequestPtr &) const; 60 | 61 | std::regex exemptPegex_; 62 | bool regexFlag_{false}; 63 | std::string secureHost_; 64 | }; 65 | 66 | } // namespace plugin 67 | } // namespace drogon 68 | -------------------------------------------------------------------------------- /examples/simple_example/api_Attachment.cc: -------------------------------------------------------------------------------- 1 | #include "api_Attachment.h" 2 | #include 3 | 4 | using namespace api; 5 | // add definition of your processing function here 6 | void Attachment::get(const HttpRequestPtr &req, 7 | std::function &&callback) 8 | { 9 | auto resp = HttpResponse::newHttpViewResponse("FileUpload", HttpViewData()); 10 | callback(resp); 11 | } 12 | 13 | void Attachment::upload(const HttpRequestPtr &req, 14 | std::function &&callback) 15 | { 16 | MultiPartParser fileUpload; 17 | if (fileUpload.parse(req) == 0) 18 | { 19 | // LOG_DEBUG << "upload good!"; 20 | auto &files = fileUpload.getFiles(); 21 | // LOG_DEBUG << "file num=" << files.size(); 22 | for (auto const &file : files) 23 | { 24 | LOG_DEBUG << "file:" << file.getFileName() 25 | << "(len=" << file.fileLength() 26 | << ",md5=" << file.getMd5() << ")"; 27 | file.save(); 28 | file.save("123"); 29 | file.saveAs("456/hehe"); 30 | file.saveAs("456/7/8/9/" + file.getMd5()); 31 | file.save(".."); 32 | file.save(".xx"); 33 | file.saveAs("../xxx"); 34 | } 35 | Json::Value json; 36 | json["result"] = "ok"; 37 | for (auto ¶m : fileUpload.getParameters()) 38 | { 39 | json[param.first] = param.second; 40 | } 41 | auto resp = HttpResponse::newHttpJsonResponse(json); 42 | callback(resp); 43 | return; 44 | } 45 | LOG_DEBUG << "upload error!"; 46 | // LOG_DEBUG<con 47 | Json::Value json; 48 | json["result"] = "failed"; 49 | auto resp = HttpResponse::newHttpJsonResponse(json); 50 | callback(resp); 51 | } 52 | 53 | void Attachment::download( 54 | const HttpRequestPtr &req, 55 | std::function &&callback) 56 | { 57 | auto resp = HttpResponse::newFileResponse("./drogon.jpg", "", CT_IMAGE_JPG); 58 | callback(resp); 59 | } 60 | -------------------------------------------------------------------------------- /lib/src/impl_forwards.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace drogon 7 | { 8 | class HttpRequest; 9 | using HttpRequestPtr = std::shared_ptr; 10 | class HttpResponse; 11 | using HttpResponsePtr = std::shared_ptr; 12 | class Cookie; 13 | class Session; 14 | using SessionPtr = std::shared_ptr; 15 | class UploadFile; 16 | class WebSocketControllerBase; 17 | using WebSocketControllerBasePtr = std::shared_ptr; 18 | class HttpFilterBase; 19 | using HttpFilterBasePtr = std::shared_ptr; 20 | class HttpSimpleControllerBase; 21 | using HttpSimpleControllerBasePtr = std::shared_ptr; 22 | class HttpRequestImpl; 23 | using HttpRequestImplPtr = std::shared_ptr; 24 | class HttpResponseImpl; 25 | using HttpResponseImplPtr = std::shared_ptr; 26 | class WebSocketConnectionImpl; 27 | using WebSocketConnectionImplPtr = std::shared_ptr; 28 | class HttpRequestParser; 29 | class StaticFileRouter; 30 | class HttpControllersRouter; 31 | class WebsocketControllersRouter; 32 | class HttpSimpleControllersRouter; 33 | class PluginsManager; 34 | class ListenerManager; 35 | class SharedLibManager; 36 | class SessionManager; 37 | class HttpServer; 38 | 39 | namespace orm 40 | { 41 | class DbClient; 42 | using DbClientPtr = std::shared_ptr; 43 | class DbClientManager; 44 | } // namespace orm 45 | } // namespace drogon 46 | 47 | namespace trantor 48 | { 49 | class EventLoop; 50 | class TcpConnection; 51 | using TcpConnectionPtr = std::shared_ptr; 52 | class Resolver; 53 | } // namespace trantor 54 | 55 | namespace drogon 56 | { 57 | using HttpAsyncCallback = 58 | std::function &&)>; 60 | using WebSocketNewAsyncCallback = 61 | std::function &&, 63 | const WebSocketConnectionImplPtr &)>; 64 | } // namespace drogon 65 | -------------------------------------------------------------------------------- /drogon_ctl/press.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * press.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by the MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include "CommandHandler.h" 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | using namespace drogon; 29 | 30 | namespace drogon_ctl 31 | { 32 | struct Statistics 33 | { 34 | std::atomic_size_t numOfRequestsSent_{0}; 35 | std::atomic_size_t bytesRecieved_{0}; 36 | std::atomic_size_t numOfGoodResponse_{0}; 37 | std::atomic_size_t numOfBadResponse_{0}; 38 | std::atomic_size_t totalDelay_{0}; 39 | trantor::Date startDate_; 40 | trantor::Date endDate_; 41 | }; 42 | class press : public DrObject, public CommandHandler 43 | { 44 | public: 45 | virtual void handleCommand(std::vector ¶meters) override; 46 | virtual std::string script() override 47 | { 48 | return "Do stress testing(Use 'drogon_ctl help press' for more " 49 | "information)"; 50 | } 51 | virtual bool isTopCommand() override 52 | { 53 | return true; 54 | } 55 | virtual std::string detail() override; 56 | 57 | private: 58 | size_t numOfThreads_{1}; 59 | size_t numOfRequests_{1}; 60 | size_t numOfConnections_{1}; 61 | // bool keepAlive_ = false; 62 | bool processIndication_{true}; 63 | std::string url_; 64 | std::string host_; 65 | std::string path_; 66 | void doTesting(); 67 | void createRequestAndClients(); 68 | void sendRequest(const HttpClientPtr &client); 69 | void outputResults(); 70 | std::unique_ptr loopPool_; 71 | std::vector clients_; 72 | Statistics statistics_; 73 | }; 74 | } // namespace drogon_ctl 75 | -------------------------------------------------------------------------------- /examples/simple_reverse_proxy/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.5) 2 | project(simple_reverse_proxy CXX) 3 | 4 | include(CheckIncludeFileCXX) 5 | 6 | check_include_file_cxx(any HAS_ANY) 7 | check_include_file_cxx(string_view HAS_STRING_VIEW) 8 | if(HAS_ANY AND HAS_STRING_VIEW) 9 | set(CMAKE_CXX_STANDARD 17) 10 | else() 11 | set(CMAKE_CXX_STANDARD 14) 12 | endif() 13 | 14 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 15 | set(CMAKE_CXX_EXTENSIONS OFF) 16 | 17 | add_executable(simple_reverse_proxy main.cc) 18 | 19 | ########## 20 | # If you include the drogon source code locally in your project, use this method to add drogon 21 | # add_subdirectory(drogon) 22 | # target_link_libraries(simple_reverse_proxy PRIVATE drogon) 23 | ########## 24 | 25 | find_package(Drogon CONFIG REQUIRED) 26 | target_link_libraries(simple_reverse_proxy PRIVATE Drogon::Drogon) 27 | 28 | if(CMAKE_CXX_STANDARD LESS 17) 29 | #With C++14, use boost to support any and string_view 30 | message(STATUS "use c++14") 31 | find_package(Boost 1.61.0 REQUIRED) 32 | target_include_directories(simple_reverse_proxy PRIVATE ${Boost_INCLUDE_DIRS}) 33 | else() 34 | message(STATUS "use c++17") 35 | endif() 36 | 37 | aux_source_directory(controllers CTL_SRC) 38 | aux_source_directory(filters FILTER_SRC) 39 | aux_source_directory(plugins PLUGIN_SRC) 40 | aux_source_directory(models MODEL_SRC) 41 | 42 | file(GLOB SCP_LIST ${CMAKE_CURRENT_SOURCE_DIR}/views/*.csp) 43 | foreach(cspFile ${SCP_LIST}) 44 | message(STATUS "cspFile:" ${cspFile}) 45 | EXEC_PROGRAM(basename ARGS "${cspFile} .csp" OUTPUT_VARIABLE classname) 46 | message(STATUS "view classname:" ${classname}) 47 | ADD_CUSTOM_COMMAND(OUTPUT ${classname}.h ${classname}.cc 48 | COMMAND drogon_ctl 49 | ARGS create view ${cspFile} 50 | DEPENDS ${cspFile} 51 | VERBATIM ) 52 | set(VIEWSRC ${VIEWSRC} ${classname}.cc) 53 | endforeach() 54 | 55 | target_include_directories(simple_reverse_proxy PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/models) 56 | target_sources(simple_reverse_proxy PRIVATE ${SRC_DIR} ${CTL_SRC} ${FILTER_SRC} ${VIEWSRC} ${PLUGIN_SRC} ${MODEL_SRC}) 57 | -------------------------------------------------------------------------------- /orm_lib/src/sqlite3_impl/Sqlite3ResultImpl.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Sqlite3ResultImpl.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "Sqlite3ResultImpl.h" 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace drogon::orm; 21 | 22 | Result::SizeType Sqlite3ResultImpl::size() const noexcept 23 | { 24 | return result_.size(); 25 | } 26 | 27 | Result::RowSizeType Sqlite3ResultImpl::columns() const noexcept 28 | { 29 | return result_.empty() ? 0 : result_[0].size(); 30 | } 31 | 32 | const char *Sqlite3ResultImpl::columnName(RowSizeType number) const 33 | { 34 | assert(number < columnNames_.size()); 35 | return columnNames_[number].c_str(); 36 | } 37 | 38 | Result::SizeType Sqlite3ResultImpl::affectedRows() const noexcept 39 | { 40 | return affectedRows_; 41 | } 42 | 43 | Result::RowSizeType Sqlite3ResultImpl::columnNumber(const char colName[]) const 44 | { 45 | auto name = std::string(colName); 46 | std::transform(name.begin(), name.end(), name.begin(), tolower); 47 | auto iter = columnNamesMap_.find(name); 48 | if (iter != columnNamesMap_.end()) 49 | { 50 | return iter->second; 51 | } 52 | throw RangeError(std::string("there is no column named ") + colName); 53 | } 54 | 55 | const char *Sqlite3ResultImpl::getValue(SizeType row, RowSizeType column) const 56 | { 57 | auto col = result_[row][column]; 58 | return col ? col->c_str() : nullptr; 59 | } 60 | 61 | bool Sqlite3ResultImpl::isNull(SizeType row, RowSizeType column) const 62 | { 63 | return !result_[row][column]; 64 | } 65 | 66 | Result::FieldSizeType Sqlite3ResultImpl::getLength(SizeType row, 67 | RowSizeType column) const 68 | { 69 | auto col = result_[row][column]; 70 | return col ? col->length() : 0; 71 | } 72 | 73 | unsigned long long Sqlite3ResultImpl::insertId() const noexcept 74 | { 75 | return insertId_; 76 | } 77 | -------------------------------------------------------------------------------- /drogon_ctl/version.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * version.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "version.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | using namespace drogon_ctl; 22 | static const char banner[] = 23 | " _ \n" 24 | " __| |_ __ ___ __ _ ___ _ __ \n" 25 | " / _` | '__/ _ \\ / _` |/ _ \\| '_ \\ \n" 26 | "| (_| | | | (_) | (_| | (_) | | | |\n" 27 | " \\__,_|_| \\___/ \\__, |\\___/|_| |_|\n" 28 | " |___/ \n"; 29 | 30 | void version::handleCommand(std::vector ¶meters) 31 | { 32 | std::cout << banner << std::endl; 33 | std::cout << "A utility for drogon" << std::endl; 34 | std::cout << "Version: " << DROGON_VERSION << std::endl; 35 | std::cout << "Git commit: " << DROGON_VERSION_SHA1 << std::endl; 36 | std::cout << "Compilation: \n Compiler: " << COMPILER_COMMAND 37 | << "\n Compiler ID: " << COMPILER_ID 38 | << "\n Compilation flags: " << COMPILATION_FLAGS 39 | << INCLUDING_DIRS << std::endl; 40 | std::cout << "Libraries: \n postgresql: " 41 | << (USE_POSTGRESQL ? "yes" : "no") << " (batch mode: " 42 | << (LIBPQ_SUPPORTS_BATCH_MODE ? "yes)\n" : "no)\n") 43 | << " mariadb: " << (USE_MYSQL ? "yes\n" : "no\n") 44 | << " sqlite3: " << (USE_SQLITE3 ? "yes\n" : "no\n"); 45 | #ifdef OpenSSL_FOUND 46 | std::cout << " openssl: yes\n"; 47 | #else 48 | std::cout << " openssl: no\n"; 49 | #endif 50 | #ifdef USE_BROTLI 51 | std::cout << " brotli: yes\n"; 52 | #else 53 | std::cout << " brotli: no\n"; 54 | #endif 55 | #ifdef Boost_FOUND 56 | std::cout << " boost: yes\n"; 57 | #else 58 | std::cout << " boost: no\n"; 59 | #endif 60 | std::cout << " c-ares: " 61 | << (trantor::Resolver::isCAresUsed() ? "yes\n" : "no\n"); 62 | } 63 | -------------------------------------------------------------------------------- /lib/inc/drogon/HttpFilter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * HttpFilter.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | namespace drogon 24 | { 25 | /** 26 | * @brief The abstract base class for filters 27 | * For more details on the class, see the wiki site (the 'Filter' section) 28 | */ 29 | class HttpFilterBase : public virtual DrObjectBase 30 | { 31 | public: 32 | /// This virtual function should be overrided in subclasses. 33 | /** 34 | * This method is an asynchronous interface, user should return the result 35 | * via 'FilterCallback' or 'FilterChainCallback'. 36 | * @param req is the request object processed by the filter 37 | * @param fcb if this is called, the response object is send to the client 38 | * by the callback, and doFilter methods of next filters and the handler 39 | * registed on the path are not called anymore. 40 | * @param fccb if this callback is called, the next filter's doFilter method 41 | * or the handler registered on the path is called. 42 | */ 43 | virtual void doFilter(const HttpRequestPtr &req, 44 | FilterCallback &&fcb, 45 | FilterChainCallback &&fccb) = 0; 46 | virtual ~HttpFilterBase() 47 | { 48 | } 49 | }; 50 | 51 | /** 52 | * @brief The reflection base class template for filters 53 | * 54 | * @tparam T The type of the implementation class 55 | * @tparam AutoCreation The flag for automatically creating, user can set this 56 | * flag to false for classes that have nondefault constructors. 57 | */ 58 | template 59 | class HttpFilter : public DrObject, public HttpFilterBase 60 | { 61 | public: 62 | static constexpr bool isAutoCreation{AutoCreation}; 63 | virtual ~HttpFilter() 64 | { 65 | } 66 | }; 67 | } // namespace drogon 68 | -------------------------------------------------------------------------------- /lib/src/SpinLock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * SpinLock.h 3 | * An Tao 4 | * 5 | * Copyright 2018, An Tao. All rights reserved. 6 | * https://github.com/an-tao/drogon 7 | * Use of this source code is governed by a MIT license 8 | * that can be found in the License file. 9 | * 10 | * Drogon 11 | * 12 | */ 13 | 14 | #pragma once 15 | #include 16 | #include 17 | #include 18 | 19 | #define LOCK_SPIN 2048 20 | 21 | namespace drogon 22 | { 23 | class SpinLock 24 | { 25 | public: 26 | inline SpinLock(std::atomic &flag) : flag_(flag) 27 | { 28 | const static int cpu = std::thread::hardware_concurrency(); 29 | int n, i; 30 | while (1) 31 | { 32 | if (!flag_.load() && 33 | !flag_.exchange(true, std::memory_order_acquire)) 34 | { 35 | return; 36 | } 37 | if (cpu > 1) 38 | { 39 | for (n = 1; n < LOCK_SPIN; n <<= 1) 40 | { 41 | for (i = 0; i < n; ++i) 42 | { 43 | //__asm__ __volatile__("rep; nop" ::: "memory"); //pause 44 | _mm_pause(); 45 | } 46 | if (!flag_.load() && 47 | !flag_.exchange(true, std::memory_order_acquire)) 48 | { 49 | return; 50 | } 51 | } 52 | } 53 | std::this_thread::yield(); 54 | } 55 | } 56 | inline ~SpinLock() 57 | { 58 | flag_.store(false, std::memory_order_release); 59 | } 60 | 61 | private: 62 | std::atomic &flag_; 63 | }; 64 | 65 | class SimpleSpinLock 66 | { 67 | public: 68 | inline SimpleSpinLock(std::atomic_flag &flag) : flag_(flag) 69 | { 70 | while (flag_.test_and_set(std::memory_order_acquire)) 71 | { 72 | //__asm__ __volatile__("rep; nop" ::: "memory"); //pause 73 | _mm_pause(); 74 | } 75 | } 76 | inline ~SimpleSpinLock() 77 | { 78 | flag_.clear(std::memory_order_release); 79 | } 80 | 81 | private: 82 | std::atomic_flag &flag_; 83 | }; 84 | 85 | } // namespace drogon 86 | -------------------------------------------------------------------------------- /drogon_ctl/create.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * create.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "create.h" 16 | #include "cmd.h" 17 | #include 18 | #include 19 | #include 20 | using namespace drogon_ctl; 21 | std::string create::detail() 22 | { 23 | return "Use create command to create some source files of drogon webapp\n\n" 24 | "Usage:drogon_ctl create " 25 | "[-options] \n\n" 26 | "drogon_ctl create view [-o ]//create " 27 | "HttpView source files from csp file\n\n" 28 | "drogon_ctl create controller [-s] <[namespace::]class_name> //" 29 | "create HttpSimpleController source files\n\n" 30 | "drogon_ctl create controller -h <[namespace::]class_name> //" 31 | "create HttpController source files\n\n" 32 | "drogon_ctl create controller -w <[namespace::]class_name> //" 33 | "create WebSocketController source files\n\n" 34 | "drogon_ctl create controller -r <[namespace::]class_name> " 35 | "[--resource=...]//" 36 | "create restful controller source files\n\n" 37 | "drogon_ctl create filter <[namespace::]class_name> //" 38 | "create a filter named class_name\n\n" 39 | "drogon_ctl create plugin <[namespace::]class_name> //" 40 | "create a plugin named class_name\n\n" 41 | "drogon_ctl create project //" 42 | "create a project named project_name\n\n" 43 | "drogon_ctl create model [--table=] [-f]//" 44 | "create model classes in model_path\n"; 45 | } 46 | 47 | void create::handleCommand(std::vector ¶meters) 48 | { 49 | // std::cout<<"create!"< 10 | 11 | <%c++ 12 | 13 | auto tableInfo = @@.get("tableInfo"); 14 | auto modelName = tableInfo.get("className"); 15 | bool hasPrimaryKey = (tableInfo.get("hasPrimaryKey")==1); 16 | 17 | 18 | auto namespaceVector=@@.get>("namespaceVector"); 19 | std::string namespaceStr; 20 | for(auto &name:namespaceVector) 21 | { 22 | namespaceStr.append(name); 23 | namespaceStr.append("::"); 24 | } 25 | if(!namespaceStr.empty()) 26 | { 27 | namespaceStr.resize(namespaceStr.length()-2); 28 | $$<<"using namespace "<("className").length(), ' '); 31 | %> 32 | 33 | <%c++ 34 | if(hasPrimaryKey) 35 | {%> 36 | void [[className]]::getOne(const HttpRequestPtr &req, 37 | {%indentStr%} std::function &&callback, 38 | {%indentStr%} {%modelName%}::PrimaryKeyType &&id) 39 | { 40 | [[className]]Base::getOne(req, std::move(callback), std::move(id)); 41 | } 42 | 43 | 44 | void [[className]]::updateOne(const HttpRequestPtr &req, 45 | {%indentStr%} std::function &&callback, 46 | {%indentStr%} {%modelName%}::PrimaryKeyType &&id) 47 | { 48 | [[className]]Base::updateOne(req, std::move(callback), std::move(id)); 49 | } 50 | 51 | 52 | void [[className]]::deleteOne(const HttpRequestPtr &req, 53 | {%indentStr%} std::function &&callback, 54 | {%indentStr%} {%modelName%}::PrimaryKeyType &&id) 55 | { 56 | [[className]]Base::deleteOne(req, std::move(callback), std::move(id)); 57 | } 58 | <%c++}%> 59 | 60 | void [[className]]::get(const HttpRequestPtr &req, 61 | {%indentStr%} std::function &&callback) 62 | { 63 | [[className]]Base::get(req, std::move(callback)); 64 | } 65 | 66 | void [[className]]::create(const HttpRequestPtr &req, 67 | {%indentStr%} std::function &&callback) 68 | { 69 | [[className]]Base::create(req, std::move(callback)); 70 | } 71 | -------------------------------------------------------------------------------- /third_party/mman-win32/mman.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sys/mman.h 3 | * mman-win32 4 | */ 5 | 6 | #ifndef _SYS_MMAN_H_ 7 | #define _SYS_MMAN_H_ 8 | 9 | #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. 10 | #define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. 11 | #endif 12 | 13 | /* All the headers include this file. */ 14 | #ifndef _MSC_VER 15 | #include <_mingw.h> 16 | #endif 17 | 18 | #if defined(MMAN_LIBRARY_DLL) 19 | /* Windows shared libraries (DLL) must be declared export when building the lib and import when building the 20 | application which links against the library. */ 21 | #if defined(MMAN_LIBRARY) 22 | #define MMANSHARED_EXPORT __declspec(dllexport) 23 | #else 24 | #define MMANSHARED_EXPORT __declspec(dllimport) 25 | #endif /* MMAN_LIBRARY */ 26 | #else 27 | /* Static libraries do not require a __declspec attribute.*/ 28 | #define MMANSHARED_EXPORT 29 | #endif /* MMAN_LIBRARY_DLL */ 30 | 31 | /* Determine offset type */ 32 | #include 33 | #if defined(_WIN64) 34 | typedef int64_t OffsetType; 35 | #else 36 | typedef uint32_t OffsetType; 37 | #endif 38 | 39 | #include 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | #define PROT_NONE 0 46 | #define PROT_READ 1 47 | #define PROT_WRITE 2 48 | #define PROT_EXEC 4 49 | 50 | #define MAP_FILE 0 51 | #define MAP_SHARED 1 52 | #define MAP_PRIVATE 2 53 | #define MAP_TYPE 0xf 54 | #define MAP_FIXED 0x10 55 | #define MAP_ANONYMOUS 0x20 56 | #define MAP_ANON MAP_ANONYMOUS 57 | 58 | #define MAP_FAILED ((void *)-1) 59 | 60 | /* Flags for msync. */ 61 | #define MS_ASYNC 1 62 | #define MS_SYNC 2 63 | #define MS_INVALIDATE 4 64 | 65 | MMANSHARED_EXPORT void* mmap(void *addr, size_t len, int prot, int flags, int fildes, OffsetType off); 66 | MMANSHARED_EXPORT int munmap(void *addr, size_t len); 67 | MMANSHARED_EXPORT int _mprotect(void *addr, size_t len, int prot); 68 | MMANSHARED_EXPORT int msync(void *addr, size_t len, int flags); 69 | MMANSHARED_EXPORT int mlock(const void *addr, size_t len); 70 | MMANSHARED_EXPORT int munlock(const void *addr, size_t len); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif /* _SYS_MMAN_H_ */ 77 | -------------------------------------------------------------------------------- /drogon_ctl/help.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * help.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "help.h" 16 | #include 17 | #include 18 | #include 19 | using namespace drogon_ctl; 20 | void help::handleCommand(std::vector ¶meters) 21 | { 22 | if (parameters.size() == 0) 23 | { 24 | std::cout << "usage: drogon_ctl [-v | --version] [-h | --help] " 25 | " []" 26 | << std::endl; 27 | std::cout << "commands list:" << std::endl; 28 | for (auto &className : drogon::DrClassMap::getAllClassName()) 29 | { 30 | auto classPtr = std::shared_ptr( 31 | drogon::DrClassMap::newObject(className)); 32 | if (classPtr) 33 | { 34 | auto cmdHdlPtr = 35 | std::dynamic_pointer_cast(classPtr); 36 | if (cmdHdlPtr) 37 | { 38 | if (!cmdHdlPtr->isTopCommand()) 39 | continue; 40 | auto pos = className.rfind("::"); 41 | if (pos != std::string::npos) 42 | { 43 | className = className.substr(pos + 2); 44 | } 45 | while (className.length() < 24) 46 | className.append(" "); 47 | std::cout << className << cmdHdlPtr->script() << std::endl; 48 | } 49 | } 50 | } 51 | } 52 | else 53 | { 54 | auto cmd = std::string("drogon_ctl::") + parameters[0]; 55 | 56 | auto classPtr = 57 | std::shared_ptr(drogon::DrClassMap::newObject(cmd)); 58 | if (classPtr) 59 | { 60 | auto cmdHdlPtr = 61 | std::dynamic_pointer_cast(classPtr); 62 | if (cmdHdlPtr) 63 | { 64 | if (cmdHdlPtr->isTopCommand()) 65 | std::cout << cmdHdlPtr->detail() << std::endl; 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/src/DbClientManager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * DbClientManager.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace drogon 26 | { 27 | namespace orm 28 | { 29 | class DbClientManager : public trantor::NonCopyable 30 | { 31 | public: 32 | void createDbClients(const std::vector &ioloops); 33 | DbClientPtr getDbClient(const std::string &name) 34 | { 35 | assert(dbClientsMap_.find(name) != dbClientsMap_.end()); 36 | return dbClientsMap_[name]; 37 | } 38 | 39 | DbClientPtr getFastDbClient(const std::string &name) 40 | { 41 | auto iter = dbFastClientsMap_.find(name); 42 | assert(iter != dbFastClientsMap_.end()); 43 | return iter->second.getThreadData(); 44 | } 45 | void createDbClient(const std::string &dbType, 46 | const std::string &host, 47 | const unsigned short port, 48 | const std::string &databaseName, 49 | const std::string &userName, 50 | const std::string &password, 51 | const size_t connectionNum, 52 | const std::string &filename, 53 | const std::string &name, 54 | const bool isFast, 55 | const std::string &characterSet); 56 | bool areAllDbClientsAvailable() const noexcept; 57 | 58 | private: 59 | std::map dbClientsMap_; 60 | struct DbInfo 61 | { 62 | std::string name_; 63 | std::string connectionInfo_; 64 | ClientType dbType_; 65 | bool isFast_; 66 | size_t connectionNumber_; 67 | }; 68 | std::vector dbInfos_; 69 | std::map> dbFastClientsMap_; 70 | }; 71 | } // namespace orm 72 | } // namespace drogon 73 | -------------------------------------------------------------------------------- /cmake_modules/FindBrotli.cmake: -------------------------------------------------------------------------------- 1 | # *************************************************************************** 2 | # _ _ ____ _ 3 | # Project ___| | | | _ \| | 4 | # / __| | | | |_) | | 5 | # | (__| |_| | _ <| |___ 6 | # \___|\___/|_| \_\_____| 7 | # 8 | # Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. 9 | # 10 | # This software is licensed as described in the file COPYING, which you should 11 | # have received as part of this distribution. The terms are also available at 12 | # https://curl.haxx.se/docs/copyright.html. 13 | # 14 | # You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 | # copies of the Software, and permit persons to whom the Software is furnished 16 | # to do so, under the terms of the COPYING file. 17 | # 18 | # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 | # KIND, either express or implied. 20 | # 21 | # ############################################################################## 22 | include(FindPackageHandleStandardArgs) 23 | 24 | find_path(BROTLI_INCLUDE_DIR "brotli/decode.h") 25 | 26 | find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon) 27 | find_library(BROTLIDEC_LIBRARY NAMES brotlidec) 28 | find_library(BROTLIENC_LIBRARY NAMES brotlienc) 29 | 30 | find_package_handle_standard_args(Brotli 31 | REQUIRED_VARS 32 | BROTLIDEC_LIBRARY 33 | BROTLIENC_LIBRARY 34 | BROTLICOMMON_LIBRARY 35 | BROTLI_INCLUDE_DIR 36 | FAIL_MESSAGE 37 | "Could NOT find BROTLI") 38 | 39 | set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR}) 40 | set(BROTLI_LIBRARIES ${BROTLICOMMON_LIBRARY} ${BROTLIDEC_LIBRARY} 41 | ${BROTLIENC_LIBRARY}) 42 | 43 | if(Brotli_FOUND) 44 | add_library(Brotli_lib INTERFACE IMPORTED) 45 | set_target_properties(Brotli_lib 46 | PROPERTIES INTERFACE_INCLUDE_DIRECTORIES 47 | "${BROTLI_INCLUDE_DIRS}" 48 | INTERFACE_LINK_LIBRARIES 49 | "${BROTLI_LIBRARIES}") 50 | endif(Brotli_FOUND) 51 | -------------------------------------------------------------------------------- /orm_lib/src/mysql_impl/MysqlResultImpl.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * MysqlResultImpl.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "MysqlResultImpl.h" 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace drogon::orm; 21 | 22 | Result::SizeType MysqlResultImpl::size() const noexcept 23 | { 24 | return rowsNumber_; 25 | } 26 | 27 | Result::RowSizeType MysqlResultImpl::columns() const noexcept 28 | { 29 | return fieldsNumber_; 30 | } 31 | 32 | const char *MysqlResultImpl::columnName(RowSizeType number) const 33 | { 34 | assert(number < fieldsNumber_); 35 | if (fieldArray_) 36 | return fieldArray_[number].name; 37 | return ""; 38 | } 39 | 40 | Result::SizeType MysqlResultImpl::affectedRows() const noexcept 41 | { 42 | return affectedRows_; 43 | } 44 | 45 | Result::RowSizeType MysqlResultImpl::columnNumber(const char colName[]) const 46 | { 47 | if (!fieldsMapPtr_) 48 | return -1; 49 | std::string col(colName); 50 | std::transform(col.begin(), col.end(), col.begin(), tolower); 51 | if (fieldsMapPtr_->find(col) != fieldsMapPtr_->end()) 52 | return (*fieldsMapPtr_)[col]; 53 | throw RangeError(std::string("no column named ") + colName); 54 | } 55 | 56 | const char *MysqlResultImpl::getValue(SizeType row, RowSizeType column) const 57 | { 58 | if (rowsNumber_ == 0 || fieldsNumber_ == 0) 59 | return NULL; 60 | assert(row < rowsNumber_); 61 | assert(column < fieldsNumber_); 62 | return (*rowsPtr_)[row].first[column]; 63 | } 64 | 65 | bool MysqlResultImpl::isNull(SizeType row, RowSizeType column) const 66 | { 67 | return getValue(row, column) == NULL; 68 | } 69 | 70 | Result::FieldSizeType MysqlResultImpl::getLength(SizeType row, 71 | RowSizeType column) const 72 | { 73 | if (rowsNumber_ == 0 || fieldsNumber_ == 0) 74 | return 0; 75 | assert(row < rowsNumber_); 76 | assert(column < fieldsNumber_); 77 | return (*rowsPtr_)[row].second[column]; 78 | } 79 | 80 | unsigned long long MysqlResultImpl::insertId() const noexcept 81 | { 82 | return insertId_; 83 | } 84 | -------------------------------------------------------------------------------- /orm_lib/inc/drogon/orm/ArrayParser.h: -------------------------------------------------------------------------------- 1 | /** Handling of SQL arrays. 2 | * 3 | * DO NOT INCLUDE THIS FILE DIRECTLY; include drogon/orm/Field.h instead. 4 | * 5 | * Copyright (c) 2018, Jeroen T. Vermeulen. 6 | * 7 | * See COPYING for copyright license. If you did not receive a file called 8 | * COPYING with this source code, please notify the distributor of this mistake, 9 | * or contact the author. 10 | */ 11 | // Taken from libpqxx and modified 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | namespace drogon 20 | { 21 | namespace orm 22 | { 23 | /// Low-level array parser. 24 | /** Use this to read an array field retrieved from the database. 25 | * 26 | * Use this only if your client encoding is UTF-8, ASCII, or a single-byte 27 | * encoding which is a superset of ASCII. 28 | * 29 | * The input is a C-style string containing the textual representation of an 30 | * array, as returned by the database. The parser reads this representation 31 | * on the fly. The string must remain in memory until parsing is done. 32 | * 33 | * Parse the array by making calls to @c get_next until it returns a 34 | * @c juncture of "done". The @c juncture tells you what the parser found in 35 | * that step: did the array "nest" to a deeper level, or "un-nest" back up? 36 | */ 37 | class ArrayParser 38 | { 39 | public: 40 | /// What's the latest thing found in the array? 41 | enum juncture 42 | { 43 | /// Starting a new row. 44 | row_start, 45 | /// Ending the current row. 46 | row_end, 47 | /// Found a NULL value. 48 | null_value, 49 | /// Found a string value. 50 | string_value, 51 | /// Parsing has completed. 52 | done, 53 | }; 54 | 55 | /// Constructor. You don't need this; use @c field::as_array instead. 56 | explicit ArrayParser(const char input[]); 57 | 58 | /// Parse the next step in the array. 59 | /** Returns what it found. If the juncture is @c string_value, the string 60 | * will contain the value. Otherwise, it will be empty. 61 | * 62 | * Call this until the @c juncture it returns is @c done. 63 | */ 64 | std::pair getNext(); 65 | 66 | private: 67 | /// Current parsing position in the input. 68 | const char *pos_; 69 | }; 70 | 71 | } // namespace orm 72 | } // namespace drogon 73 | -------------------------------------------------------------------------------- /drogon_ctl/create_controller.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * create_controller.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include "CommandHandler.h" 20 | using namespace drogon; 21 | namespace drogon_ctl 22 | { 23 | class create_controller : public DrObject, 24 | public CommandHandler 25 | { 26 | public: 27 | virtual void handleCommand(std::vector ¶meters) override; 28 | virtual std::string script() override 29 | { 30 | return "create controller files"; 31 | } 32 | 33 | protected: 34 | enum ControllerType 35 | { 36 | Simple = 0, 37 | Http, 38 | WebSocket, 39 | Restful 40 | }; 41 | 42 | void createController(std::vector &httpClasses, 43 | ControllerType type); 44 | void createController(const std::string &className, ControllerType type); 45 | void createARestfulController(const std::string &className, 46 | const std::string &resource); 47 | 48 | void newSimpleControllerHeaderFile(std::ofstream &file, 49 | const std::string &className); 50 | void newSimpleControllerSourceFile(std::ofstream &file, 51 | const std::string &className, 52 | const std::string &filename); 53 | 54 | void newWebsockControllerHeaderFile(std::ofstream &file, 55 | const std::string &className); 56 | void newWebsockControllerSourceFile(std::ofstream &file, 57 | const std::string &className, 58 | const std::string &filename); 59 | 60 | void newHttpControllerHeaderFile(std::ofstream &file, 61 | const std::string &className); 62 | void newHttpControllerSourceFile(std::ofstream &file, 63 | const std::string &className, 64 | const std::string &filename); 65 | }; 66 | } // namespace drogon_ctl 67 | -------------------------------------------------------------------------------- /unittest/MsgBufferUnittest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace trantor; 6 | TEST(MsgBufferTest, readableTest) 7 | { 8 | MsgBuffer buffer; 9 | 10 | EXPECT_EQ(0, buffer.readableBytes()); 11 | buffer.append(std::string(128, 'a')); 12 | EXPECT_EQ(128, buffer.readableBytes()); 13 | buffer.retrieve(100); 14 | EXPECT_EQ(28, buffer.readableBytes()); 15 | EXPECT_EQ('a', buffer.peekInt8()); 16 | buffer.retrieveAll(); 17 | EXPECT_EQ(0, buffer.readableBytes()); 18 | } 19 | TEST(MsgBufferTest, writableTest) 20 | { 21 | MsgBuffer buffer(100); 22 | 23 | EXPECT_EQ(100, buffer.writableBytes()); 24 | buffer.append("abcde"); 25 | EXPECT_EQ(95, buffer.writableBytes()); 26 | buffer.append(std::string(100, 'x')); 27 | EXPECT_EQ(111, buffer.writableBytes()); 28 | buffer.retrieve(100); 29 | EXPECT_EQ(111, buffer.writableBytes()); 30 | buffer.append(std::string(112, 'c')); 31 | EXPECT_EQ(99, buffer.writableBytes()); 32 | buffer.retrieveAll(); 33 | EXPECT_EQ(216, buffer.writableBytes()); 34 | } 35 | 36 | TEST(MsgBufferTest, addInFrontTest) 37 | { 38 | MsgBuffer buffer(100); 39 | 40 | EXPECT_EQ(100, buffer.writableBytes()); 41 | buffer.addInFrontInt8('a'); 42 | EXPECT_EQ(100, buffer.writableBytes()); 43 | buffer.addInFrontInt64(123); 44 | EXPECT_EQ(92, buffer.writableBytes()); 45 | buffer.addInFrontInt64(100); 46 | EXPECT_EQ(84, buffer.writableBytes()); 47 | buffer.addInFrontInt8(1); 48 | EXPECT_EQ(84, buffer.writableBytes()); 49 | } 50 | 51 | TEST(MsgBuffer, MoveContrustor) 52 | { 53 | MsgBuffer buf1(100); 54 | const char *bufptr1 = buf1.peek(); 55 | MsgBuffer buffnew1 = std::move(buf1); 56 | EXPECT_EQ(bufptr1, buffnew1.peek()); 57 | 58 | MsgBuffer buf2(100); 59 | const char *bufptr2 = buf2.peek(); 60 | MsgBuffer buffnew2(std::move(buf2)); 61 | EXPECT_EQ(bufptr2, buffnew2.peek()); 62 | } 63 | 64 | TEST(Msgbuffer, MoveAssignmentOperator) 65 | { 66 | MsgBuffer buf(100); 67 | const char *bufptr = buf.peek(); 68 | size_t writable = buf.writableBytes(); 69 | MsgBuffer buffnew(1000); 70 | buffnew = std::move(buf); 71 | EXPECT_EQ(bufptr, buffnew.peek()); 72 | EXPECT_EQ(writable, buffnew.writableBytes()); 73 | } 74 | int main(int argc, char **argv) 75 | { 76 | testing::InitGoogleTest(&argc, argv); 77 | return RUN_ALL_TESTS(); 78 | } -------------------------------------------------------------------------------- /orm_lib/src/RestfulController.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * RestfulController.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include 16 | 17 | using namespace drogon; 18 | 19 | orm::Criteria RestfulController::makeCriteria( 20 | const Json::Value &pJson) noexcept(false) 21 | { 22 | if (!pJson.isArray()) 23 | { 24 | throw std::runtime_error("Json format error"); 25 | } 26 | orm::Criteria ret; 27 | for (auto &orJson : pJson) 28 | { 29 | if (!orJson.isArray()) 30 | { 31 | throw std::runtime_error("Json format error"); 32 | } 33 | orm::Criteria orCriteria; 34 | for (auto &andJson : orJson) 35 | { 36 | if (!andJson.isArray() || andJson.size() != 3) 37 | { 38 | throw std::runtime_error("Json format error"); 39 | } 40 | if (masquerading_) 41 | { 42 | Json::Value newJson(andJson); 43 | auto iter = masqueradingMap_.find(newJson[0].asString()); 44 | if (iter != masqueradingMap_.end()) 45 | { 46 | newJson[0] = masqueradingVector_[iter->second]; 47 | if (!orCriteria) 48 | { 49 | orCriteria = orm::Criteria(newJson); 50 | } 51 | else 52 | { 53 | orCriteria = orCriteria && orm::Criteria(newJson); 54 | } 55 | } 56 | else 57 | { 58 | throw std::runtime_error("Json format error"); 59 | } 60 | } 61 | else 62 | { 63 | if (!orCriteria) 64 | { 65 | orCriteria = orm::Criteria(andJson); 66 | } 67 | else 68 | { 69 | orCriteria = orCriteria && orm::Criteria(andJson); 70 | } 71 | } 72 | } 73 | if (!ret) 74 | { 75 | ret = std::move(orCriteria); 76 | } 77 | else 78 | { 79 | ret = ret || orCriteria; 80 | } 81 | } 82 | return ret; 83 | } -------------------------------------------------------------------------------- /lib/src/ssl_funcs/Md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | ******************************************************* 3 | * brief: md5 encryption 4 | * author: Monkey.Knight 5 | ******************************************************* 6 | */ 7 | 8 | /** 9 | * 10 | * Md5.h 11 | * An Tao 12 | * 13 | * Copyright 2018, An Tao. All rights reserved. 14 | * https://github.com/an-tao/drogon 15 | * Use of this source code is governed by a MIT license 16 | * that can be found in the License file. 17 | * 18 | * Drogon 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | #define BIT_OF_BYTE 8 28 | #define BIT_OF_GROUP 512 29 | #define SRC_DATA_LEN 64 30 | 31 | #define DEF_F(X, Y, Z) ((((X) & (Y)) | ((~X) & (Z)))) 32 | #define DEF_G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z))) 33 | #define DEF_H(X, Y, Z) ((X) ^ (Y) ^ (Z)) 34 | #define DEF_I(X, Y, Z) ((Y) ^ ((X) | (~Z))) 35 | 36 | #define FF(a, b, c, d, Mj, s, ti) \ 37 | (a = b + cycleMoveLeft((a + DEF_F(b, c, d) + Mj + ti), s)); 38 | #define GG(a, b, c, d, Mj, s, ti) \ 39 | (a = b + cycleMoveLeft((a + DEF_G(b, c, d) + Mj + ti), s)); 40 | #define HH(a, b, c, d, Mj, s, ti) \ 41 | (a = b + cycleMoveLeft((a + DEF_H(b, c, d) + Mj + ti), s)); 42 | #define II(a, b, c, d, Mj, s, ti) \ 43 | (a = b + cycleMoveLeft((a + DEF_I(b, c, d) + Mj + ti), s)); 44 | 45 | class Md5Encode 46 | { 47 | public: 48 | struct ParamDynamic 49 | { 50 | uint32_t ua_; 51 | uint32_t ub_; 52 | uint32_t uc_; 53 | uint32_t ud_; 54 | uint32_t va_last_; 55 | uint32_t vb_last_; 56 | uint32_t vc_last_; 57 | uint32_t vd_last_; 58 | }; 59 | 60 | public: 61 | static std::string encode(const char *data, const size_t dataLen); 62 | 63 | protected: 64 | static uint32_t cycleMoveLeft(uint32_t srcNum, int bitNumToMove); 65 | static void roundF(char *data512Ptr, ParamDynamic ¶m); 66 | static void roundG(char *data512Ptr, ParamDynamic ¶m); 67 | static void roundH(char *data512Ptr, ParamDynamic ¶m); 68 | static void roundI(char *data512Ptr, ParamDynamic ¶m); 69 | static void rotationCalculate(char *data512Ptr, ParamDynamic ¶m); 70 | static std::string getHexStr(uint32_t numStr); 71 | static uint32_t fillData(const char *inDataPtr, 72 | int dataByteLen, 73 | char **outDataPtr); 74 | 75 | private: 76 | static const uint32_t kA; 77 | static const uint32_t kB; 78 | static const uint32_t kC; 79 | static const uint32_t kD; 80 | static const uint64_t tiNumInteger; 81 | }; 82 | -------------------------------------------------------------------------------- /drogon_ctl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(ctl_sources 2 | cmd.cc 3 | create.cc 4 | create_controller.cc 5 | create_filter.cc 6 | create_model.cc 7 | create_plugin.cc 8 | create_project.cc 9 | create_view.cc 10 | help.cc 11 | main.cc 12 | press.cc 13 | version.cc) 14 | add_executable(_drogon_ctl 15 | main.cc 16 | cmd.cc 17 | create.cc 18 | create_view.cc) 19 | target_link_libraries(_drogon_ctl ${PROJECT_NAME}) 20 | file(GLOB SCP_LIST ${CMAKE_CURRENT_SOURCE_DIR}/templates/*.csp) 21 | foreach(cspFile ${SCP_LIST}) 22 | message(STATUS "cspFile:" ${cspFile}) 23 | get_filename_component(classname ${cspFile} NAME_WE) 24 | message(STATUS "view classname:" ${classname}) 25 | add_custom_command(OUTPUT ${classname}.h ${classname}.cc 26 | COMMAND _drogon_ctl 27 | ARGS 28 | create 29 | view 30 | ${cspFile} 31 | DEPENDS ${cspFile} 32 | VERBATIM) 33 | set(TEMPL_SRC ${TEMPL_SRC} ${classname}.cc) 34 | endforeach() 35 | add_executable(drogon_ctl ${ctl_sources} ${TEMPL_SRC}) 36 | target_link_libraries(drogon_ctl PRIVATE ${PROJECT_NAME}) 37 | target_include_directories(drogon_ctl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) 38 | add_dependencies(drogon_ctl _drogon_ctl) 39 | if(WIN32) 40 | target_link_libraries(drogon_ctl PRIVATE ws2_32 Rpcrt4) 41 | endif(WIN32) 42 | message(STATUS "bin:" ${INSTALL_BIN_DIR}) 43 | install(TARGETS drogon_ctl RUNTIME DESTINATION ${INSTALL_BIN_DIR}) 44 | if(WIN32) 45 | set(CTL_FILE $) 46 | add_custom_command(TARGET drogon_ctl POST_BUILD 47 | COMMAND ${CMAKE_COMMAND} 48 | -DCTL_FILE=${CTL_FILE} 49 | -DINSTALL_BIN_DIR=${INSTALL_BIN_DIR} 50 | -P 51 | ${CMAKE_CURRENT_SOURCE_DIR}/CopyDlls.cmake) 52 | else(WIN32) 53 | install(CODE "execute_process( \ 54 | COMMAND ${CMAKE_COMMAND} -E create_symlink \ 55 | ./drogon_ctl \ 56 | ./dg_ctl \ 57 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})") 58 | install(FILES "${CMAKE_CURRENT_BINARY_DIR}/dg_ctl" 59 | DESTINATION ${INSTALL_BIN_DIR}) 60 | endif(WIN32) 61 | set(ctl_targets _drogon_ctl drogon_ctl) 62 | set_property(TARGET ${ctl_targets} PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD}) 63 | set_property(TARGET ${ctl_targets} PROPERTY CXX_STANDARD_REQUIRED ON) 64 | set_property(TARGET ${ctl_targets} PROPERTY CXX_EXTENSIONS OFF) 65 | -------------------------------------------------------------------------------- /examples/simple_example_test/WebSocketTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | using namespace drogon; 8 | using namespace std::chrono_literals; 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | auto wsPtr = WebSocketClient::newWebSocketClient("127.0.0.1", 8848); 13 | auto req = HttpRequest::newHttpRequest(); 14 | bool continually = true; 15 | if (argc > 1) 16 | { 17 | if (std::string(argv[1]) == "-t") 18 | continually = false; 19 | } 20 | req->setPath("/chat"); 21 | wsPtr->setMessageHandler([continually](const std::string &message, 22 | const WebSocketClientPtr &wsPtr, 23 | const WebSocketMessageType &type) { 24 | std::cout << "new message:" << message << std::endl; 25 | if (type == WebSocketMessageType::Pong) 26 | { 27 | std::cout << "recv a pong" << std::endl; 28 | if (!continually) 29 | { 30 | app().getLoop()->quit(); 31 | } 32 | } 33 | }); 34 | wsPtr->setConnectionClosedHandler([](const WebSocketClientPtr &wsPtr) { 35 | std::cout << "ws closed!" << std::endl; 36 | }); 37 | wsPtr->connectToServer(req, 38 | [continually](ReqResult r, 39 | const HttpResponsePtr &resp, 40 | const WebSocketClientPtr &wsPtr) { 41 | if (r == ReqResult::Ok) 42 | { 43 | std::cout << "ws connected!" << std::endl; 44 | wsPtr->getConnection()->setPingMessage("", 45 | 2s); 46 | wsPtr->getConnection()->send("hello!"); 47 | } 48 | else 49 | { 50 | std::cout << "ws failed!" << std::endl; 51 | if (!continually) 52 | { 53 | exit(1); 54 | } 55 | } 56 | }); 57 | app().getLoop()->runAfter(5.0, [continually]() { 58 | if (!continually) 59 | { 60 | exit(1); 61 | } 62 | }); 63 | app().run(); 64 | } -------------------------------------------------------------------------------- /lib/src/ListenerManager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * ListenerManager.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include "impl_forwards.h" 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace drogon 26 | { 27 | class ListenerManager : public trantor::NonCopyable 28 | { 29 | public: 30 | void addListener(const std::string &ip, 31 | uint16_t port, 32 | bool useSSL = false, 33 | const std::string &certFile = "", 34 | const std::string &keyFile = ""); 35 | std::vector createListeners( 36 | const HttpAsyncCallback &httpCallback, 37 | const WebSocketNewAsyncCallback &webSocketCallback, 38 | const trantor::ConnectionCallback &connectionCallback, 39 | size_t connectionTimeout, 40 | const std::string &globalCertFile, 41 | const std::string &globalKeyFile, 42 | size_t threadNum, 43 | const std::vector< 44 | std::function> 45 | &syncAdvices); 46 | void startListening(); 47 | ~ListenerManager(); 48 | 49 | trantor::EventLoop *getIOLoop(size_t id) const; 50 | void stopListening(); 51 | std::vector ioLoops_; 52 | 53 | private: 54 | struct ListenerInfo 55 | { 56 | ListenerInfo(const std::string &ip, 57 | uint16_t port, 58 | bool useSSL, 59 | const std::string &certFile, 60 | const std::string &keyFile) 61 | : ip_(ip), 62 | port_(port), 63 | useSSL_(useSSL), 64 | certFile_(certFile), 65 | keyFile_(keyFile) 66 | { 67 | } 68 | std::string ip_; 69 | uint16_t port_; 70 | bool useSSL_; 71 | std::string certFile_; 72 | std::string keyFile_; 73 | }; 74 | std::vector listeners_; 75 | std::vector> servers_; 76 | std::vector> 77 | listeningloopThreads_; 78 | std::shared_ptr ioLoopThreadPoolPtr_; 79 | }; 80 | 81 | } // namespace drogon 82 | -------------------------------------------------------------------------------- /orm_lib/src/postgresql_impl/PostgreSQLResultImpl.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * PostgreSQLResultImpl.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "PostgreSQLResultImpl.h" 16 | #include 17 | #include 18 | 19 | using namespace drogon::orm; 20 | 21 | Result::SizeType PostgreSQLResultImpl::size() const noexcept 22 | { 23 | return result_ ? PQntuples(result_.get()) : 0; 24 | } 25 | 26 | Result::RowSizeType PostgreSQLResultImpl::columns() const noexcept 27 | { 28 | auto ptr = const_cast(result_.get()); 29 | return ptr ? Result::RowSizeType(PQnfields(ptr)) : 0; 30 | } 31 | 32 | const char *PostgreSQLResultImpl::columnName(RowSizeType number) const 33 | { 34 | auto ptr = const_cast(result_.get()); 35 | if (ptr) 36 | { 37 | auto N = PQfname(ptr, int(number)); 38 | assert(N); 39 | return N; 40 | } 41 | throw "nullptr result"; // The program will never execute here 42 | } 43 | 44 | Result::SizeType PostgreSQLResultImpl::affectedRows() const noexcept 45 | { 46 | char *str = PQcmdTuples(result_.get()); 47 | if (str == nullptr || str[0] == '\0') 48 | return 0; 49 | return atol(str); 50 | } 51 | 52 | Result::RowSizeType PostgreSQLResultImpl::columnNumber( 53 | const char colName[]) const 54 | { 55 | auto ptr = const_cast(result_.get()); 56 | if (ptr) 57 | { 58 | auto N = PQfnumber(ptr, colName); 59 | if (N == -1) 60 | throw RangeError(std::string("there is no column named ") + 61 | colName); 62 | return N; 63 | } 64 | throw "nullptr result"; // The program will never execute here 65 | } 66 | 67 | const char *PostgreSQLResultImpl::getValue(SizeType row, 68 | RowSizeType column) const 69 | { 70 | return PQgetvalue(result_.get(), int(row), int(column)); 71 | } 72 | 73 | bool PostgreSQLResultImpl::isNull(SizeType row, RowSizeType column) const 74 | { 75 | return PQgetisnull(result_.get(), int(row), int(column)) != 0; 76 | } 77 | 78 | Result::FieldSizeType PostgreSQLResultImpl::getLength(SizeType row, 79 | RowSizeType column) const 80 | { 81 | return PQgetlength(result_.get(), int(row), int(column)); 82 | } 83 | 84 | int PostgreSQLResultImpl::oid(RowSizeType column) const 85 | { 86 | return PQftype(result_.get(), (int)column); 87 | } 88 | -------------------------------------------------------------------------------- /lib/src/SessionManager.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * SessionManager.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "SessionManager.h" 16 | #include 17 | 18 | using namespace drogon; 19 | 20 | SessionManager::SessionManager(trantor::EventLoop *loop, size_t timeout) 21 | : loop_(loop), timeout_(timeout) 22 | { 23 | assert(timeout_ >= 0); 24 | if (timeout_ > 0) 25 | { 26 | size_t wheelNum = 1; 27 | size_t bucketNum = 0; 28 | if (timeout_ < 500) 29 | { 30 | bucketNum = timeout_ + 1; 31 | } 32 | else 33 | { 34 | auto tmpTimeout = timeout_; 35 | bucketNum = 100; 36 | while (tmpTimeout > 100) 37 | { 38 | ++wheelNum; 39 | tmpTimeout = tmpTimeout / 100; 40 | } 41 | } 42 | sessionMapPtr_ = std::unique_ptr>( 43 | new CacheMap( 44 | loop_, 1.0, wheelNum, bucketNum)); 45 | } 46 | else if (timeout_ == 0) 47 | { 48 | sessionMapPtr_ = std::unique_ptr>( 49 | new CacheMap(loop_, 0, 0, 0)); 50 | } 51 | } 52 | 53 | SessionPtr SessionManager::getSession(const std::string &sessionID, 54 | bool needToSet) 55 | { 56 | assert(!sessionID.empty()); 57 | SessionPtr sessionPtr; 58 | std::lock_guard lock(mapMutex_); 59 | if (sessionMapPtr_->findAndFetch(sessionID, sessionPtr) == false) 60 | { 61 | sessionPtr = 62 | std::shared_ptr(new Session(sessionID, needToSet)); 63 | sessionMapPtr_->insert(sessionID, sessionPtr, timeout_); 64 | return sessionPtr; 65 | } 66 | return sessionPtr; 67 | } 68 | 69 | void SessionManager::changeSessionId(const SessionPtr &sessionPtr) 70 | { 71 | auto oldId = sessionPtr->sessionId(); 72 | auto newId = utils::getUuid(); 73 | sessionPtr->setSessionId(newId); 74 | sessionMapPtr_->insert(newId, sessionPtr, timeout_); 75 | // For requests sent before setting the new session ID to the client, we 76 | // reserve the old session slot for a period of time. 77 | sessionMapPtr_->runAfter(10, [this, oldId = std::move(oldId)]() { 78 | LOG_TRACE << "remove the old slot of the session"; 79 | sessionMapPtr_->erase(oldId); 80 | }); 81 | } -------------------------------------------------------------------------------- /lib/inc/drogon/utils/string_view.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * string_view.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | #if __cplusplus >= 201703L || (defined _MSC_VER && _MSC_VER > 1900) 17 | #include 18 | #else 19 | #include 20 | #include 21 | #endif 22 | 23 | #include 24 | 25 | namespace drogon 26 | { 27 | #if __cplusplus >= 201703L || (defined _MSC_VER && _MSC_VER > 1900) 28 | using std::string_view; 29 | #else 30 | using boost::string_view; 31 | #endif 32 | } // namespace drogon 33 | namespace trantor 34 | { 35 | inline LogStream &operator<<(LogStream &ls, const drogon::string_view &v) 36 | { 37 | ls.append(v.data(), v.length()); 38 | return ls; 39 | } 40 | } // namespace trantor 41 | 42 | #if __cplusplus < 201703L 43 | namespace std 44 | { 45 | template <> 46 | struct hash 47 | { 48 | size_t operator()(const drogon::string_view &__str) const noexcept 49 | { 50 | // Take from the memory header file 51 | //===-------------------------- memory 52 | //------------------------------------===// 53 | // 54 | // The LLVM Compiler Infrastructure 55 | // 56 | // This file is dual licensed under the MIT and the University of 57 | // Illinois Open Source Licenses. See LICENSE.TXT for details. 58 | // 59 | //===----------------------------------------------------------------------===// 60 | const size_t __m = 0x5bd1e995; 61 | const size_t __r = 24; 62 | size_t __h = __str.length(); 63 | auto __len = __h; 64 | const unsigned char *__data = (const unsigned char *)(__str.data()); 65 | for (; __len >= 4; __data += 4, __len -= 4) 66 | { 67 | size_t __k = *((size_t *)__data); 68 | __k *= __m; 69 | __k ^= __k >> __r; 70 | __k *= __m; 71 | __h *= __m; 72 | __h ^= __k; 73 | } 74 | switch (__len) 75 | { 76 | case 3: 77 | __h ^= __data[2] << 16; 78 | case 2: 79 | __h ^= __data[1] << 8; 80 | case 1: 81 | __h ^= __data[0]; 82 | __h *= __m; 83 | } 84 | __h ^= __h >> 13; 85 | __h *= __m; 86 | __h ^= __h >> 15; 87 | return __h; 88 | } 89 | }; 90 | } // namespace std 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /orm_lib/src/DbClientLockFree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * DbClientLockFree.h 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #pragma once 16 | 17 | #include "DbConnection.h" 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | namespace drogon 28 | { 29 | namespace orm 30 | { 31 | class DbClientLockFree : public DbClient, 32 | public std::enable_shared_from_this 33 | { 34 | public: 35 | DbClientLockFree(const std::string &connInfo, 36 | trantor::EventLoop *loop, 37 | ClientType type, 38 | size_t connectionNumberPerLoop); 39 | virtual ~DbClientLockFree() noexcept; 40 | virtual void execSql(const char *sql, 41 | size_t sqlLength, 42 | size_t paraNum, 43 | std::vector &¶meters, 44 | std::vector &&length, 45 | std::vector &&format, 46 | ResultCallback &&rcb, 47 | std::function 48 | &&exceptCallback) override; 49 | virtual std::shared_ptr newTransaction( 50 | const std::function &commitCallback = nullptr) override; 51 | virtual void newTransactionAsync( 52 | const std::function &)> 53 | &callback) override; 54 | virtual bool hasAvailableConnections() const noexcept override; 55 | 56 | private: 57 | std::string connectionInfo_; 58 | trantor::EventLoop *loop_; 59 | DbConnectionPtr newConnection(); 60 | const size_t connectionsNumber_; 61 | std::vector connections_; 62 | std::vector connectionHolders_; 63 | std::unordered_set transSet_; 64 | std::deque> sqlCmdBuffer_; 65 | 66 | std::queue &)>> 67 | transCallbacks_; 68 | 69 | void makeTrans( 70 | const DbConnectionPtr &conn, 71 | std::function &)> &&callback); 72 | 73 | void handleNewTask(const DbConnectionPtr &conn); 74 | #if LIBPQ_SUPPORTS_BATCH_MODE 75 | size_t connectionPos_{0}; // Used for pg batch mode. 76 | #endif 77 | }; 78 | 79 | } // namespace orm 80 | } // namespace drogon 81 | -------------------------------------------------------------------------------- /drogon_ctl/templates/restful_controller_base_h.csp: -------------------------------------------------------------------------------- 1 | <%inc#include "create_model.h" 2 | using namespace drogon_ctl; 3 | %> 4 | /** 5 | * 6 | * [[fileName]]Base.h 7 | * DO NOT EDIT. This file is generated by drogon_ctl automatically. 8 | * Users should implement business logic in the derived class. 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | 16 | <%c++ 17 | auto tableInfo = @@.get("tableInfo"); 18 | auto modelName = tableInfo.get("className"); 19 | $$<<"#include \""<("hasPrimaryKey")==1); 21 | $$<<"using namespace drogon;\n"; 22 | 23 | $$<<"using namespace drogon_model::"<("dbName"); 24 | auto &schema=tableInfo.get("schema"); 25 | if(!schema.empty()) 26 | { 27 | $$<<"::"<>("namespaceVector"); 35 | for(auto &name:namespaceVector) 36 | { 37 | %> 38 | namespace {%name%} 39 | { 40 | <%c++}%> 41 | /** 42 | * @brief this class is created by the drogon_ctl command. 43 | * this class is a restful API controller for reading and writing the [[tableName]] table. 44 | */ 45 | 46 | class [[className]]Base : public RestfulController 47 | { 48 | public: 49 | <%c++if(hasPrimaryKey) 50 | { 51 | %> 52 | void getOne(const HttpRequestPtr &req, 53 | std::function &&callback, 54 | {%modelName%}::PrimaryKeyType &&id); 55 | void updateOne(const HttpRequestPtr &req, 56 | std::function &&callback, 57 | {%modelName%}::PrimaryKeyType &&id); 58 | void deleteOne(const HttpRequestPtr &req, 59 | std::function &&callback, 60 | {%modelName%}::PrimaryKeyType &&id); 61 | <%c++} 62 | %> 63 | void get(const HttpRequestPtr &req, 64 | std::function &&callback); 65 | void create(const HttpRequestPtr &req, 66 | std::function &&callback); 67 | 68 | 69 | // void update(const HttpRequestPtr &req, 70 | // std::function &&callback); 71 | 72 | orm::DbClientPtr getDbClient() 73 | { 74 | return drogon::app().get{%(@@.get("isFastDbClient")?"Fast":"")%}DbClient(dbClientName_); 75 | } 76 | 77 | protected: 78 | /// Ensure that subclasses inherited from this class are instantiated. 79 | [[className]]Base(); 80 | const std::string dbClientName_{"[[dbClientName]]"}; 81 | }; 82 | <%c++ for(size_t i=0;i -------------------------------------------------------------------------------- /lib/src/FiltersFunction.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * FiltersFunction.cc 4 | * An Tao 5 | * 6 | * Copyright 2018, An Tao. All rights reserved. 7 | * https://github.com/an-tao/drogon 8 | * Use of this source code is governed by a MIT license 9 | * that can be found in the License file. 10 | * 11 | * Drogon 12 | * 13 | */ 14 | 15 | #include "FiltersFunction.h" 16 | #include "HttpRequestImpl.h" 17 | #include "HttpResponseImpl.h" 18 | #include "HttpAppFrameworkImpl.h" 19 | #include 20 | 21 | #include 22 | 23 | namespace drogon 24 | { 25 | namespace filters_function 26 | { 27 | static void doFilterChains( 28 | const std::vector> &filters, 29 | size_t index, 30 | const HttpRequestImplPtr &req, 31 | const std::shared_ptr> 32 | &callbackPtr, 33 | std::function &&missCallback) 34 | { 35 | if (index < filters.size()) 36 | { 37 | auto &filter = filters[index]; 38 | filter->doFilter( 39 | req, 40 | [req, callbackPtr](const HttpResponsePtr &res) { 41 | HttpAppFrameworkImpl::instance().callCallback(req, 42 | res, 43 | *callbackPtr); 44 | }, 45 | [=, &filters, missCallback = std::move(missCallback)]() mutable { 46 | doFilterChains(filters, 47 | index + 1, 48 | req, 49 | callbackPtr, 50 | std::move(missCallback)); 51 | }); 52 | } 53 | else 54 | { 55 | missCallback(); 56 | } 57 | } 58 | 59 | std::vector> createFilters( 60 | const std::vector &filterNames) 61 | { 62 | std::vector> filters; 63 | for (auto const &filter : filterNames) 64 | { 65 | auto object_ = DrClassMap::getSingleInstance(filter); 66 | auto filter_ = std::dynamic_pointer_cast(object_); 67 | if (filter_) 68 | filters.push_back(filter_); 69 | else 70 | { 71 | LOG_ERROR << "filter " << filter << " not found"; 72 | } 73 | } 74 | return filters; 75 | } 76 | 77 | void doFilters( 78 | const std::vector> &filters, 79 | const HttpRequestImplPtr &req, 80 | const std::shared_ptr> 81 | &callbackPtr, 82 | std::function &&missCallback) 83 | { 84 | doFilterChains(filters, 0, req, callbackPtr, std::move(missCallback)); 85 | } 86 | 87 | } // namespace filters_function 88 | } // namespace drogon -------------------------------------------------------------------------------- /lib/src/SecureSSLRedirector.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * drogon_plugin_SecureSSLRedirector.cc 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace drogon; 11 | using namespace drogon::plugin; 12 | 13 | void SecureSSLRedirector::initAndStart(const Json::Value &config) 14 | { 15 | if (config.isMember("ssl_redirect_exempt") && 16 | config["ssl_redirect_exempt"].isArray()) 17 | { 18 | std::string regexString; 19 | for (auto &exempt : config["ssl_redirect_exempt"]) 20 | { 21 | assert(exempt.isString()); 22 | regexString.append("(").append(exempt.asString()).append(")|"); 23 | } 24 | if (!regexString.empty()) 25 | { 26 | regexString.resize(regexString.length() - 1); 27 | exemptPegex_ = std::regex(regexString); 28 | regexFlag_ = true; 29 | } 30 | } 31 | secureHost_ = config.get("secure_ssl_host", "").asString(); 32 | app().registerSyncAdvice([this](const HttpRequestPtr &req) { 33 | return this->redirectingAdvice(req); 34 | }); 35 | } 36 | 37 | void SecureSSLRedirector::shutdown() 38 | { 39 | /// Shutdown the plugin 40 | } 41 | 42 | HttpResponsePtr SecureSSLRedirector::redirectingAdvice( 43 | const HttpRequestPtr &req) const 44 | { 45 | if (req->isOnSecureConnection()) 46 | { 47 | return HttpResponsePtr{}; 48 | } 49 | else if (regexFlag_) 50 | { 51 | std::smatch regexResult; 52 | if (std::regex_match(req->path(), regexResult, exemptPegex_)) 53 | { 54 | return HttpResponsePtr{}; 55 | } 56 | else 57 | { 58 | return redirectToSSL(req); 59 | } 60 | } 61 | else 62 | { 63 | return redirectToSSL(req); 64 | } 65 | } 66 | 67 | HttpResponsePtr SecureSSLRedirector::redirectToSSL( 68 | const HttpRequestPtr &req) const 69 | { 70 | if (!secureHost_.empty()) 71 | { 72 | static std::string urlPrefix{"https://" + secureHost_}; 73 | std::string query{urlPrefix + req->path()}; 74 | if (!req->query().empty()) 75 | { 76 | query += "?" + req->query(); 77 | } 78 | return HttpResponse::newRedirectionResponse(query); 79 | } 80 | else 81 | { 82 | const auto &host = req->getHeader("host"); 83 | if (!host.empty()) 84 | { 85 | std::string query{"https://" + host}; 86 | query += req->path(); 87 | if (!req->query().empty()) 88 | { 89 | query += "?" + req->query(); 90 | } 91 | return HttpResponse::newRedirectionResponse(query); 92 | } 93 | else 94 | { 95 | return HttpResponse::newNotFoundResponse(); 96 | } 97 | } 98 | } --------------------------------------------------------------------------------