mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2024-11-14 04:57:21 +01:00
Removed lots of unneeded files.
This commit is contained in:
parent
d2b0ff2e22
commit
13b2863908
4
modules/drogon/drogon/.gitmodules
vendored
4
modules/drogon/drogon/.gitmodules
vendored
@ -1,4 +0,0 @@
|
||||
[submodule "trantor"]
|
||||
path = trantor
|
||||
url = https://github.com/an-tao/trantor.git
|
||||
|
@ -1,80 +0,0 @@
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: xenial
|
||||
- os: osx
|
||||
osx_image: xcode12.2
|
||||
|
||||
sudo: required
|
||||
|
||||
language: cpp
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- xenial
|
||||
- sourceline: 'deb http://archive.ubuntu.com/ubuntu xenial main'
|
||||
- sourceline: 'ppa:mhier/libboost-latest'
|
||||
packages:
|
||||
- gcc
|
||||
- g++
|
||||
- libjsoncpp-dev
|
||||
- uuid-dev
|
||||
- zlib1g-dev
|
||||
- postgresql-server-dev-10
|
||||
- openssl
|
||||
- libssl-dev
|
||||
- libsqlite3-dev
|
||||
- mariadb-client
|
||||
- mariadb-server
|
||||
- build-essential
|
||||
- cmake
|
||||
- boost1.67
|
||||
- libbrotli-dev
|
||||
homebrew:
|
||||
packages:
|
||||
- jsoncpp
|
||||
- ossp-uuid
|
||||
- openssl
|
||||
- cmake
|
||||
- libtool
|
||||
- lz4
|
||||
- mariadb
|
||||
- sqlite3
|
||||
update: true
|
||||
mariadb: '10.0'
|
||||
|
||||
before_install:
|
||||
- wget https://github.com/google/googletest/archive/release-1.10.0.tar.gz
|
||||
- tar xf release-1.10.0.tar.gz
|
||||
- cd googletest-release-1.10.0
|
||||
- cmake .
|
||||
- make
|
||||
- sudo make install
|
||||
- cd -
|
||||
|
||||
before_script:
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
brew tap homebrew/services;
|
||||
brew services restart postgresql;
|
||||
brew services start mariadb;
|
||||
sleep 4;
|
||||
mariadb -e "CREATE USER 'root'@'localhost' IDENTIFIED BY ''";
|
||||
mariadb -e "SET PASSWORD FOR 'root'@'localhost' = PASSWORD('')";
|
||||
mariadb -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost'";
|
||||
mariadb -e "FLUSH PRIVILEGES";
|
||||
brew services restart mariadb;
|
||||
sleep 4;
|
||||
psql -c 'create user postgres superuser;' postgres;
|
||||
fi
|
||||
|
||||
services:
|
||||
- postgresql
|
||||
- mysql
|
||||
|
||||
script:
|
||||
- ./build.sh -t
|
||||
- ./test.sh -t
|
||||
- sudo rm /usr/local/lib/libtrantor.a && sudo rm /usr/local/lib/libdrogon.a
|
||||
- ./build.sh -tshared
|
||||
- ./test.sh -t
|
@ -1,574 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(drogon)
|
||||
|
||||
message(STATUS "compiler: " ${CMAKE_CXX_COMPILER_ID})
|
||||
|
||||
# If your cross compile is failing, you should set
|
||||
# CMAKE_SYSTEM_NAME in your toolchain file
|
||||
if (NOT CMAKE_CROSSCOMPILING)
|
||||
set(BUILD_PROGRAMS ON)
|
||||
else ()
|
||||
set(BUILD_PROGRAMS OFF)
|
||||
endif ()
|
||||
|
||||
option(BUILD_CTL "Build drogon_ctl" ${BUILD_PROGRAMS})
|
||||
option(BUILD_EXAMPLES "Build examples" ${BUILD_PROGRAMS})
|
||||
option(BUILD_ORM "Build orm" ON)
|
||||
option(COZ_PROFILING "Use coz for profiling" OFF)
|
||||
option(BUILD_DROGON_SHARED "Build drogon as a shared lib" OFF)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
CMAKE_DEPENDENT_OPTION(BUILD_POSTGRESQL "Build with postgresql support" ON "BUILD_ORM" OFF)
|
||||
CMAKE_DEPENDENT_OPTION(LIBPQ_BATCH_MODE "Use batch mode for libpq" ON "BUILD_POSTGRESQL" OFF)
|
||||
CMAKE_DEPENDENT_OPTION(BUILD_MYSQL "Build with mysql support" ON "BUILD_ORM" OFF)
|
||||
CMAKE_DEPENDENT_OPTION(BUILD_SQLITE "Build with sqlite3 support" ON "BUILD_ORM" OFF)
|
||||
CMAKE_DEPENDENT_OPTION(BUILD_REDIS "Build with redis support" ON "BUILD_ORM" OFF)
|
||||
|
||||
set(DROGON_MAJOR_VERSION 1)
|
||||
set(DROGON_MINOR_VERSION 6)
|
||||
set(DROGON_PATCH_VERSION 0)
|
||||
set(DROGON_VERSION
|
||||
${DROGON_MAJOR_VERSION}.${DROGON_MINOR_VERSION}.${DROGON_PATCH_VERSION})
|
||||
set(DROGON_VERSION_STRING "${DROGON_VERSION}")
|
||||
|
||||
# Offer the user the choice of overriding the installation directories
|
||||
set(INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries")
|
||||
set(INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables")
|
||||
set(INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files")
|
||||
set(DEF_INSTALL_DROGON_CMAKE_DIR lib/cmake/Drogon)
|
||||
set(INSTALL_DROGON_CMAKE_DIR ${DEF_INSTALL_DROGON_CMAKE_DIR}
|
||||
CACHE PATH "Installation directory for cmake files")
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
# Force MSVC to use UTF-8 because that's what we use. Otherwise it uses
|
||||
# the default of whatever Windows sets and causes encoding issues.
|
||||
message(STATUS "You are using MSVC. Forceing to use UTF-8")
|
||||
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
|
||||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
|
||||
endif ()
|
||||
|
||||
if (BUILD_DROGON_SHARED)
|
||||
set(BUILD_TRANTOR_SHARED TRUE)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||
find_package(Threads)
|
||||
# set(BUILD_EXAMPLES FALSE)
|
||||
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES
|
||||
"${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}" isSystemDir)
|
||||
if ("${isSystemDir}" STREQUAL "-1")
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}")
|
||||
endif ("${isSystemDir}" STREQUAL "-1")
|
||||
add_library(${PROJECT_NAME} SHARED)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
VERSION ${DROGON_VERSION}
|
||||
SOVERSION ${DROGON_MAJOR_VERSION})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Threads::Threads)
|
||||
if (WIN32)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Rpcrt4 ws2_32 crypt32 Advapi32)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
# Ignore MSVC C4251 and C4275 warning of exporting std objects with no dll export
|
||||
# We export class to facilitate maintenance, thus if you compile
|
||||
# drogon on windows as a shared library, you will need to use
|
||||
# exact same compiler for drogon and your app.
|
||||
target_compile_options(${PROJECT_NAME} PUBLIC /wd4251 /wd4275)
|
||||
endif ()
|
||||
endif ()
|
||||
else (BUILD_DROGON_SHARED)
|
||||
add_library(${PROJECT_NAME} STATIC)
|
||||
endif (BUILD_DROGON_SHARED)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Werror)
|
||||
endif ()
|
||||
|
||||
include(GenerateExportHeader)
|
||||
generate_export_header(${PROJECT_NAME} EXPORT_FILE_NAME ${CMAKE_CURRENT_BINARY_DIR}/exports/drogon/exports.h)
|
||||
|
||||
include(cmake/DrogonUtilities.cmake)
|
||||
include(cmake/ParseAndAddDrogonTests.cmake)
|
||||
include(CheckIncludeFileCXX)
|
||||
|
||||
check_include_file_cxx(any HAS_ANY)
|
||||
check_include_file_cxx(string_view HAS_STRING_VIEW)
|
||||
check_include_file_cxx(coroutine HAS_COROUTINE)
|
||||
if (HAS_ANY AND HAS_STRING_VIEW AND HAS_COROUTINE)
|
||||
set(DROGON_CXX_STANDARD 20)
|
||||
elseif (HAS_ANY AND HAS_STRING_VIEW)
|
||||
set(DROGON_CXX_STANDARD 17)
|
||||
else ()
|
||||
set(DROGON_CXX_STANDARD 14)
|
||||
endif ()
|
||||
|
||||
target_include_directories(
|
||||
${PROJECT_NAME}
|
||||
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib/inc>
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/orm_lib/inc>
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/nosql_lib/redis/inc>
|
||||
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/trantor>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/exports>
|
||||
$<INSTALL_INTERFACE:${INSTALL_INCLUDE_DIR}>)
|
||||
|
||||
if (WIN32)
|
||||
target_include_directories(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/third_party/mman-win32>)
|
||||
endif (WIN32)
|
||||
|
||||
add_subdirectory(trantor)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC trantor)
|
||||
|
||||
if (NOT WIN32)
|
||||
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE dl)
|
||||
endif (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
||||
else (NOT WIN32)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE shlwapi)
|
||||
endif (NOT WIN32)
|
||||
|
||||
if (DROGON_CXX_STANDARD EQUAL 14)
|
||||
# With C++14, use boost to support any and string_view
|
||||
message(STATUS "use c++14")
|
||||
find_package(Boost 1.61.0 REQUIRED)
|
||||
message(STATUS "boost include dir:" ${Boost_INCLUDE_DIR})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::boost)
|
||||
list(APPEND INCLUDE_DIRS_FOR_DYNAMIC_VIEW ${Boost_INCLUDE_DIR})
|
||||
elseif (DROGON_CXX_STANDARD EQUAL 17)
|
||||
message(STATUS "use c++17")
|
||||
else ()
|
||||
message(STATUS "use c++20")
|
||||
endif ()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules/)
|
||||
|
||||
# jsoncpp
|
||||
find_package(Jsoncpp REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Jsoncpp_lib)
|
||||
list(APPEND INCLUDE_DIRS_FOR_DYNAMIC_VIEW ${JSONCPP_INCLUDE_DIRS})
|
||||
|
||||
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
|
||||
AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD"
|
||||
AND NOT WIN32)
|
||||
find_package(UUID REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE UUID_lib)
|
||||
|
||||
try_compile(normal_uuid ${CMAKE_BINARY_DIR}/cmaketest
|
||||
${PROJECT_SOURCE_DIR}/cmake/tests/normal_uuid_lib_test.cc
|
||||
LINK_LIBRARIES UUID_lib)
|
||||
try_compile(ossp_uuid ${CMAKE_BINARY_DIR}/cmaketest
|
||||
${PROJECT_SOURCE_DIR}/cmake/tests/ossp_uuid_lib_test.cc
|
||||
LINK_LIBRARIES UUID_lib)
|
||||
if (normal_uuid)
|
||||
add_definitions(-DUSE_OSSP_UUID=0)
|
||||
elseif (ossp_uuid)
|
||||
add_definitions(-DUSE_OSSP_UUID=1)
|
||||
else ()
|
||||
message(FATAL_ERROR "uuid lib error")
|
||||
endif ()
|
||||
endif (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
|
||||
AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD"
|
||||
AND NOT WIN32)
|
||||
|
||||
find_package(Brotli)
|
||||
if (Brotli_FOUND)
|
||||
message(STATUS "Brotli found")
|
||||
add_definitions(-DUSE_BROTLI)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Brotli_lib)
|
||||
endif (Brotli_FOUND)
|
||||
|
||||
set(DROGON_SOURCES
|
||||
lib/src/AOPAdvice.cc
|
||||
lib/src/CacheFile.cc
|
||||
lib/src/ConfigLoader.cc
|
||||
lib/src/Cookie.cc
|
||||
lib/src/DrClassMap.cc
|
||||
lib/src/DrTemplateBase.cc
|
||||
lib/src/FiltersFunction.cc
|
||||
lib/src/HttpAppFrameworkImpl.cc
|
||||
lib/src/HttpBinder.cc
|
||||
lib/src/HttpClientImpl.cc
|
||||
lib/src/HttpControllersRouter.cc
|
||||
lib/src/HttpFileImpl.cc
|
||||
lib/src/HttpFileUploadRequest.cc
|
||||
lib/src/HttpRequestImpl.cc
|
||||
lib/src/HttpRequestParser.cc
|
||||
lib/src/HttpResponseImpl.cc
|
||||
lib/src/HttpResponseParser.cc
|
||||
lib/src/HttpServer.cc
|
||||
lib/src/HttpSimpleControllersRouter.cc
|
||||
lib/src/HttpUtils.cc
|
||||
lib/src/HttpViewData.cc
|
||||
lib/src/IntranetIpFilter.cc
|
||||
lib/src/ListenerManager.cc
|
||||
lib/src/LocalHostFilter.cc
|
||||
lib/src/MultiPart.cc
|
||||
lib/src/NotFound.cc
|
||||
lib/src/PluginsManager.cc
|
||||
lib/src/SecureSSLRedirector.cc
|
||||
lib/src/AccessLogger.cc
|
||||
lib/src/SessionManager.cc
|
||||
lib/src/StaticFileRouter.cc
|
||||
lib/src/TaskTimeoutFlag.cc
|
||||
lib/src/Utilities.cc
|
||||
lib/src/WebSocketClientImpl.cc
|
||||
lib/src/WebSocketConnectionImpl.cc
|
||||
lib/src/WebsocketControllersRouter.cc)
|
||||
|
||||
if (NOT WIN32)
|
||||
set(DROGON_SOURCES ${DROGON_SOURCES} lib/src/SharedLibManager.cc)
|
||||
else (NOT WIN32)
|
||||
set(DROGON_SOURCES ${DROGON_SOURCES} third_party/mman-win32/mman.c)
|
||||
endif (NOT WIN32)
|
||||
|
||||
if (BUILD_POSTGRESQL)
|
||||
# find postgres
|
||||
find_package(pg)
|
||||
if (pg_FOUND)
|
||||
message(STATUS "libpq inc path:" ${PG_INCLUDE_DIRS})
|
||||
message(STATUS "libpq lib:" ${PG_LIBRARIES})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE pg_lib)
|
||||
set(DROGON_SOURCES ${DROGON_SOURCES}
|
||||
orm_lib/src/postgresql_impl/PostgreSQLResultImpl.cc)
|
||||
if (LIBPQ_BATCH_MODE)
|
||||
try_compile(libpq_supports_batch ${CMAKE_BINARY_DIR}/cmaketest
|
||||
${PROJECT_SOURCE_DIR}/cmake/tests/test_libpq_batch_mode.cc
|
||||
LINK_LIBRARIES ${PostgreSQL_LIBRARIES}
|
||||
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${PostgreSQL_INCLUDE_DIR}")
|
||||
endif (LIBPQ_BATCH_MODE)
|
||||
if (libpq_supports_batch)
|
||||
message(STATUS "The libpq supports batch mode")
|
||||
option(LIBPQ_SUPPORTS_BATCH_MODE "libpq batch mode" ON)
|
||||
set(DROGON_SOURCES ${DROGON_SOURCES}
|
||||
orm_lib/src/postgresql_impl/PgBatchConnection.cc)
|
||||
else (libpq_supports_batch)
|
||||
option(LIBPQ_SUPPORTS_BATCH_MODE "libpq batch mode" OFF)
|
||||
set(DROGON_SOURCES ${DROGON_SOURCES}
|
||||
orm_lib/src/postgresql_impl/PgConnection.cc)
|
||||
endif (libpq_supports_batch)
|
||||
endif (pg_FOUND)
|
||||
endif (BUILD_POSTGRESQL)
|
||||
|
||||
if (BUILD_MYSQL)
|
||||
# Find mysql, only mariadb client liberary is supported
|
||||
find_package(MySQL)
|
||||
if (MySQL_FOUND)
|
||||
message(STATUS "Ok! We find the mariadb!")
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE MySQL_lib)
|
||||
set(DROGON_SOURCES ${DROGON_SOURCES}
|
||||
orm_lib/src/mysql_impl/MysqlConnection.cc
|
||||
orm_lib/src/mysql_impl/MysqlResultImpl.cc)
|
||||
endif (MySQL_FOUND)
|
||||
endif (BUILD_MYSQL)
|
||||
|
||||
if (BUILD_SQLITE)
|
||||
# Find sqlite3.
|
||||
find_package(SQLite3)
|
||||
if (SQLite3_FOUND)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE SQLite3_lib)
|
||||
set(DROGON_SOURCES ${DROGON_SOURCES}
|
||||
orm_lib/src/sqlite3_impl/Sqlite3Connection.cc
|
||||
orm_lib/src/sqlite3_impl/Sqlite3ResultImpl.cc)
|
||||
endif (SQLite3_FOUND)
|
||||
endif (BUILD_SQLITE)
|
||||
|
||||
if (BUILD_REDIS)
|
||||
find_package(Hiredis)
|
||||
if (Hiredis_FOUND)
|
||||
add_definitions(-DUSE_REDIS)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Hiredis_lib)
|
||||
set(DROGON_SOURCES
|
||||
${DROGON_SOURCES}
|
||||
nosql_lib/redis/src/RedisClientImpl.cc
|
||||
nosql_lib/redis/src/RedisConnection.cc
|
||||
nosql_lib/redis/src/RedisResult.cc
|
||||
nosql_lib/redis/src/RedisClientLockFree.cc
|
||||
nosql_lib/redis/src/RedisClientManager.cc
|
||||
nosql_lib/redis/src/RedisTransactionImpl.cc)
|
||||
|
||||
endif (Hiredis_FOUND)
|
||||
endif (BUILD_REDIS)
|
||||
|
||||
if (NOT Hiredis_FOUND)
|
||||
set(DROGON_SOURCES
|
||||
${DROGON_SOURCES}
|
||||
lib/src/RedisClientSkipped.cc
|
||||
lib/src/RedisResultSkipped.cc
|
||||
lib/src/RedisClientManagerSkipped.cc)
|
||||
endif (NOT Hiredis_FOUND)
|
||||
|
||||
if (BUILD_TESTING)
|
||||
add_subdirectory(nosql_lib/redis/tests)
|
||||
endif (BUILD_TESTING)
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ZLIB::ZLIB)
|
||||
|
||||
find_package(OpenSSL)
|
||||
if (OpenSSL_FOUND)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE OpenSSL::SSL OpenSSL::Crypto)
|
||||
else (OpenSSL_FOUND)
|
||||
set(DROGON_SOURCES ${DROGON_SOURCES} lib/src/ssl_funcs/Md5.cc
|
||||
lib/src/ssl_funcs/Sha1.cc)
|
||||
endif (OpenSSL_FOUND)
|
||||
|
||||
execute_process(COMMAND "git" rev-parse HEAD
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE GIT_SHA1
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/cmake/templates/version.h.in"
|
||||
"${PROJECT_SOURCE_DIR}/lib/inc/drogon/version.h" @ONLY)
|
||||
|
||||
if (DROGON_CXX_STANDARD EQUAL 20)
|
||||
option(USE_COROUTINE "Enable C++20 coroutine support" ON)
|
||||
else (DROGON_CXX_STANDARD EQUAL 20)
|
||||
option(USE_COROUTINE "Enable C++20 coroutine support" OFF)
|
||||
endif (DROGON_CXX_STANDARD EQUAL 20)
|
||||
|
||||
if (BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif (BUILD_EXAMPLES)
|
||||
|
||||
if (BUILD_CTL)
|
||||
add_subdirectory(drogon_ctl)
|
||||
endif (BUILD_CTL)
|
||||
|
||||
if (COZ_PROFILING)
|
||||
find_package(coz-profiler REQUIRED)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE -DCOZ_PROFILING=1)
|
||||
# If linked will not need to be ran with `coz run --- [executable]` to run the
|
||||
# profiler, but drogon_ctl currently won't build because it doesn't find debug
|
||||
# information while trying to generate it's own sources
|
||||
# target_link_libraries(${PROJECT_NAME} PUBLIC coz::coz)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${COZ_INCLUDE_DIRS})
|
||||
endif (COZ_PROFILING)
|
||||
|
||||
set(DROGON_SOURCES
|
||||
${DROGON_SOURCES}
|
||||
orm_lib/src/ArrayParser.cc
|
||||
orm_lib/src/Criteria.cc
|
||||
orm_lib/src/DbClient.cc
|
||||
orm_lib/src/DbClientImpl.cc
|
||||
orm_lib/src/DbClientLockFree.cc
|
||||
orm_lib/src/DbConnection.cc
|
||||
orm_lib/src/Exception.cc
|
||||
orm_lib/src/Field.cc
|
||||
orm_lib/src/Result.cc
|
||||
orm_lib/src/Row.cc
|
||||
orm_lib/src/SqlBinder.cc
|
||||
orm_lib/src/TransactionImpl.cc
|
||||
orm_lib/src/RestfulController.cc)
|
||||
if (pg_FOUND OR MySQL_FOUND OR SQLite3_FOUND)
|
||||
set(DROGON_SOURCES
|
||||
${DROGON_SOURCES}
|
||||
orm_lib/src/DbClientManager.cc)
|
||||
else (pg_FOUND OR MySQL_FOUND OR SQLite3_FOUND)
|
||||
set(DROGON_SOURCES ${DROGON_SOURCES} lib/src/DbClientManagerSkipped.cc)
|
||||
endif (pg_FOUND OR MySQL_FOUND OR SQLite3_FOUND)
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE ${DROGON_SOURCES})
|
||||
|
||||
set_target_properties(${PROJECT_NAME}
|
||||
PROPERTIES CXX_STANDARD ${DROGON_CXX_STANDARD})
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD_REQUIRED ON)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_EXTENSIONS OFF)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES EXPORT_NAME Drogon)
|
||||
|
||||
if (pg_FOUND OR MySQL_FOUND OR SQLite3_FOUND)
|
||||
if (pg_FOUND)
|
||||
option(USE_POSTGRESQL "Enable PostgreSQL" ON)
|
||||
else (pg_FOUND)
|
||||
option(USE_POSTGRESQL "Disable PostgreSQL" OFF)
|
||||
endif (pg_FOUND)
|
||||
|
||||
if (MySQL_FOUND)
|
||||
option(USE_MYSQL "Enable Mysql" ON)
|
||||
else (MySQL_FOUND)
|
||||
option(USE_MYSQL "DisableMysql" OFF)
|
||||
endif (MySQL_FOUND)
|
||||
|
||||
if (SQLite3_FOUND)
|
||||
option(USE_SQLITE3 "Enable Sqlite3" ON)
|
||||
else (SQLite3_FOUND)
|
||||
option(USE_SQLITE3 "Disable Sqlite3" OFF)
|
||||
endif (SQLite3_FOUND)
|
||||
endif (pg_FOUND OR MySQL_FOUND OR SQLite3_FOUND)
|
||||
|
||||
set(COMPILER_COMMAND ${CMAKE_CXX_COMPILER})
|
||||
set(COMPILER_ID ${CMAKE_CXX_COMPILER_ID})
|
||||
|
||||
if (CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} _type)
|
||||
if (_type STREQUAL release)
|
||||
set(COMPILATION_FLAGS "${CMAKE_CXX_FLAGS_RELEASE} -std=c++")
|
||||
elseif (_type STREQUAL debug)
|
||||
set(COMPILATION_FLAGS "${CMAKE_CXX_FLAGS_DEBUG} -std=c++")
|
||||
else ()
|
||||
set(COMPILATION_FLAGS "-std=c++")
|
||||
endif ()
|
||||
else (CMAKE_BUILD_TYPE)
|
||||
set(COMPILATION_FLAGS "-std=c++")
|
||||
endif (CMAKE_BUILD_TYPE)
|
||||
|
||||
list(APPEND INCLUDE_DIRS_FOR_DYNAMIC_VIEW
|
||||
"${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR}")
|
||||
list(REMOVE_DUPLICATES INCLUDE_DIRS_FOR_DYNAMIC_VIEW)
|
||||
set(INS_STRING "")
|
||||
foreach (loop_var ${INCLUDE_DIRS_FOR_DYNAMIC_VIEW})
|
||||
set(INS_STRING "${INS_STRING} -I${loop_var}")
|
||||
endforeach (loop_var)
|
||||
|
||||
set(INCLUDING_DIRS ${INS_STRING})
|
||||
|
||||
configure_file(${PROJECT_SOURCE_DIR}/cmake/templates/config.h.in
|
||||
${PROJECT_BINARY_DIR}/drogon/config.h @ONLY)
|
||||
|
||||
if (BUILD_TESTING)
|
||||
message(STATUS "Building tests")
|
||||
enable_testing()
|
||||
add_subdirectory(lib/tests)
|
||||
if (pg_FOUND)
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/postgresql_impl/test)
|
||||
endif (pg_FOUND)
|
||||
if (MySQL_FOUND)
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/mysql_impl/test)
|
||||
endif (MySQL_FOUND)
|
||||
if (SQLite3_FOUND)
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/sqlite3_impl/test)
|
||||
endif (SQLite3_FOUND)
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/tests)
|
||||
endif (BUILD_TESTING)
|
||||
|
||||
# Installation
|
||||
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
EXPORT DrogonTargets
|
||||
RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
|
||||
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" COMPONENT lib
|
||||
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT lib)
|
||||
|
||||
set(DROGON_HEADERS
|
||||
lib/inc/drogon/Attribute.h
|
||||
lib/inc/drogon/CacheMap.h
|
||||
lib/inc/drogon/Cookie.h
|
||||
lib/inc/drogon/DrClassMap.h
|
||||
lib/inc/drogon/DrObject.h
|
||||
lib/inc/drogon/DrTemplate.h
|
||||
lib/inc/drogon/DrTemplateBase.h
|
||||
lib/inc/drogon/HttpAppFramework.h
|
||||
lib/inc/drogon/HttpBinder.h
|
||||
lib/inc/drogon/HttpClient.h
|
||||
lib/inc/drogon/HttpController.h
|
||||
lib/inc/drogon/HttpFilter.h
|
||||
lib/inc/drogon/HttpRequest.h
|
||||
lib/inc/drogon/HttpResponse.h
|
||||
lib/inc/drogon/HttpSimpleController.h
|
||||
lib/inc/drogon/HttpTypes.h
|
||||
lib/inc/drogon/HttpViewData.h
|
||||
lib/inc/drogon/IntranetIpFilter.h
|
||||
lib/inc/drogon/IOThreadStorage.h
|
||||
lib/inc/drogon/LocalHostFilter.h
|
||||
lib/inc/drogon/MultiPart.h
|
||||
lib/inc/drogon/NotFound.h
|
||||
lib/inc/drogon/Session.h
|
||||
lib/inc/drogon/UploadFile.h
|
||||
lib/inc/drogon/WebSocketClient.h
|
||||
lib/inc/drogon/WebSocketConnection.h
|
||||
lib/inc/drogon/WebSocketController.h
|
||||
lib/inc/drogon/drogon.h
|
||||
lib/inc/drogon/version.h
|
||||
lib/inc/drogon/drogon_callbacks.h
|
||||
lib/inc/drogon/PubSubService.h
|
||||
lib/inc/drogon/drogon_test.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/exports/drogon/exports.h)
|
||||
install(FILES ${DROGON_HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR}/drogon)
|
||||
|
||||
set(ORM_HEADERS
|
||||
orm_lib/inc/drogon/orm/ArrayParser.h
|
||||
orm_lib/inc/drogon/orm/Criteria.h
|
||||
orm_lib/inc/drogon/orm/DbClient.h
|
||||
orm_lib/inc/drogon/orm/DbTypes.h
|
||||
orm_lib/inc/drogon/orm/Exception.h
|
||||
orm_lib/inc/drogon/orm/Field.h
|
||||
orm_lib/inc/drogon/orm/FunctionTraits.h
|
||||
orm_lib/inc/drogon/orm/Mapper.h
|
||||
orm_lib/inc/drogon/orm/CoroMapper.h
|
||||
orm_lib/inc/drogon/orm/Result.h
|
||||
orm_lib/inc/drogon/orm/ResultIterator.h
|
||||
orm_lib/inc/drogon/orm/Row.h
|
||||
orm_lib/inc/drogon/orm/RowIterator.h
|
||||
orm_lib/inc/drogon/orm/SqlBinder.h
|
||||
orm_lib/inc/drogon/orm/RestfulController.h)
|
||||
install(FILES ${ORM_HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/orm)
|
||||
|
||||
set(NOSQL_HEADERS nosql_lib/redis/inc/drogon/nosql/RedisClient.h
|
||||
nosql_lib/redis/inc/drogon/nosql/RedisResult.h
|
||||
nosql_lib/redis/inc/drogon/nosql/RedisException.h)
|
||||
install(FILES ${NOSQL_HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/nosql)
|
||||
|
||||
set(DROGON_UTIL_HEADERS
|
||||
lib/inc/drogon/utils/FunctionTraits.h
|
||||
lib/inc/drogon/utils/Utilities.h
|
||||
lib/inc/drogon/utils/any.h
|
||||
lib/inc/drogon/utils/string_view.h
|
||||
lib/inc/drogon/utils/optional.h
|
||||
lib/inc/drogon/utils/coroutine.h
|
||||
lib/inc/drogon/utils/HttpConstraint.h
|
||||
lib/inc/drogon/utils/OStringStream.h)
|
||||
install(FILES ${DROGON_UTIL_HEADERS}
|
||||
DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/utils)
|
||||
|
||||
set(DROGON_PLUGIN_HEADERS lib/inc/drogon/plugins/Plugin.h
|
||||
lib/inc/drogon/plugins/SecureSSLRedirector.h
|
||||
lib/inc/drogon/plugins/AccessLogger.h)
|
||||
install(FILES ${DROGON_PLUGIN_HEADERS}
|
||||
DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/plugins)
|
||||
|
||||
source_group("Public API"
|
||||
FILES
|
||||
${DROGON_HEADERS}
|
||||
${ORM_HEADERS}
|
||||
${DROGON_UTIL_HEADERS}
|
||||
${DROGON_PLUGIN_HEADERS}
|
||||
${NOSQL_HEADERS})
|
||||
|
||||
# Export the package for use from the build-tree (this registers the build-tree
|
||||
# with a global cmake-registry) export(PACKAGE Drogon)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
# ... for the install tree
|
||||
configure_package_config_file(
|
||||
cmake/templates/DrogonConfig.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/DrogonConfig.cmake
|
||||
INSTALL_DESTINATION
|
||||
${INSTALL_DROGON_CMAKE_DIR})
|
||||
|
||||
# version
|
||||
write_basic_package_version_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/DrogonConfigVersion.cmake
|
||||
VERSION ${DROGON_VERSION}
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
|
||||
# Install the DrogonConfig.cmake and DrogonConfigVersion.cmake
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/DrogonConfig.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/DrogonConfigVersion.cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindUUID.cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindJsoncpp.cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindSQLite3.cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindMySQL.cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/Findpg.cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindBrotli.cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/Findcoz-profiler.cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindHiredis.cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/DrogonUtilities.cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/ParseAndAddDrogonTests.cmake"
|
||||
DESTINATION "${INSTALL_DROGON_CMAKE_DIR}"
|
||||
COMPONENT dev)
|
||||
|
||||
# Install the export set for use with the install-tree
|
||||
install(EXPORT DrogonTargets
|
||||
DESTINATION "${INSTALL_DROGON_CMAKE_DIR}"
|
||||
NAMESPACE Drogon::
|
||||
COMPONENT dev)
|
||||
|
@ -1,78 +0,0 @@
|
||||
# Contributing
|
||||
|
||||
**Drogon** is an open source project at its heart and every contribution is
|
||||
welcome. By participating in this project you agree to stick to common sense and
|
||||
contribute in an overall positive way.
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Fork, then clone the repository: `git clone
|
||||
git@github.com:your-username/drogon.git`
|
||||
1. Follow the [official installation steps on
|
||||
DocsForge](https://drogon.docsforge.com/master/installation/). It’s best to
|
||||
make sure to have the `drogon_ctl` executable in your shell’s `PATH`
|
||||
environment variable in case you use a terminal.
|
||||
|
||||
Now you can create branches, start adding features & bugfixes to the code, and
|
||||
[create pull requests](https://github.com/an-tao/drogon/compare).
|
||||
|
||||
## Pull Requests
|
||||
|
||||
Feel free to [create a pull request](https://github.com/an-tao/drogon/compare)
|
||||
if you think you can contribute to the project. You will be listed as a
|
||||
[contributor](https://github.com/an-tao/drogon/graphs/contributors), agree to
|
||||
this document, and the
|
||||
[LICENSE](https://github.com/an-tao/drogon/blob/master/LICENSE).
|
||||
|
||||
There are also some recommendations you can follow. These aren’t requirements,
|
||||
but they will make the development more straightforward:
|
||||
|
||||
1. If you are unsure about a specific change, have questions, or want to get
|
||||
feedback about a feature you want to introduce, [open a new
|
||||
issue](https://github.com/an-tao/drogon/issues) (please make sure that there
|
||||
is no previous issue about a similar topic).
|
||||
1. You should branch off the current state of the `master` branch, and also
|
||||
merge it into your local branch before creating a pull request if there were
|
||||
other changes introduced in the meantime.
|
||||
1. You can use the following branch names to make your intent clearer:
|
||||
* `bugfix/123-fix-template-parser` when you want to fix a bug in the
|
||||
template parser.
|
||||
* `feature/123-add-l10n-and-i18n` if you want to add localization (l10n) and
|
||||
internationalization (i18n) as a new feature to the project.
|
||||
* If there’s no open issue and no need to open one you can skip the number,
|
||||
and just use the descriptive part: `bugfix/fix-typo-in-docs`.
|
||||
1. Write a brief, but good, and descriptive commit message / pull request title in English,
|
||||
e. g. “Added Internationalization and Localization”.
|
||||
|
||||
If you follow these recommendations your pull request will have more success:
|
||||
|
||||
1. Keep the style consistent to the project, when in doubt refer to the [Google
|
||||
C++ Style Guide](https://google.github.io/styleguide/cppguide.html#C++_Version).
|
||||
1. Please write all comments in English. Comments for new public API introduced by
|
||||
your pull request must be added and written in [Doxygen](http://www.doxygen.nl/) format.
|
||||
1. Format the code with `clang-format` (>= 8.0.0). The configuration is already
|
||||
provided in the `.clang-format` file, just run the `./format.sh` script
|
||||
before submitting your pull request.
|
||||
1. Install [Google Test](https://github.com/google/googletest), and write a test
|
||||
case.
|
||||
1. In case it is a bugfix, it’s best to write a test that breaks in the old
|
||||
version, but works in the new one. This way regressions can be tracked
|
||||
over time.
|
||||
1. If you add a feature, it is best to write the test as if it would be an
|
||||
example how to use the newly introduced feature and to test all major,
|
||||
newly introduced code.
|
||||
|
||||
## Project Maintainers & Collaborators
|
||||
|
||||
In addition to the guidelines mentioned above, collaborators with write access
|
||||
to the repository should also follow these guidelines:
|
||||
|
||||
1. If there are new tests as part of the pull request, you should make sure that
|
||||
they succeed.
|
||||
1. When merging **Pull Requests** you should use the option *Squash & Merge* and
|
||||
chose a descriptive commit message for the bugfix / feature (if not already
|
||||
done by the individual contributor).
|
||||
|
||||
This way the history in the `master` branch will be free of small
|
||||
corrections and easier to follow for people who aren’t engaged in the
|
||||
project on a day-to-day basis.
|
@ -1,837 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.6.0] - 2021-05-15
|
||||
|
||||
### API changes list
|
||||
|
||||
- Add option to set default handler.
|
||||
|
||||
- Add the setTimeout() method to the DbClient class and the RedisClient class.
|
||||
|
||||
- Add the validateCert parameter to the newWebSocketClient method.
|
||||
|
||||
### Changed
|
||||
|
||||
- A few mini changes to drogon_ctl command.
|
||||
|
||||
- Improve the MultiPartParser class.
|
||||
|
||||
- Add GNU -Werror & fix warnings.
|
||||
|
||||
- Enhancements on files part.
|
||||
|
||||
- Add version/soversion to shared library.
|
||||
|
||||
- Disallow coroutines to be resolved as plain subroutine handlers.
|
||||
|
||||
- Send the content-length header even if the body(POST,PUT,OPTIONS,PATCH) is empty.
|
||||
|
||||
- Use make_exception_ptr instead of throw/catch when possible.
|
||||
|
||||
- Remove duplicated inclusion.
|
||||
|
||||
- Print error before terminating in AsyncTask.
|
||||
|
||||
- Allow users to override drogon Find modules.
|
||||
|
||||
- Use two-phase construction for the DbClientImpl and the RedisClientImpl.
|
||||
|
||||
- Add support 'select <db>' for redis.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix a bug of the Transaction class.
|
||||
|
||||
- Copy CoroMapper.h to installation location.
|
||||
|
||||
- Remove the related request from the buffer if it's not sent after the timeout.
|
||||
|
||||
- Fix ORM with SQLite3 not compiling on Arch Linux.
|
||||
|
||||
- Fix an error when constructing RedisClientImpl objects.
|
||||
|
||||
- Fix coroutine frame leak upon assigning to awaitable.
|
||||
|
||||
- Set running flag to true before installing plugins.
|
||||
|
||||
- Fix double free in coroutine exception handling.
|
||||
|
||||
## [1.5.1] - 2021-04-10
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix a bug of reflection failure.
|
||||
|
||||
## [1.5.0] - 2021-04-10
|
||||
|
||||
### API changes list
|
||||
|
||||
- Add option to disable signal handling.
|
||||
|
||||
- Added newFileResponse Support for buffers in memory.
|
||||
|
||||
- Add a method to HttpRequest to set the user_agent header.
|
||||
|
||||
- Catch exceptions thrown by handlers.
|
||||
|
||||
### Changed
|
||||
|
||||
- Add convert method to models.
|
||||
|
||||
- Add Arch Dockerfile.
|
||||
|
||||
- Add Redis support.
|
||||
|
||||
- Print error and exit when IP parsing failed in server startup.
|
||||
|
||||
- Use a canonical way of calling max() function on Windows.
|
||||
|
||||
- Remove an assertion statement in the HttpClientImpl class.
|
||||
|
||||
- Send ping messages by default for WebSockets.
|
||||
|
||||
- Use canonical cmake logic for cross-compilation.
|
||||
|
||||
- set make job count to the number of threads in GitHub Actions workflow.
|
||||
|
||||
- Use lambda instead of std::bind in HttpServer.
|
||||
|
||||
- Add exports macro to allow Shared Library with hidden symbols by default.
|
||||
|
||||
- Remove repeated class names on relationships from the model generator.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix compile warnings in SQL client.
|
||||
|
||||
- Fix compilation errors for the TimeFilter example.
|
||||
|
||||
- Fix build.sh missing nproc error in build for macOS.
|
||||
|
||||
- Fix a bug when creating sqlite3 models.
|
||||
|
||||
- Fix two building corner cases, CMake quality of life improvements.
|
||||
|
||||
- Add CoroMapper to models' friends.
|
||||
|
||||
## [1.4.1] - 2021-03-07
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix a bug of DbClientImpl class that can lead to a crash when database connections are breaking.
|
||||
|
||||
## [1.4.0] - 2021-03-05
|
||||
|
||||
### API changes list
|
||||
|
||||
- Add coroutine support.
|
||||
|
||||
- Add default value interface to SqlBinder for MySQL and PostgreSQL.
|
||||
|
||||
- Support SNI in the HttpClient class.
|
||||
|
||||
- Validate certificate in HttpClient.
|
||||
|
||||
- HttpRequest: add a feature to avoid URL encoding of the path.
|
||||
|
||||
### Changed
|
||||
|
||||
- Handle cross-compiling properly.
|
||||
|
||||
- Lowercase all HTTP headers, add webp and avif types.
|
||||
|
||||
- Modify FindMySQL.cmake
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix an error in the HttpClient class when a response has no content-length.
|
||||
|
||||
- Return 404 or 405 responses correctly.
|
||||
|
||||
- Fix compilation errors on vs2019.
|
||||
|
||||
- Fix stack use after scope error in client_example.
|
||||
|
||||
- Fix the error when the SSL handshake fails.
|
||||
|
||||
## [1.3.0] - 2021-01-16
|
||||
|
||||
### API changes list
|
||||
|
||||
- Add an option for setting float precision in Json string.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix brotli link order.
|
||||
|
||||
- Fix cmake with drogonctl cross-compilation.
|
||||
|
||||
- sqlite3: Insert into stmtsMap_ as string_view.
|
||||
|
||||
- Fix some bugs when creating models via drogon_ctl.
|
||||
|
||||
- Fix an error in sqlite3 ORM generator.
|
||||
|
||||
- Fix an error with missing composite key to sqlite3 ORM generator.
|
||||
|
||||
### Changed
|
||||
|
||||
- Remove the use of std::filesystem to adapt to old compilers.
|
||||
|
||||
- Add github actions.
|
||||
|
||||
- Serve wasm files with the correct MIME type.
|
||||
|
||||
## [1.2.0] - 2020-12-12
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix error when receiving response without content-length header.
|
||||
|
||||
- Fix a stack-overflow error when high concurrency happening on sqlite3.
|
||||
|
||||
- Fix MinGW ORM building by enabling htonll and ntohll.
|
||||
|
||||
### Changed
|
||||
|
||||
- Modify the WebSocketTest controller to create a simple chat room.
|
||||
|
||||
- Add support for OpenBSD.
|
||||
|
||||
- Return 400 if the content-length is invalid.
|
||||
|
||||
- Don't send content type in a 304 response.
|
||||
|
||||
- Add the reuse_port option to app() interface.
|
||||
|
||||
- Add the 'std::optional' support in the SqlBinder class and the Session class.
|
||||
|
||||
- Add implicit page resolving capability.
|
||||
|
||||
## [1.1.0] - 2020-10-31
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix failing to connect to DB if parameters contains spaces.
|
||||
|
||||
- Fix a CMAKE bug when SHARED and EXAMPLES are on.
|
||||
|
||||
- Fix the HttpServer::isWebSocket method.
|
||||
|
||||
- Find MariaDB client library correctly on Ubuntu 20.04.
|
||||
|
||||
- Fix a bug when creating sqlite3 database models.
|
||||
|
||||
- Fix a bug in the Mapper::insertFuture method.
|
||||
|
||||
### Changed
|
||||
|
||||
- Disable TLS1.0/1.1 on HTTPS by default.
|
||||
|
||||
- Use explicit lambda capture lists.
|
||||
|
||||
- Modify the procedure of the app().run() method.
|
||||
|
||||
- Support namespaces when creating view source files.
|
||||
|
||||
- Add --path-to-namespace option to drogon_ctl for creating views.
|
||||
|
||||
- Add the Host and Sec-WebSocket-Version headers when connecting to a websocket server.
|
||||
|
||||
## [1.0.0] - 2020-09-27
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix an issue of simple_reverse_proxy when handling chunked transfer-encoding.
|
||||
|
||||
- Fix a bug when losting connection to MySQL server during query.
|
||||
|
||||
- Remove the expired std::iterator template.
|
||||
|
||||
- Fix a bug when creating models in some special cases.
|
||||
|
||||
### API changes list
|
||||
|
||||
- Modify methods related to headers.
|
||||
|
||||
- Remove the expired std::iterator template.
|
||||
|
||||
- Add getListeners() method to the HttpAppFramework class.
|
||||
|
||||
- Remove the useless method stat() from the PluginBase class.
|
||||
|
||||
- Add ConfigLoader::ConfigLoader(const Json::Value &data).
|
||||
|
||||
### Changed
|
||||
|
||||
- Add support for status code 418.
|
||||
|
||||
- Modify session handling.
|
||||
|
||||
- Modify the FileUpload.csp in simple_example to avoid CORS.
|
||||
|
||||
- remove execution permission on /tmp/drogon.lock.
|
||||
|
||||
## [1.0.0-beta21] - 2020-08-19
|
||||
|
||||
### Changed
|
||||
|
||||
- Modify the Result class in ORM.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix zlib link error on Windows for the latest vcpkg.
|
||||
|
||||
## [1.0.0-beta20] - 2020-08-15
|
||||
|
||||
### API changes list
|
||||
|
||||
- Provide users with a method to change the session ID of a session.
|
||||
|
||||
### Changed
|
||||
|
||||
- Modify parseContentType function.
|
||||
|
||||
- Modify the docker file to build release version in docker.
|
||||
|
||||
- Set session to requests for websockets.
|
||||
|
||||
- Modify parseContentType function.
|
||||
|
||||
- Change the return value type of the mktime() function in models.
|
||||
|
||||
- Fix compilation warning of sprintf function.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix a bug when saving uploaded files on Windows.
|
||||
|
||||
- Fix a MySQL issue when connections are lost.
|
||||
|
||||
- Resolve an issue when sending big files (>=2GB) on Windows.
|
||||
|
||||
- Fix boost::string_view compilation error of MysqlConnection class.
|
||||
|
||||
- Set the response Access-Control-Allow-Headers header correctly for CORS.
|
||||
|
||||
- Fix a bug in drogon_ctl when creating a model, that causes to write source files multiple times.
|
||||
|
||||
## [1.0.0-beta19] - 2020-07-16
|
||||
|
||||
### API changes list
|
||||
|
||||
- Add a method to disable unicode escaping in json string.
|
||||
|
||||
- Add a timeout parameter when sending HTTP requests.
|
||||
|
||||
- Add the getJsonError method.
|
||||
|
||||
### Changed
|
||||
|
||||
- Remove the restriction on the location of layout tags in views.
|
||||
|
||||
- Add a way to set the character set when creating DbClient objects.
|
||||
|
||||
- Make `GET` as the only method for accessing static files.
|
||||
|
||||
- Modify the 404 pages generator.
|
||||
|
||||
- Modify the DbClient class.
|
||||
|
||||
- Optimize the HttpResponse class.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Properly handle chunked encoding requests.
|
||||
|
||||
- Destroy DNS resolver of HttpClient in the correct thread.
|
||||
|
||||
- Add the header <cctype> to resolve build errors in VS2017.
|
||||
|
||||
## [1.0.0-beta18] - 2020-06-14
|
||||
|
||||
### API changes list
|
||||
|
||||
- Add a new joinpoint of AOP for modification on each HTTP response.
|
||||
|
||||
- Add a method for the TERM signal handling.
|
||||
|
||||
- Add getContextRef method to the WebSocketConnection class.
|
||||
|
||||
### Changed
|
||||
|
||||
- Create a class template for publish subscribe pattern.
|
||||
|
||||
- Add contribution recommendations.
|
||||
|
||||
- Send a close message when closing a web socket connection.
|
||||
|
||||
- Add additional formats for getHttpDate function.
|
||||
|
||||
- Make app().run() method callable on a non-main thread.
|
||||
|
||||
- Add digest filter in examples.
|
||||
|
||||
- Use string_view to parse multipart/form-data requests.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix building of ORM on FreeBSD.
|
||||
|
||||
- Fix a Mysql connection error on Windows.
|
||||
|
||||
- Fix a bug in ListenerManager::getIOLoop().
|
||||
|
||||
- Fix the count() method of Mysql ORM.
|
||||
|
||||
- Fix a compilation issue on windows.
|
||||
|
||||
- Fix model generation for PostgreSQL primary keys.
|
||||
|
||||
- Fix a bug with quoted column names in sqlite3 databases.
|
||||
|
||||
## [1.0.0-beta17] - 2020-05-22
|
||||
|
||||
### API changes list
|
||||
|
||||
- Add methods to get DbClient connection status
|
||||
|
||||
### Changed
|
||||
|
||||
- Add causal profiling with coz
|
||||
|
||||
- Add filters on static file locations
|
||||
|
||||
- Pass data from view to its layout container
|
||||
|
||||
- Add additional HttpStatusCodes and implement a custom error handler
|
||||
|
||||
- Modify drogon_ctl to show more compilation information
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix a bug in drogon_ctl (when size of a line is larger than buffer size)
|
||||
|
||||
- Fix a connection bug of MariaDB clients
|
||||
|
||||
## [1.0.0-beta16] - 2020-04-27
|
||||
|
||||
### API changes list
|
||||
|
||||
- Standardize Row and Result api in ORM
|
||||
|
||||
### Changed
|
||||
|
||||
- Add support for brotli compression
|
||||
|
||||
- Parse content-type of HTTP requests
|
||||
|
||||
- Remove non standard macros
|
||||
|
||||
- Support url safe base64 codec
|
||||
|
||||
## [1.0.0-beta15] - 2020-03-28
|
||||
|
||||
### API changes list
|
||||
|
||||
- Modify the Attributes interface of the HttpRequest class
|
||||
|
||||
- Add the getHomePage() method to HttpAppFramework
|
||||
|
||||
### Changed
|
||||
|
||||
- Support br compression files
|
||||
|
||||
- Update Content-Type support for PDF
|
||||
|
||||
- Add support for MSVC 2015
|
||||
|
||||
- Optimize the rendering of HTTP responses
|
||||
|
||||
- Update the Dynamic Views Loading, add the `layout` tag
|
||||
|
||||
- Graceful shutdown
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix error when finding the jsoncpp library
|
||||
|
||||
- Fix the 'many to many' relationship in ORM
|
||||
|
||||
- Fix a bug when creating json responses
|
||||
|
||||
- Fix a bug on filters with WebSocketControllers
|
||||
|
||||
- Fix a fatal bug in the MysqlConnection class
|
||||
|
||||
- Fix crash with partial matched url
|
||||
|
||||
- Fix null jsonObject from newHttpJsonRequest
|
||||
|
||||
## [1.0.0-beta14] - 2020-02-17
|
||||
|
||||
### API changes list
|
||||
|
||||
- None
|
||||
|
||||
### Added
|
||||
|
||||
- Add IOLoop access function
|
||||
|
||||
### Changed
|
||||
|
||||
- Add support for regular expressions when routing
|
||||
|
||||
- Add location configuration for static resources
|
||||
|
||||
- Port drogon to Windows
|
||||
|
||||
- Support 'password' keyword in configuration files
|
||||
|
||||
- Remove get_version.sh
|
||||
|
||||
- Modify dynamic view loading algorithm, add 'layout' tag for view generation.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix an issue of out-of-range (#334)
|
||||
|
||||
- Fix a bug in views generation (#341)
|
||||
|
||||
## [1.0.0-beta13] - 2020-01-04
|
||||
|
||||
### API changes list
|
||||
|
||||
- None
|
||||
|
||||
### Changed
|
||||
|
||||
- Add some unit tests (based on gtest)
|
||||
|
||||
- Add a reverse proxy example
|
||||
|
||||
- Make a patch to support the ossp UUID library
|
||||
|
||||
- Make shared linking possible
|
||||
|
||||
- Add the drogon::OStringStream class
|
||||
|
||||
- Optimize ORM
|
||||
|
||||
- Modify singleton logic of DrClassMap
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix an error in the batch mode of libpq
|
||||
|
||||
- Fix an error when clients use HTTP1.0
|
||||
|
||||
## [1.0.0-beta12] - 2019-11-30
|
||||
|
||||
### Changed
|
||||
|
||||
- Make dg_ctl a symlink
|
||||
|
||||
- Modify some code styles
|
||||
|
||||
- Explicitly set path to '/' for JSESSIONID cookie
|
||||
|
||||
- Handle gzip errors safely
|
||||
|
||||
- Add the SecureSSLRedirector plugin
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix a bug in dg_ctl for creating models of sqlite3
|
||||
|
||||
- Reset the flag used to parse json to false before recycling HttpRequest objects
|
||||
|
||||
## [1.0.0-beta11] - 2019-11-06
|
||||
|
||||
### Changed
|
||||
|
||||
- Delete useless log output
|
||||
|
||||
## [1.0.0-beta10] - 2019-11-04
|
||||
|
||||
### API changes list
|
||||
|
||||
- None
|
||||
|
||||
### Changed
|
||||
|
||||
- Add the headers configuration option for static files
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix(compilation on alpine): Replace u_short alias.
|
||||
|
||||
|
||||
## [1.0.0-beta9] - 2019-10-28
|
||||
|
||||
### API changes list
|
||||
|
||||
- Add interfaces for accessing content of attachments.
|
||||
|
||||
- Add option to disable setting the 404 status code of the custom 404 page.
|
||||
|
||||
- Make user can use any string as a placeholder's name in routing patterns.
|
||||
|
||||
- Add type conversion methods to the HttpRequest and HttpResponse classes.
|
||||
|
||||
### Changed
|
||||
|
||||
- Modify cmake configuration.
|
||||
|
||||
- Modify the quit() method.
|
||||
|
||||
- Implement relationships in ORM.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix size_t underflow of drogon_ctl.
|
||||
|
||||
- Fix some race conditions.
|
||||
|
||||
- Fix a busy loop bug when connections to MySQL server are timeout.
|
||||
|
||||
|
||||
## [1.0.0-beta8] - 2019-10-03
|
||||
|
||||
### API changes list
|
||||
|
||||
- Add length() method to the Field class.
|
||||
|
||||
- Add `as<bool>()` function template specialization to the Field class.
|
||||
|
||||
- Add add attribute store methods to the HttpRequest class.
|
||||
|
||||
- Add the setCustomContentTypeString() method to the HttpRequest class.
|
||||
|
||||
- Add thread storage.
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Use .find('x') instead of .find("x") in a string search.
|
||||
|
||||
- Add the ability to create restful API controllers.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix a bug of creating models for MySQL.
|
||||
|
||||
- Fix a bug when HTTP method is PUT.
|
||||
|
||||
- Fix a bug when using 'is null' substatement in ORM.
|
||||
|
||||
- Fix a sqlite3 bug when some SQL errors occur.
|
||||
|
||||
- Fix bug with parsing json.
|
||||
|
||||
- Fix url decode.
|
||||
|
||||
- Fix a error in HttpClient.
|
||||
|
||||
- Fix a error in setThreadNum method.
|
||||
|
||||
- Fix some race conditions.
|
||||
|
||||
## [1.0.0-beta7] - 2019-08-31
|
||||
|
||||
### API changes list
|
||||
|
||||
- Remove the default value parameter of some methods (#220)
|
||||
|
||||
### Changed
|
||||
|
||||
- Optimize DNS in HttpClient and WebSocketClient (support c-ares library).
|
||||
|
||||
- Reduce dependencies between declarations.
|
||||
|
||||
- Add database tests in the travis CI and add test cases to database tests.
|
||||
|
||||
- Reduce size of docker image.
|
||||
|
||||
- Make the framework API support chained calls.
|
||||
|
||||
- Add a synchronous join point for AOP.
|
||||
|
||||
- Modify the CMakeLists to modern cmake style.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix bugs in default return values of functions(#220),
|
||||
|
||||
- Fix a bug in the cmake configuration file when there's '+' in the building path.
|
||||
|
||||
- Fix a bug in drogon_ctl (when creating orm models)
|
||||
|
||||
|
||||
## [1.0.0-beta6] - 2019-08-08
|
||||
|
||||
### API changes list
|
||||
|
||||
- None
|
||||
|
||||
### Changed
|
||||
|
||||
- Modify the 'create view' sub-command of drogon_ctl
|
||||
|
||||
- Optimize the transmission of pipelining responses.
|
||||
|
||||
- Add the DrogonConfig.cmake file so that users can use drogon with the `find_package(Drogon)` command.
|
||||
|
||||
## [1.0.0-beta5] - 2019-08-01
|
||||
|
||||
### API changes list
|
||||
|
||||
- None
|
||||
|
||||
### Added
|
||||
|
||||
- Add two methods to control if the Server header or the Date header is sent to clients with HTTP responses.
|
||||
* void HttpAppFramework::enableServerHeader(bool);
|
||||
* void HttpAppFramework::enableDateHeader(bool);
|
||||
|
||||
### Changed
|
||||
|
||||
- Support high performance batch mode of libpq.
|
||||
|
||||
### Fixed
|
||||
|
||||
- None
|
||||
|
||||
## [1.0.0-beta4] - 2019-07-30
|
||||
|
||||
### API changes list
|
||||
|
||||
- HttpRequest::query() returns a const reference of std::string instead of a string_view
|
||||
- WebSocketConnection::setContext(), WebSocketConnection::getContext(), etc.
|
||||
- Remove the config.h from public API.
|
||||
|
||||
### Added
|
||||
|
||||
- None
|
||||
|
||||
### Changed
|
||||
|
||||
- Modify the CMakeLists.txt
|
||||
- Modify the get_version.sh
|
||||
|
||||
### Fixed
|
||||
|
||||
- None
|
||||
|
||||
## [1.0.0-beta3] - 2019-07-28
|
||||
|
||||
### API changes list
|
||||
|
||||
- None
|
||||
|
||||
### Added
|
||||
|
||||
- Add a README file for examples.
|
||||
- Add some managers to reduce the size of the HttpAppFrameworkImpl code.
|
||||
- Add missing wasm ContentType.
|
||||
|
||||
### Changed
|
||||
|
||||
- Update the submodule - trantor.
|
||||
- Optimize processing of HTTP pipelining.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix an error in the HttpClient class when sending a request using the HEAD method.
|
||||
|
||||
## [1.0.0-beta2] - 2019-07-10
|
||||
|
||||
### API changes list
|
||||
|
||||
- Add setBody methods to the HttpRequest class.
|
||||
- Add the setContentTypeCodeAndCustomString method to the HttpResponse class.
|
||||
|
||||
### Added
|
||||
|
||||
- Add stress testing command to drogon_ctl.
|
||||
- Add -v, -h parameters to drogon_ctl.
|
||||
|
||||
### Changed
|
||||
|
||||
- Update the submodule - trantor.
|
||||
- Modify the handling of CORS.
|
||||
- Optimize the htmlTranslate method and the Field class.
|
||||
- Make all listeners share IO threads in the MacOS/Unix system.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix a bug of the IsPlugin class.
|
||||
- Use default constructor of string_view to reset _statusMessage to fix a warning on GCC 9.1 on Arch Linux.
|
||||
|
||||
## [1.0.0-beta1] - 2019-06-11
|
||||
|
||||
[Unreleased]: https://github.com/an-tao/drogon/compare/v1.6.0...HEAD
|
||||
|
||||
[1.6.0]: https://github.com/an-tao/drogon/compare/v1.5.1...v1.6.0
|
||||
|
||||
[1.5.1]: https://github.com/an-tao/drogon/compare/v1.5.0...v1.5.1
|
||||
|
||||
[1.5.0]: https://github.com/an-tao/drogon/compare/v1.4.1...v1.5.0
|
||||
|
||||
[1.4.1]: https://github.com/an-tao/drogon/compare/v1.4.0...v1.4.1
|
||||
|
||||
[1.4.0]: https://github.com/an-tao/drogon/compare/v1.3.0...v1.4.0
|
||||
|
||||
[1.3.0]: https://github.com/an-tao/drogon/compare/v1.2.0...v1.3.0
|
||||
|
||||
[1.2.0]: https://github.com/an-tao/drogon/compare/v1.1.0...v1.2.0
|
||||
|
||||
[1.1.0]: https://github.com/an-tao/drogon/compare/v1.0.0...v1.1.0
|
||||
|
||||
[1.0.0]: https://github.com/an-tao/drogon/compare/v1.0.0-beta21...v1.0.0
|
||||
|
||||
[1.0.0-beta21]: https://github.com/an-tao/drogon/compare/v1.0.0-beta20...v1.0.0-beta21
|
||||
|
||||
[1.0.0-beta20]: https://github.com/an-tao/drogon/compare/v1.0.0-beta19...v1.0.0-beta20
|
||||
|
||||
[1.0.0-beta19]: https://github.com/an-tao/drogon/compare/v1.0.0-beta18...v1.0.0-beta19
|
||||
|
||||
[1.0.0-beta18]: https://github.com/an-tao/drogon/compare/v1.0.0-beta17...v1.0.0-beta18
|
||||
|
||||
[1.0.0-beta17]: https://github.com/an-tao/drogon/compare/v1.0.0-beta16...v1.0.0-beta17
|
||||
|
||||
[1.0.0-beta16]: https://github.com/an-tao/drogon/compare/v1.0.0-beta15...v1.0.0-beta16
|
||||
|
||||
[1.0.0-beta15]: https://github.com/an-tao/drogon/compare/v1.0.0-beta14...v1.0.0-beta15
|
||||
|
||||
[1.0.0-beta14]: https://github.com/an-tao/drogon/compare/v1.0.0-beta13...v1.0.0-beta14
|
||||
|
||||
[1.0.0-beta13]: https://github.com/an-tao/drogon/compare/v1.0.0-beta12...v1.0.0-beta13
|
||||
|
||||
[1.0.0-beta12]: https://github.com/an-tao/drogon/compare/v1.0.0-beta11...v1.0.0-beta12
|
||||
|
||||
[1.0.0-beta11]: https://github.com/an-tao/drogon/compare/v1.0.0-beta10...v1.0.0-beta11
|
||||
|
||||
[1.0.0-beta10]: https://github.com/an-tao/drogon/compare/v1.0.0-beta9...v1.0.0-beta10
|
||||
|
||||
[1.0.0-beta9]: https://github.com/an-tao/drogon/compare/v1.0.0-beta8...v1.0.0-beta9
|
||||
|
||||
[1.0.0-beta8]: https://github.com/an-tao/drogon/compare/v1.0.0-beta7...v1.0.0-beta8
|
||||
|
||||
[1.0.0-beta7]: https://github.com/an-tao/drogon/compare/v1.0.0-beta6...v1.0.0-beta7
|
||||
|
||||
[1.0.0-beta6]: https://github.com/an-tao/drogon/compare/v1.0.0-beta5...v1.0.0-beta6
|
||||
|
||||
[1.0.0-beta5]: https://github.com/an-tao/drogon/compare/v1.0.0-beta4...v1.0.0-beta5
|
||||
|
||||
[1.0.0-beta4]: https://github.com/an-tao/drogon/compare/v1.0.0-beta3...v1.0.0-beta4
|
||||
|
||||
[1.0.0-beta3]: https://github.com/an-tao/drogon/compare/v1.0.0-beta2...v1.0.0-beta3
|
||||
|
||||
[1.0.0-beta2]: https://github.com/an-tao/drogon/compare/v1.0.0-beta1...v1.0.0-beta2
|
||||
|
||||
[1.0.0-beta1]: https://github.com/an-tao/drogon/releases/tag/v1.0.0-beta1
|
@ -1,199 +0,0 @@
|
||||
![](https://github.com/an-tao/drogon/wiki/images/drogon-white.jpg)
|
||||
|
||||
[![Build Status](https://travis-ci.com/an-tao/drogon.svg?branch=master)](https://travis-ci.com/an-tao/drogon)
|
||||
![Build Status](https://github.com/an-tao/drogon/workflows/Build%20Drogon/badge.svg?branch=master)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/12ffuf6j5vankgyb/branch/master?svg=true)](https://ci.appveyor.com/project/an-tao/drogon/branch/master)
|
||||
[![Total alerts](https://img.shields.io/lgtm/alerts/g/an-tao/drogon.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/an-tao/drogon/alerts/)
|
||||
[![Join the chat at https://gitter.im/drogon-web/community](https://badges.gitter.im/drogon-web/community.svg)](https://gitter.im/drogon-web/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[![Join the telegram group at https://t.me/joinchat/_mMNGv0748ZkMDAx](https://img.shields.io/badge/Telegram-2CA5E0?style=flat&logo=telegram&logoColor=white)](https://t.me/joinchat/_mMNGv0748ZkMDAx)
|
||||
[![Docker image](https://img.shields.io/badge/Docker-image-blue.svg)](https://cloud.docker.com/u/drogonframework/repository/docker/drogonframework/drogon)
|
||||
|
||||
[English](./README.md) | 简体中文 | [繁體中文](./README.zh-TW.md)
|
||||
|
||||
**Drogon**是一个基于C++14/17的Http应用框架,使用Drogon可以方便的使用C++构建各种类型的Web应用服务端程序。
|
||||
本版本库是github上[Drogon工程](https://github.com/an-tao/drogon)的镜像库。**Drogon**是作者非常喜欢的美剧《权力的游戏》中的一条龙的名字(汉译作卓耿),和龙有关但并不是dragon的误写,为了不至于引起不必要的误会这里说明一下。
|
||||
|
||||
Drogon是一个跨平台框架,它支持Linux,也支持macOS、FreeBSD,OpenBSD,和Windows。它的主要特点如下:
|
||||
|
||||
* 网络层使用基于epoll(macOS/FreeBSD下是kqueue)的非阻塞IO框架,提供高并发、高性能的网络IO。详细请见[TFB Tests Results](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite);
|
||||
* 全异步编程模式;
|
||||
* 支持Http1.0/1.1(server端和client端);
|
||||
* 基于template实现了简单的反射机制,使主程序框架、控制器(controller)和视图(view)完全解耦;
|
||||
* 支持cookies和内建的session;
|
||||
* 支持后端渲染,把控制器生成的数据交给视图生成Html页面,视图由CSP模板文件描述,通过CSP标签把C++代码嵌入到Html页面,由drogon的命令行工具在编译阶段自动生成C++代码并编译;
|
||||
* 支持运行期的视图页面动态加载(动态编译和加载so文件);
|
||||
* 非常方便灵活的路径(path)到控制器处理函数(handler)的映射方案;
|
||||
* 支持过滤器(filter)链,方便在控制器之前执行统一的逻辑(如登录验证、Http Method约束验证等);
|
||||
* 支持https(基于OpenSSL实现);
|
||||
* 支持websocket(server端和client端);
|
||||
* 支持Json格式请求和应答, 对Restful API应用开发非常友好;
|
||||
* 支持文件下载和上传,支持sendfile系统调用;
|
||||
* 支持gzip/brotli压缩传输;
|
||||
* 支持pipelining;
|
||||
* 提供一个轻量的命令行工具drogon_ctl,帮助简化各种类的创建和视图代码的生成过程;
|
||||
* 基于非阻塞IO实现的异步数据库读写,目前支持PostgreSQL和MySQL(MariaDB)数据库;
|
||||
* 基于线程池实现sqlite3数据库的异步读写,提供与上文数据库相同的接口;
|
||||
* 支持Redis异步读写;
|
||||
* 支持ARM架构;
|
||||
* 方便的轻量级ORM实现,支持常规的对象到数据库的双向映射操作;
|
||||
* 支持插件,可通过配置文件在加载期动态拆装;
|
||||
* 支持内建插入点的AOP
|
||||
* 支持C++协程
|
||||
|
||||
## 一个非常简单的例子
|
||||
|
||||
不像大多数C++框架那样,drogon的主程序可以保持非常简单。 Drogon使用了一些小技巧使主程序和控制器解耦合. 控制器的路由设置可以在控制器类中定义或者配置文件中完成.
|
||||
|
||||
下面是一个典型的主程序的样子:
|
||||
|
||||
```c++
|
||||
#include <drogon/drogon.h>
|
||||
using namespace drogon;
|
||||
int main()
|
||||
{
|
||||
app().setLogPath("./")
|
||||
.setLogLevel(trantor::Logger::kWarn)
|
||||
.addListener("0.0.0.0", 80)
|
||||
.setThreadNum(16)
|
||||
.enableRunAsDaemon()
|
||||
.run();
|
||||
}
|
||||
```
|
||||
|
||||
如果使用配置文件,可以进一步简化成如下的样子:
|
||||
|
||||
```c++
|
||||
#include <drogon/drogon.h>
|
||||
using namespace drogon;
|
||||
int main()
|
||||
{
|
||||
app().loadConfigFile("./config.json").run();
|
||||
}
|
||||
```
|
||||
|
||||
当然,Drogon也提供了一些接口,使用户可以在main()函数中直接添加控制器逻辑,比如,用户可以注册一个lambda处理器到drogon框架中,如下所示:
|
||||
|
||||
```c++
|
||||
app().registerHandler("/test?username={name}",
|
||||
[](const HttpRequestPtr& req,
|
||||
std::function<void (const HttpResponsePtr &)> &&callback,
|
||||
const std::string &name)
|
||||
{
|
||||
Json::Value json;
|
||||
json["result"]="ok";
|
||||
json["message"]=std::string("hello,")+name;
|
||||
auto resp=HttpResponse::newHttpJsonResponse(json);
|
||||
callback(resp);
|
||||
},
|
||||
{Get,"LoginFilter"});
|
||||
```
|
||||
|
||||
|
||||
这看起来是很方便,但是这并不适用于复杂的应用,试想假如有数十个或者数百个处理函数要注册进框架,main()函数将膨胀到不可读的程度。显然,让每个包含处理函数的类在自己的定义中完成注册是更好的选择。所以,除非你的应用逻辑非常简单,我们不推荐使用上述接口,更好的实践是,我们可以创建一个HttpSimpleController对象,如下:
|
||||
|
||||
|
||||
```c++
|
||||
/// The TestCtrl.h file
|
||||
#pragma once
|
||||
#include <drogon/HttpSimpleController.h>
|
||||
using namespace drogon;
|
||||
class TestCtrl:public drogon::HttpSimpleController<TestCtrl>
|
||||
{
|
||||
public:
|
||||
virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
|
||||
PATH_LIST_BEGIN
|
||||
PATH_ADD("/test",Get);
|
||||
PATH_LIST_END
|
||||
};
|
||||
|
||||
/// The TestCtrl.cc file
|
||||
#include "TestCtrl.h"
|
||||
void TestCtrl::asyncHandleHttpRequest(const HttpRequestPtr& req,
|
||||
std::function<void (const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
//write your application logic here
|
||||
auto resp = HttpResponse::newHttpResponse();
|
||||
resp->setBody("<p>Hello, world!</p>");
|
||||
resp->setExpiredTime(0);
|
||||
callback(resp);
|
||||
}
|
||||
```
|
||||
|
||||
**上面程序的大部分代码都可以由`drogon_ctl`命令创建**(这个命令是`drogon_ctl create controller TestCtr`)。用户所需做的就是添加自己的业务逻辑。在这个例子中,当客户端访问URL`http://ip/test`时,控制器简单的返回了一个`Hello, world!`页面。
|
||||
|
||||
对于JSON格式的响应,我们可以像下面这样创建控制器:
|
||||
|
||||
```c++
|
||||
/// The header file
|
||||
#pragma once
|
||||
#include <drogon/HttpSimpleController.h>
|
||||
using namespace drogon;
|
||||
class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
|
||||
{
|
||||
public:
|
||||
virtual void asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) override;
|
||||
PATH_LIST_BEGIN
|
||||
//list path definitions here;
|
||||
PATH_ADD("/json", Get);
|
||||
PATH_LIST_END
|
||||
};
|
||||
|
||||
/// The source file
|
||||
#include "JsonCtrl.h"
|
||||
void JsonCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["message"] = "Hello, World!";
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
callback(resp);
|
||||
}
|
||||
```
|
||||
|
||||
让我们更进一步,通过HttpController类创建一个RESTful API的例子,如下所示(忽略了实现文件):
|
||||
|
||||
```c++
|
||||
/// The header file
|
||||
#pragma once
|
||||
#include <drogon/HttpController.h>
|
||||
using namespace drogon;
|
||||
namespace api
|
||||
{
|
||||
namespace v1
|
||||
{
|
||||
class User : public drogon::HttpController<User>
|
||||
{
|
||||
public:
|
||||
METHOD_LIST_BEGIN
|
||||
//use METHOD_ADD to add your custom processing function here;
|
||||
METHOD_ADD(User::getInfo, "/{id}", Get); //path is /api/v1/User/{arg1}
|
||||
METHOD_ADD(User::getDetailInfo, "/{id}/detailinfo", Get); //path is /api/v1/User/{arg1}/detailinfo
|
||||
METHOD_ADD(User::newUser, "/{name}", Post); //path is /api/v1/User/{arg1}
|
||||
METHOD_LIST_END
|
||||
//your declaration of processing function maybe like this:
|
||||
void getInfo(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, int userId) const;
|
||||
void getDetailInfo(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, int userId) const;
|
||||
void newUser(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, std::string &&userName);
|
||||
public:
|
||||
User()
|
||||
{
|
||||
LOG_DEBUG << "User constructor!";
|
||||
}
|
||||
};
|
||||
} // namespace v1
|
||||
} // namespace api
|
||||
```
|
||||
|
||||
如你所见,通过`HttpController`类,用户可以同时映射路径和路径参数,这对RESTful API应用来说非常方便。
|
||||
|
||||
另外,你可以发现前面所有的处理函数接口都是异步的,处理器的响应是通过回调对象返回的。这种设计是出于对高性能的考虑,因为在异步模式下,可以使用少量的线程(比如和处理器核心数相等的线程)处理大量的并发请求。
|
||||
|
||||
编译上述的所有源文件后,我们得到了一个非常简单的web应用程序,这是一个不错的开始。**请访问[wiki](https://github.com/an-tao/drogon/wiki/CHN-01-概述)或者[doxiz](https://doxiz.com/drogon/master/overview/)以获取更多的信息**
|
||||
|
||||
## 贡献方式
|
||||
|
||||
欢迎您的贡献。 请阅读[贡献指南](CONTRIBUTING.md)以获取更多的信息。
|
||||
|
||||
## QQ交流群:1137909452
|
||||
|
||||
欢迎交流探讨。
|
@ -1,199 +0,0 @@
|
||||
![](https://github.com/an-tao/drogon/wiki/images/drogon-white.jpg)
|
||||
|
||||
[![Build Status](https://travis-ci.com/an-tao/drogon.svg?branch=master)](https://travis-ci.com/an-tao/drogon)
|
||||
![Build Status](https://github.com/an-tao/drogon/workflows/Build%20Drogon/badge.svg?branch=master)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/12ffuf6j5vankgyb/branch/master?svg=true)](https://ci.appveyor.com/project/an-tao/drogon/branch/master)
|
||||
[![Total alerts](https://img.shields.io/lgtm/alerts/g/an-tao/drogon.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/an-tao/drogon/alerts/)
|
||||
[![Join the chat at https://gitter.im/drogon-web/community](https://badges.gitter.im/drogon-web/community.svg)](https://gitter.im/drogon-web/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[![Join the telegram group at https://t.me/joinchat/_mMNGv0748ZkMDAx](https://img.shields.io/badge/Telegram-2CA5E0?style=flat&logo=telegram&logoColor=white)](https://t.me/joinchat/_mMNGv0748ZkMDAx)
|
||||
[![Docker image](https://img.shields.io/badge/Docker-image-blue.svg)](https://cloud.docker.com/u/drogonframework/repository/docker/drogonframework/drogon)
|
||||
|
||||
[English](./README.md) | [简体中文](./README.zh-CN.md) | 繁體中文
|
||||
|
||||
**Drogon**是一個基於C++14/17的Http應用框架,使用Drogon可以方便的使用C++構建各種類型的Web App伺服器程式。
|
||||
本版本庫是github上[Drogon](https://github.com/an-tao/drogon)的鏡像庫。 **Drogon**是作者非常喜歡的美劇《冰與火之歌:權力遊戲》中的一條龍的名字(漢譯作卓耿),和龍有關但並不是dragon的誤寫,為了不至於引起不必要的誤會這裡說明一下。
|
||||
|
||||
Drogon是一個跨平台框架,它支援Linux,也支援macOS、FreeBSD/OpenBSD和Windows。它的主要特點如下:
|
||||
|
||||
* 網路層使用基於epoll(macOS/FreeBSD下是kqueue)的非阻塞IO框架,提供高並發、高性能的網路IO。詳細請見[TFB Tests Results](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite);
|
||||
* 全異步程式設計;
|
||||
* 支援Http1.0/1.1(server端和client端);
|
||||
* 基於模板(template)實現了簡單的反射機制,使主程式框架、控制器(controller)和視圖(view)完全去耦;
|
||||
* 支援cookies和內建的session;
|
||||
* 支援後端渲染,把控制器生成的數據交給視圖生成Html頁面,視圖由CSP模板文件描述,通過CSP標籤把C++程式碼嵌入到Html頁面,由drogon的指令列工具在編譯階段自動生成C++程式碼並編譯;
|
||||
* 支援運行期的視圖頁面動態加載(動態編譯和載入so文件);
|
||||
* 非常方便靈活的路徑(path)到控制器處理函數(handler)的映射方案;
|
||||
* 支援過濾器(filter)鏈,方便在控制器之前執行統一的邏輯(如登錄驗證、Http Method約束驗證等);
|
||||
* 支援https(基於OpenSSL);
|
||||
* 支援websocket(server端和client端);
|
||||
* 支援Json格式的請求和回應, 方便開發Restful API;
|
||||
* 支援文件下載和上傳,支援sendfile系統呼叫;
|
||||
* 支援gzip/brotli壓縮傳輸;
|
||||
* 支援pipelining;
|
||||
* 提供一個輕量的指令列工具drogon_ctl,幫助簡化各種類的創造和視圖程式碼的生成過程;
|
||||
* 非同步的讀寫資料庫,目前支援PostgreSQL和MySQL(MariaDB)資料庫;
|
||||
* 支援異步讀寫Redis;
|
||||
* 基於執行序池實現sqlite3資料庫的異步讀寫,提供與上文資料庫相同的接口;
|
||||
* 支援ARM架構;
|
||||
* 方便的輕量級ORM實現,一般物件到資料庫的雙向映射;
|
||||
* 支援外掛,可通過設定文件在載入時動態載入;
|
||||
* 支援內建插入點的AOP
|
||||
* 支援C++ coroutine
|
||||
|
||||
## 一個非常簡單的例子
|
||||
|
||||
不像大多數C++框架那樣,drogon的主程式可以非常簡單。 Drogon使用了一些小技巧使主程式和控制器去耦. 控制器的路由設定可以在控制器類別中定義或者設定文件中完成.
|
||||
|
||||
下面是一個典型的主程式的樣子:
|
||||
|
||||
```c++
|
||||
#include <drogon/drogon.h>
|
||||
using namespace drogon;
|
||||
int main()
|
||||
{
|
||||
app().setLogPath("./")
|
||||
.setLogLevel(trantor::Logger::kWarn)
|
||||
.addListener("0.0.0.0", 80)
|
||||
.setThreadNum(16)
|
||||
.enableRunAsDaemon()
|
||||
.run();
|
||||
}
|
||||
```
|
||||
|
||||
如果使用設定文件,可以進一步簡化成這樣:
|
||||
|
||||
```c++
|
||||
#include <drogon/drogon.h>
|
||||
using namespace drogon;
|
||||
int main()
|
||||
{
|
||||
app().loadConfigFile("./config.json").run();
|
||||
}
|
||||
```
|
||||
|
||||
當然,Drogon也提供了一些函數,使使用者可以在main()函數中直接添加控制器邏輯,比如,使用者可以註冊一個lambda處理器到drogon框架中,如下所示:
|
||||
|
||||
```c++
|
||||
app().registerHandler("/test?username={name}",
|
||||
[](const HttpRequestPtr& req,
|
||||
std::function<void (const HttpResponsePtr &)> &&callback,
|
||||
const std::string &name)
|
||||
{
|
||||
Json::Value json;
|
||||
json["result"]="ok";
|
||||
json["message"]=std::string("hello,")+name;
|
||||
auto resp=HttpResponse::newHttpJsonResponse(json);
|
||||
callback(resp);
|
||||
},
|
||||
{Get,"LoginFilter"});
|
||||
```
|
||||
|
||||
|
||||
這看起來是很方便,但是這並不適用於復雜的場景,試想假如有數十個或者數百個處理函數要註冊進框架,main()函數將膨脹到不可讀的程度。顯然,讓每個包含處理函數的類在自己的定義中完成註冊是更好的選擇。所以,除非你的應用邏輯非常簡單,我們不推薦使用上述接口,更好的實踐是,我們可以創造一個HttpSimpleController類別,如下:
|
||||
|
||||
|
||||
```c++
|
||||
/// The TestCtrl.h file
|
||||
#pragma once
|
||||
#include <drogon/HttpSimpleController.h>
|
||||
using namespace drogon;
|
||||
class TestCtrl:public drogon::HttpSimpleController<TestCtrl>
|
||||
{
|
||||
public:
|
||||
virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
|
||||
PATH_LIST_BEGIN
|
||||
PATH_ADD("/test",Get);
|
||||
PATH_LIST_END
|
||||
};
|
||||
|
||||
/// The TestCtrl.cc file
|
||||
#include "TestCtrl.h"
|
||||
void TestCtrl::asyncHandleHttpRequest(const HttpRequestPtr& req,
|
||||
std::function<void (const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
//write your application logic here
|
||||
auto resp = HttpResponse::newHttpResponse();
|
||||
resp->setBody("<p>Hello, world!</p>");
|
||||
resp->setExpiredTime(0);
|
||||
callback(resp);
|
||||
}
|
||||
```
|
||||
|
||||
**上面程式的大部分程式碼都可以由`drogon_ctl`指令創造**(這個指令是`drogon_ctl create controller TestCtr`)。使用者所需做的就是添加自己的業務邏輯。在這個例子中,當客戶端訪問URL`http://ip/test`時,控制器簡單的回傳了一個`Hello, world!`頁面。
|
||||
|
||||
對於JSON格式的回應,我們可以像下面這樣創造控制器:
|
||||
|
||||
```c++
|
||||
/// The header file
|
||||
#pragma once
|
||||
#include <drogon/HttpSimpleController.h>
|
||||
using namespace drogon;
|
||||
class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
|
||||
{
|
||||
public:
|
||||
virtual void asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) override;
|
||||
PATH_LIST_BEGIN
|
||||
//list path definitions here;
|
||||
PATH_ADD("/json", Get);
|
||||
PATH_LIST_END
|
||||
};
|
||||
|
||||
/// The source file
|
||||
#include "JsonCtrl.h"
|
||||
void JsonCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["message"] = "Hello, World!";
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
callback(resp);
|
||||
}
|
||||
```
|
||||
|
||||
讓我們更進一步,通過HttpController類別創造一個RESTful API的例子,如下所示(忽略了實做文件):
|
||||
|
||||
```c++
|
||||
/// The header file
|
||||
#pragma once
|
||||
#include <drogon/HttpController.h>
|
||||
using namespace drogon;
|
||||
namespace api
|
||||
{
|
||||
namespace v1
|
||||
{
|
||||
class User : public drogon::HttpController<User>
|
||||
{
|
||||
public:
|
||||
METHOD_LIST_BEGIN
|
||||
//use METHOD_ADD to add your custom processing function here;
|
||||
METHOD_ADD(User::getInfo, "/{id}", Get); //path is /api/v1/User/{arg1}
|
||||
METHOD_ADD(User::getDetailInfo, "/{id}/detailinfo", Get); //path is /api/v1/User/{arg1}/detailinfo
|
||||
METHOD_ADD(User::newUser, "/{name}", Post); //path is /api/v1/User/{arg1}
|
||||
METHOD_LIST_END
|
||||
//your declaration of processing function maybe like this:
|
||||
void getInfo(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, int userId) const;
|
||||
void getDetailInfo(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, int userId) const;
|
||||
void newUser(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, std::string &&userName);
|
||||
public:
|
||||
User()
|
||||
{
|
||||
LOG_DEBUG << "User constructor!";
|
||||
}
|
||||
};
|
||||
} // namespace v1
|
||||
} // namespace api
|
||||
```
|
||||
|
||||
如你所見,通過`HttpController`類別,使用者可以同時映射路徑和路徑參數,這對RESTful API應用來說非常方便。
|
||||
|
||||
另外,你可以發現前面所有的處理函數接口都是異步的,處理器的回應是通過回調對象回傳的。這種設計是出於對高性能的考慮,因為在異步模式下,可以使用少量的執行序(比如和處理器核心數相等的執行序)處理大量的並發請求。
|
||||
|
||||
編譯上述的所有源文件後,我們得到了一個非常簡單的web應用程式,這是一個不錯的開始。 **請瀏覽[wiki](https://github.com/an-tao/drogon/wiki/CHN-01-概述)或者[doxiz](https://doxiz.com/drogon/master/overview/)以獲取更多的信息**
|
||||
|
||||
## 貢獻方式
|
||||
|
||||
歡迎您的貢獻。請閱讀[貢獻指南](CONTRIBUTING.md)以獲取更多的信息。
|
||||
|
||||
## QQ交流群:1137909452
|
||||
|
||||
歡迎交流探討。
|
@ -1,101 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#build drogon
|
||||
function build_drogon() {
|
||||
|
||||
#Update the submodule and initialize
|
||||
git submodule update --init
|
||||
|
||||
#Remove the config.h generated by the old version of drogon.
|
||||
rm -f lib/inc/drogon/config.h
|
||||
|
||||
#Save current directory
|
||||
current_dir="${PWD}"
|
||||
|
||||
#The folder in which we will build drogon
|
||||
build_dir='./build'
|
||||
if [ -d $build_dir ]; then
|
||||
echo "Deleted folder: ${build_dir}"
|
||||
rm -rf $build_dir
|
||||
fi
|
||||
|
||||
#Create building folder
|
||||
echo "Created building folder: ${build_dir}"
|
||||
mkdir $build_dir
|
||||
|
||||
echo "Entering folder: ${build_dir}"
|
||||
cd $build_dir
|
||||
|
||||
echo "Start building drogon ..."
|
||||
if [ $1 -eq 1 ]; then
|
||||
cmake .. -DBUILD_TESTING=YES $cmake_gen
|
||||
elif [ $1 -eq 2 ]; then
|
||||
cmake .. -DBUILD_TESTING=YES -DBUILD_DROGON_SHARED=ON -DCMAKE_CXX_VISIBILITY_PRESET=hidden -DCMAKE_VISIBILITY_INLINES_HIDDEN=1 $cmake_gen
|
||||
else
|
||||
cmake .. -DCMAKE_BUILD_TYPE=release $cmake_gen
|
||||
fi
|
||||
|
||||
#If errors then exit
|
||||
if [ "$?" != "0" ]; then
|
||||
exit -1
|
||||
fi
|
||||
|
||||
$make_program $make_flags
|
||||
|
||||
#If errors then exit
|
||||
if [ "$?" != "0" ]; then
|
||||
exit -1
|
||||
fi
|
||||
|
||||
echo "Installing ..."
|
||||
sudo $make_program install
|
||||
|
||||
#Go back to the current directory
|
||||
cd $current_dir
|
||||
#Ok!
|
||||
}
|
||||
|
||||
make_program=make
|
||||
make_flags=''
|
||||
cmake_gen=''
|
||||
parallel=1
|
||||
|
||||
case $(uname) in
|
||||
FreeBSD)
|
||||
nproc=$(sysctl -n hw.ncpu)
|
||||
;;
|
||||
Darwin)
|
||||
nproc=$(sysctl -n hw.ncpu) # sysctl -n hw.ncpu is the equivalent to nproc on macOS.
|
||||
;;
|
||||
*)
|
||||
nproc=$(nproc)
|
||||
;;
|
||||
esac
|
||||
|
||||
# simulate ninja's parallelism
|
||||
case nproc in
|
||||
1)
|
||||
parallel=$(( nproc + 1 ))
|
||||
;;
|
||||
2)
|
||||
parallel=$(( nproc + 1 ))
|
||||
;;
|
||||
*)
|
||||
parallel=$(( nproc + 2 ))
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -f /bin/ninja ]; then
|
||||
make_program=ninja
|
||||
cmake_gen='-GNinja'
|
||||
else
|
||||
make_flags="$make_flags -j$parallel"
|
||||
fi
|
||||
|
||||
if [ "$1" = "-t" ]; then
|
||||
build_drogon 1
|
||||
elif [ "$1" = "-tshared" ]; then
|
||||
build_drogon 2
|
||||
else
|
||||
build_drogon 0
|
||||
fi
|
@ -1,60 +0,0 @@
|
||||
# ##############################################################################
|
||||
# function drogon_create_views(target source_path output_path
|
||||
# [use_path_as_namespace])
|
||||
# ##############################################################################
|
||||
function(drogon_create_views arg)
|
||||
if(ARGC LESS 3)
|
||||
message(STATUS "arguments error when calling drogon_create_views")
|
||||
return()
|
||||
endif()
|
||||
file(MAKE_DIRECTORY ${ARGV2})
|
||||
file(GLOB_RECURSE SCP_LIST ${ARGV1}/*.csp)
|
||||
foreach(cspFile ${SCP_LIST})
|
||||
file(RELATIVE_PATH
|
||||
inFile
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${cspFile})
|
||||
if(ARGC GREATER 3 AND ARGV3)
|
||||
string(REPLACE "/"
|
||||
"_"
|
||||
f1
|
||||
${inFile})
|
||||
string(REPLACE "\\"
|
||||
"_"
|
||||
f2
|
||||
${f1})
|
||||
string(REPLACE ".csp"
|
||||
""
|
||||
outputFile
|
||||
${f2})
|
||||
add_custom_command(OUTPUT ${ARGV2}/${outputFile}.h ${ARGV2}/${outputFile}.cc
|
||||
COMMAND drogon_ctl
|
||||
ARGS
|
||||
create
|
||||
view
|
||||
${inFile}
|
||||
--path-to-namespace
|
||||
-o
|
||||
${ARGV2}
|
||||
DEPENDS ${cspFile}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
VERBATIM)
|
||||
set(VIEWSRC ${VIEWSRC} ${ARGV2}/${outputFile}.cc)
|
||||
else()
|
||||
get_filename_component(classname ${cspFile} NAME_WE)
|
||||
add_custom_command(OUTPUT ${ARGV2}/${classname}.h ${ARGV2}/${classname}.cc
|
||||
COMMAND drogon_ctl
|
||||
ARGS
|
||||
create
|
||||
view
|
||||
${inFile}
|
||||
-o
|
||||
${ARGV2}
|
||||
DEPENDS ${cspFile}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
VERBATIM)
|
||||
set(VIEWSRC ${VIEWSRC} ${ARGV2}/${classname}.cc)
|
||||
endif()
|
||||
endforeach()
|
||||
target_sources(${ARGV0} PRIVATE ${VIEWSRC})
|
||||
endfunction(drogon_create_views)
|
@ -1,79 +0,0 @@
|
||||
#==================================================================================================#
|
||||
# Adapted and re-written from Catch2 to work with Drogon Test #
|
||||
# #
|
||||
# Usage #
|
||||
# 1. make sure this module is in the path or add this otherwise: #
|
||||
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake_modules/") #
|
||||
# 2. make sure that you've enabled testing option for the project by the call: #
|
||||
# enable_testing() #
|
||||
# 3. add the lines to the script for testing target (sample CMakeLists.txt): #
|
||||
# project(testing_target) #
|
||||
# enable_testing() #
|
||||
# #
|
||||
# file(GLOB SOURCE_FILES "*.cpp") #
|
||||
# add_executable(${PROJECT_NAME} ${SOURCE_FILES}) #
|
||||
# #
|
||||
# include(ParseAndAddDrogonTests) #
|
||||
# ParseAndAddDrogonTests(${PROJECT_NAME}) #
|
||||
#==================================================================================================#
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# This removes the contents between
|
||||
# - block comments (i.e. /* ... */)
|
||||
# - full line comments (i.e. // ... )
|
||||
# contents have been read into '${CppCode}'.
|
||||
# !keep partial line comments
|
||||
function(RemoveComments CppCode)
|
||||
string(ASCII 2 CMakeBeginBlockComment)
|
||||
string(ASCII 3 CMakeEndBlockComment)
|
||||
string(REGEX REPLACE "/\\*" "${CMakeBeginBlockComment}" ${CppCode} "${${CppCode}}")
|
||||
string(REGEX REPLACE "\\*/" "${CMakeEndBlockComment}" ${CppCode} "${${CppCode}}")
|
||||
string(REGEX REPLACE "${CMakeBeginBlockComment}[^${CMakeEndBlockComment}]*${CMakeEndBlockComment}" "" ${CppCode} "${${CppCode}}")
|
||||
string(REGEX REPLACE "\n[ \t]*//+[^\n]+" "\n" ${CppCode} "${${CppCode}}")
|
||||
|
||||
set(${CppCode} "${${CppCode}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Worker function
|
||||
function(ParseFile SourceFile TestTarget)
|
||||
set(FullSourcePath ${CMAKE_CURRENT_SOURCE_DIR}/${SourceFile})
|
||||
if(NOT EXISTS ${FullSourcePath})
|
||||
return()
|
||||
endif()
|
||||
file(STRINGS ${FullSourcePath} Contents NEWLINE_CONSUME)
|
||||
|
||||
# Remove block and fullline comments
|
||||
RemoveComments(Contents)
|
||||
|
||||
# Find definition of test names
|
||||
string(REGEX MATCHALL "[ \t]*DROGON_TEST[ \t]*\\\([a-zA-Z0-9_]+\\\)" Tests "${Contents}")
|
||||
|
||||
foreach(TestLine ${Tests})
|
||||
# Strip newlines
|
||||
string(REGEX REPLACE "\\\\\n|\n" "" TestLine "${TestLine}")
|
||||
|
||||
# Get the name of the test
|
||||
string(REGEX REPLACE "[ \t]*DROGON_TEST[ \t]*" "" TestLine "${TestLine}")
|
||||
string(REGEX MATCHALL "[a-zA-Z0-9_]+" TestName "${TestLine}")
|
||||
|
||||
# Validate that a test name and tags have been provided
|
||||
list(LENGTH TestName TestNameLength)
|
||||
if(NOT TestNameLength EQUAL 1)
|
||||
message(FATAL_ERROR "${TestName} in ${SourceFile} is not a valid test name."
|
||||
" Either a bug in the Drogon Test CMake parser or a bug in the test itself")
|
||||
endif()
|
||||
|
||||
# Add the test and set its properties
|
||||
add_test(NAME "${TestName}" COMMAND ${TestTarget} -r ${TestName} ${AdditionalCatchParameters})
|
||||
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# entry point
|
||||
function(ParseAndAddDrogonTests TestTarget)
|
||||
get_target_property(SourceFiles ${TestTarget} SOURCES)
|
||||
foreach(SourceFile ${SourceFiles})
|
||||
ParseFile(${SourceFile} ${TestTarget})
|
||||
endforeach()
|
||||
endfunction()
|
@ -1,56 +0,0 @@
|
||||
# - Config file for the Drogon package
|
||||
# It defines the following variables
|
||||
# DROGON_INCLUDE_DIRS - include directories for Drogon
|
||||
# DROGON_LIBRARIES - libraries to link against
|
||||
# DROGON_EXECUTABLE - the drogon_ctl executable
|
||||
# Drogon_FOUND
|
||||
# This module defines the following IMPORTED target:
|
||||
# Drogon::Drogon
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
find_dependency(Jsoncpp REQUIRED)
|
||||
find_dependency(Trantor REQUIRED)
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD" AND NOT WIN32)
|
||||
find_dependency(UUID REQUIRED)
|
||||
endif(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD" AND NOT WIN32)
|
||||
find_dependency(ZLIB REQUIRED)
|
||||
if(@pg_FOUND@)
|
||||
find_dependency(pg)
|
||||
endif()
|
||||
if(@SQLite3_FOUND@)
|
||||
find_dependency(SQLite3)
|
||||
endif()
|
||||
if(@MySQL_FOUND@)
|
||||
find_dependency(MySQL)
|
||||
endif()
|
||||
if(@Boost_FOUND@)
|
||||
find_dependency(Boost)
|
||||
endif()
|
||||
if(@Brotli_FOUND@)
|
||||
find_dependency(Brotli)
|
||||
endif()
|
||||
if(@COZ-PROFILER_FOUND@)
|
||||
find_dependency(coz-profiler)
|
||||
endif()
|
||||
if(@Hiredis_FOUND@)
|
||||
find_dependency(Hiredis)
|
||||
endif()
|
||||
if(@BUILD_DROGON_SHARED@)
|
||||
find_dependency(Threads)
|
||||
endif()
|
||||
|
||||
# Our library dependencies (contains definitions for IMPORTED targets)
|
||||
|
||||
get_filename_component(DROGON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
if(NOT TARGET Drogon::Drogon)
|
||||
include("${DROGON_CMAKE_DIR}/DrogonTargets.cmake")
|
||||
include("${DROGON_CMAKE_DIR}/DrogonUtilities.cmake")
|
||||
endif()
|
||||
|
||||
get_target_property(DROGON_INCLUDE_DIRS Drogon::Drogon INTERFACE_INCLUDE_DIRECTORIES)
|
||||
set(DROGON_LIBRARIES Drogon::Drogon)
|
||||
set(DROGON_EXECUTABLE drogon_ctl)
|
@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#cmakedefine01 USE_POSTGRESQL
|
||||
#cmakedefine01 LIBPQ_SUPPORTS_BATCH_MODE
|
||||
#cmakedefine01 USE_MYSQL
|
||||
#cmakedefine01 USE_SQLITE3
|
||||
#cmakedefine OpenSSL_FOUND
|
||||
#cmakedefine Boost_FOUND
|
||||
|
||||
#cmakedefine COMPILATION_FLAGS "@COMPILATION_FLAGS@@DROGON_CXX_STANDARD@"
|
||||
#cmakedefine COMPILER_COMMAND "@COMPILER_COMMAND@"
|
||||
#cmakedefine COMPILER_ID "@COMPILER_ID@"
|
||||
|
||||
#cmakedefine INCLUDING_DIRS "@INCLUDING_DIRS@"
|
@ -1,5 +0,0 @@
|
||||
#define MAJOR @DROGON_MAJOR_VERSION@
|
||||
#define MINOR @DROGON_MINOR_VERSION@
|
||||
#define PATCH @DROGON_PATCH_VERSION@
|
||||
#define DROGON_VERSION "@DROGON_VERSION_STRING@"
|
||||
#define DROGON_VERSION_SHA1 "@GIT_SHA1@"
|
@ -1,7 +0,0 @@
|
||||
#include <uuid.h>
|
||||
int main()
|
||||
{
|
||||
uuid_t uu;
|
||||
uuid_generate(uu);
|
||||
return 0;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#include <uuid.h>
|
||||
int main()
|
||||
{
|
||||
uuid_t *uuid;
|
||||
uuid_create(&uuid);
|
||||
uuid_make(uuid, UUID_MAKE_V1);
|
||||
return 0;
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#include <libpq-fe.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
PQisInBatchMode(NULL);
|
||||
PQbatchIsAborted(NULL);
|
||||
PQqueriesInBatch(NULL);
|
||||
PQbeginBatchMode(NULL);
|
||||
PQendBatchMode(NULL);
|
||||
PQsendEndBatch(NULL);
|
||||
PQgetNextQuery(NULL);
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
# ***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which you should
|
||||
# have received as part of this distribution. The terms are also available at
|
||||
# https://curl.haxx.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is furnished
|
||||
# to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# ##############################################################################
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
|
||||
|
||||
find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon)
|
||||
find_library(BROTLIDEC_LIBRARY NAMES brotlidec)
|
||||
find_library(BROTLIENC_LIBRARY NAMES brotlienc)
|
||||
|
||||
find_package_handle_standard_args(Brotli
|
||||
REQUIRED_VARS
|
||||
BROTLIDEC_LIBRARY
|
||||
BROTLIENC_LIBRARY
|
||||
BROTLICOMMON_LIBRARY
|
||||
BROTLI_INCLUDE_DIR
|
||||
FAIL_MESSAGE
|
||||
"Could NOT find BROTLI")
|
||||
|
||||
set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR})
|
||||
set(BROTLI_LIBRARIES ${BROTLIDEC_LIBRARY}
|
||||
${BROTLIENC_LIBRARY} ${BROTLICOMMON_LIBRARY})
|
||||
|
||||
if(Brotli_FOUND)
|
||||
add_library(Brotli_lib INTERFACE IMPORTED)
|
||||
set_target_properties(Brotli_lib
|
||||
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
||||
"${BROTLI_INCLUDE_DIRS}"
|
||||
INTERFACE_LINK_LIBRARIES
|
||||
"${BROTLI_LIBRARIES}")
|
||||
endif(Brotli_FOUND)
|
@ -1,40 +0,0 @@
|
||||
# Try to find hiredis
|
||||
# Once done, this will define
|
||||
#
|
||||
# HIREDIS_FOUND - system has hiredis
|
||||
# HIREDIS_INCLUDE_DIRS - hiredis include directories
|
||||
# HIREDIS_LIBRARIES - libraries need to use hiredis
|
||||
|
||||
if (HIREDIS_INCLUDE_DIRS AND HIREDIS_LIBRARIES)
|
||||
set(HIREDIS_FIND_QUIETLY TRUE)
|
||||
else ()
|
||||
find_path(
|
||||
HIREDIS_INCLUDE_DIR
|
||||
NAMES hiredis/hiredis.h
|
||||
HINTS ${HIREDIS_ROOT_DIR}
|
||||
PATH_SUFFIXES include)
|
||||
|
||||
find_library(
|
||||
HIREDIS_LIBRARY
|
||||
NAMES hiredis
|
||||
HINTS ${HIREDIS_ROOT_DIR}
|
||||
PATH_SUFFIXES ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
set(HIREDIS_INCLUDE_DIRS ${HIREDIS_INCLUDE_DIR})
|
||||
set(HIREDIS_LIBRARIES ${HIREDIS_LIBRARY})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(
|
||||
Hiredis DEFAULT_MSG HIREDIS_LIBRARY HIREDIS_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(HIREDIS_LIBRARY HIREDIS_INCLUDE_DIR)
|
||||
endif ()
|
||||
|
||||
if(Hiredis_FOUND)
|
||||
add_library(Hiredis_lib INTERFACE IMPORTED)
|
||||
set_target_properties(Hiredis_lib
|
||||
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
||||
"${HIREDIS_INCLUDE_DIRS}"
|
||||
INTERFACE_LINK_LIBRARIES
|
||||
"${HIREDIS_LIBRARIES}")
|
||||
endif(Hiredis_FOUND)
|
@ -1,68 +0,0 @@
|
||||
# Find jsoncpp
|
||||
#
|
||||
# Find the jsoncpp includes and library
|
||||
#
|
||||
# if you nee to add a custom library search path, do it via via
|
||||
# CMAKE_PREFIX_PATH
|
||||
#
|
||||
# This module defines JSONCPP_INCLUDE_DIRS, where to find header, etc.
|
||||
# JSONCPP_LIBRARIES, the libraries needed to use jsoncpp. JSONCPP_FOUND, If
|
||||
# false, do not try to use jsoncpp.
|
||||
# Jsoncpp_lib - The imported target library.
|
||||
|
||||
# only look in default directories
|
||||
find_path(JSONCPP_INCLUDE_DIRS
|
||||
NAMES json/json.h
|
||||
DOC "jsoncpp include dir"
|
||||
PATH_SUFFIXES jsoncpp)
|
||||
|
||||
find_library(JSONCPP_LIBRARIES NAMES jsoncpp DOC "jsoncpp library")
|
||||
|
||||
# debug library on windows same naming convention as in qt (appending debug
|
||||
# library with d) boost is using the same "hack" as us with "optimized" and
|
||||
# "debug" if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
# find_library(JSONCPP_LIBRARIES_DEBUG NAMES jsoncppd DOC "jsoncpp debug
|
||||
# library") if("${JSONCPP_LIBRARIES_DEBUG}" STREQUAL "JSONCPP_LIBRARIES_DEBUG-
|
||||
# NOTFOUND") set(JSONCPP_LIBRARIES_DEBUG ${JSONCPP_LIBRARIES}) endif()
|
||||
|
||||
# set(JSONCPP_LIBRARIES optimized ${JSONCPP_LIBRARIES} debug
|
||||
# ${JSONCPP_LIBRARIES_DEBUG})
|
||||
|
||||
# endif()
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set JSONCPP_FOUND to TRUE if all
|
||||
# listed variables are TRUE, hide their existence from configuration view
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Jsoncpp
|
||||
DEFAULT_MSG
|
||||
JSONCPP_INCLUDE_DIRS
|
||||
JSONCPP_LIBRARIES)
|
||||
mark_as_advanced(JSONCPP_INCLUDE_DIRS JSONCPP_LIBRARIES)
|
||||
|
||||
if(Jsoncpp_FOUND)
|
||||
if(NOT EXISTS ${JSONCPP_INCLUDE_DIRS}/json/version.h)
|
||||
message(FATAL_ERROR "Error: jsoncpp lib is too old.....stop")
|
||||
endif()
|
||||
if(NOT WIN32)
|
||||
exec_program(
|
||||
cat
|
||||
ARGS
|
||||
"${JSONCPP_INCLUDE_DIRS}/json/version.h |grep JSONCPP_VERSION_STRING|sed s'/.*define/define/'|awk '{printf $3}'|sed s'/\"//g'"
|
||||
OUTPUT_VARIABLE
|
||||
jsoncpp_ver)
|
||||
message(STATUS "jsoncpp verson:" ${jsoncpp_ver})
|
||||
if(jsoncpp_ver LESS 1.7)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"jsoncpp lib is too old, please get new version from https://github.com/open-source-parsers/jsoncpp"
|
||||
)
|
||||
endif(jsoncpp_ver LESS 1.7)
|
||||
endif()
|
||||
add_library(Jsoncpp_lib INTERFACE IMPORTED)
|
||||
set_target_properties(Jsoncpp_lib
|
||||
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
||||
"${JSONCPP_INCLUDE_DIRS}"
|
||||
INTERFACE_LINK_LIBRARIES
|
||||
"${JSONCPP_LIBRARIES}")
|
||||
|
||||
endif(Jsoncpp_FOUND)
|
@ -1,122 +0,0 @@
|
||||
# --------------------------------------------------------
|
||||
# Copyright (C) 1995-2007 MySQL AB
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of version 2 of the GNU General Public License as published by the
|
||||
# Free Software Foundation.
|
||||
#
|
||||
# There are special exceptions to the terms and conditions of the GPL as it is
|
||||
# applied to this software. View the full text of the exception in file
|
||||
# LICENSE.exceptions in the top-level directory of this software distribution.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
|
||||
# Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
#
|
||||
# The MySQL Connector/ODBC is licensed under the terms of the GPL, like most
|
||||
# MySQL Connectors. There are special exceptions to the terms and conditions of
|
||||
# the GPL as it is applied to this software, see the FLOSS License Exception
|
||||
# available on mysql.com.
|
||||
# MySQL_lib - The imported target library.
|
||||
|
||||
# ##############################################################################
|
||||
|
||||
# -------------- FIND MYSQL_INCLUDE_DIRS ------------------
|
||||
find_path(MYSQL_INCLUDE_DIRS
|
||||
NAMES mysql.h
|
||||
PATH_SUFFIXES mysql
|
||||
PATHS /usr/include/mysql
|
||||
/usr/local/include/mysql
|
||||
/usr/include/mariadb
|
||||
/usr/local/include/mariadb
|
||||
/opt/mysql/mysql/include
|
||||
/opt/mysql/mysql/include/mysql
|
||||
/opt/mysql/include
|
||||
/opt/local/include/mysql5
|
||||
/usr/local/mysql/include
|
||||
/usr/local/mysql/include/mysql
|
||||
/usr/local/mariadb/include
|
||||
/usr/local/mariadb/include/mariadb
|
||||
/opt/rh/rh-mariadb105/root/usr/include
|
||||
/opt/rh/rh-mariadb105/root/usr/include/mysql
|
||||
$ENV{ProgramFiles}/MySQL/*/include
|
||||
$ENV{SystemDrive}/MySQL/*/include)
|
||||
|
||||
if(EXISTS "${MYSQL_INCLUDE_DIRS}/mysql.h")
|
||||
|
||||
elseif(EXISTS "${MYSQL_INCLUDE_DIRS}/mysql/mysql.h")
|
||||
set(MYSQL_INCLUDE_DIRS ${MYSQL_INCLUDE_DIRS}/mysql)
|
||||
endif()
|
||||
|
||||
# ----------------- FIND MYSQL_LIBRARIES_DIR -------------------
|
||||
if(WIN32)
|
||||
# Set lib path suffixes dist = for mysql binary distributions build = for
|
||||
# custom built tree
|
||||
if(CMAKE_BUILD_TYPE STREQUAL Debug)
|
||||
set(libsuffixDist debug)
|
||||
set(libsuffixBuild Debug)
|
||||
else(CMAKE_BUILD_TYPE STREQUAL Debug)
|
||||
set(libsuffixDist opt)
|
||||
set(libsuffixBuild Release)
|
||||
add_definitions(-DDBUG_OFF)
|
||||
endif(CMAKE_BUILD_TYPE STREQUAL Debug)
|
||||
|
||||
find_library(MYSQL_LIBRARIES
|
||||
NAMES mariadbclient
|
||||
PATHS $ENV{MYSQL_DIR}/lib/${libsuffixDist}
|
||||
$ENV{MYSQL_DIR}/libmysql
|
||||
$ENV{MYSQL_DIR}/libmysql/${libsuffixBuild}
|
||||
$ENV{MYSQL_DIR}/client/${libsuffixBuild}
|
||||
$ENV{MYSQL_DIR}/libmysql/${libsuffixBuild}
|
||||
$ENV{ProgramFiles}/MySQL/*/lib/${libsuffixDist}
|
||||
$ENV{SystemDrive}/MySQL/*/lib/${libsuffixDist})
|
||||
else(WIN32)
|
||||
find_library(MYSQL_LIBRARIES
|
||||
NAMES mysqlclient_r mariadbclient
|
||||
PATHS /usr/lib/mysql
|
||||
/usr/lib/mariadb
|
||||
/usr/local/lib/mysql
|
||||
/usr/local/lib/mariadb
|
||||
/usr/local/mysql/lib
|
||||
/usr/local/mysql/lib/mysql
|
||||
/opt/local/mysql5/lib
|
||||
/opt/local/lib/mysql5/mysql
|
||||
/opt/mysql/mysql/lib/mysql
|
||||
/opt/mysql/lib/mysql
|
||||
/opt/rh/rh-mariadb105/root/usr/lib64)
|
||||
endif(WIN32)
|
||||
|
||||
if(MYSQL_INCLUDE_DIRS AND MYSQL_LIBRARIES)
|
||||
message(STATUS "MySQL Include dir: ${MYSQL_INCLUDE_DIRS}")
|
||||
message(STATUS "MySQL client libraries: ${MYSQL_LIBRARIES}")
|
||||
elseif(MySQL_FIND_REQUIRED)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Cannot find MySQL. Include dir: ${MYSQL_INCLUDE_DIRS} library dir: ${MYSQL_LIBRARIES_DIR}"
|
||||
)
|
||||
endif(MYSQL_INCLUDE_DIRS AND MYSQL_LIBRARIES)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(MySQL
|
||||
DEFAULT_MSG
|
||||
MYSQL_LIBRARIES
|
||||
MYSQL_INCLUDE_DIRS)
|
||||
# Copy the results to the output variables.
|
||||
if(MySQL_FOUND)
|
||||
add_library(MySQL_lib INTERFACE IMPORTED)
|
||||
set_target_properties(MySQL_lib
|
||||
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
||||
"${MYSQL_INCLUDE_DIRS}"
|
||||
INTERFACE_LINK_LIBRARIES
|
||||
"${MYSQL_LIBRARIES}")
|
||||
else(MySQL_FOUND)
|
||||
set(MYSQL_LIBRARIES)
|
||||
set(MYSQL_INCLUDE_DIRS)
|
||||
endif(MySQL_FOUND)
|
||||
|
||||
mark_as_advanced(MYSQL_INCLUDE_DIRS MYSQL_LIBRARIES)
|
@ -1,43 +0,0 @@
|
||||
# Copyright (C) 2007-2009 LuaDist. Created by Peter Kapec <kapecp@gmail.com>
|
||||
# Redistribution and use of this file is allowed according to the terms of the
|
||||
# MIT license. For details see the COPYRIGHT file distributed with LuaDist.
|
||||
# Note: Searching headers and libraries is very simple and is NOT as powerful as
|
||||
# scripts distributed with CMake, because LuaDist defines directories to search
|
||||
# for. Everyone is encouraged to contact the author with improvements. Maybe
|
||||
# this file becomes part of CMake distribution sometimes.
|
||||
|
||||
# * Find sqlite3 Find the native SQLITE3 headers and libraries.
|
||||
#
|
||||
# SQLITE3_INCLUDE_DIRS - where to find sqlite3.h, etc.
|
||||
# SQLITE3_LIBRARIES - List of libraries when using sqlite.
|
||||
# SQLite3_FOUND - True if sqlite3 found.
|
||||
# SQLite3_lib - The imported target library.
|
||||
|
||||
# Look for the header file.
|
||||
find_path(SQLITE3_INCLUDE_DIRS NAMES sqlite3.h)
|
||||
|
||||
# Look for the library.
|
||||
find_library(SQLITE3_LIBRARIES NAMES sqlite3)
|
||||
|
||||
# Handle the QUIETLY and REQUIRED arguments and set SQLite3_FOUND to TRUE if all
|
||||
# listed variables are TRUE.
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(SQLite3
|
||||
DEFAULT_MSG
|
||||
SQLITE3_LIBRARIES
|
||||
SQLITE3_INCLUDE_DIRS)
|
||||
|
||||
# Copy the results to the output variables.
|
||||
if(SQLite3_FOUND)
|
||||
add_library(SQLite3_lib INTERFACE IMPORTED)
|
||||
set_target_properties(SQLite3_lib
|
||||
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
||||
"${SQLITE3_INCLUDE_DIRS}"
|
||||
INTERFACE_LINK_LIBRARIES
|
||||
"${SQLITE3_LIBRARIES}")
|
||||
else(SQLite3_FOUND)
|
||||
set(SQLITE3_LIBRARIES)
|
||||
set(SQLITE3_INCLUDE_DIRS)
|
||||
endif(SQLite3_FOUND)
|
||||
|
||||
mark_as_advanced(SQLITE3_INCLUDE_DIRS SQLITE3_LIBRARIES)
|
@ -1,118 +0,0 @@
|
||||
# * Try to find UUID Once done this will define
|
||||
#
|
||||
# UUID_FOUND - system has UUID
|
||||
# UUID_INCLUDE_DIRS - the UUID include directory
|
||||
# UUID_LIBRARIES - Link these to use UUID UUID_DEFINITIONS - Compiler switches
|
||||
# required for using UUID
|
||||
#
|
||||
# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New BSD
|
||||
# license. For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
if(UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(UUID_FOUND TRUE)
|
||||
else(UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
|
||||
find_path(
|
||||
UUID_INCLUDE_DIR
|
||||
NAMES uuid.h
|
||||
PATH_SUFFIXES uuid
|
||||
HINTS ${UUID_DIR}/include
|
||||
$ENV{UUID_DIR}/include
|
||||
$ENV{UUID_DIR}
|
||||
${DELTA3D_EXT_DIR}/inc
|
||||
$ENV{DELTA_ROOT}/ext/inc
|
||||
$ENV{DELTA_ROOT}
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
/usr/include/gdal
|
||||
/sw/include # Fink
|
||||
/opt/local/include # DarwinPorts
|
||||
/opt/csw/include # Blastwave
|
||||
/opt/include
|
||||
[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/include
|
||||
/usr/freeware/include)
|
||||
|
||||
find_library(UUID_LIBRARY
|
||||
NAMES uuid ossp-uuid
|
||||
HINTS ${UUID_DIR}/lib
|
||||
$ENV{UUID_DIR}/lib
|
||||
$ENV{UUID_DIR}
|
||||
${DELTA3D_EXT_DIR}/lib
|
||||
$ENV{DELTA_ROOT}/ext/lib
|
||||
$ENV{DELTA_ROOT}
|
||||
$ENV{OSG_ROOT}/lib
|
||||
PATHS ~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
/sw/lib
|
||||
/opt/local/lib
|
||||
/opt/csw/lib
|
||||
/opt/lib
|
||||
/usr/freeware/lib64)
|
||||
|
||||
find_library(UUID_LIBRARY_DEBUG
|
||||
NAMES uuidd
|
||||
HINTS ${UUID_DIR}/lib
|
||||
$ENV{UUID_DIR}/lib
|
||||
$ENV{UUID_DIR}
|
||||
${DELTA3D_EXT_DIR}/lib
|
||||
$ENV{DELTA_ROOT}/ext/lib
|
||||
$ENV{DELTA_ROOT}
|
||||
$ENV{OSG_ROOT}/lib
|
||||
PATHS ~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
/sw/lib
|
||||
/opt/local/lib
|
||||
/opt/csw/lib
|
||||
/opt/lib
|
||||
/usr/freeware/lib64)
|
||||
|
||||
if(NOT UUID_LIBRARY AND BSD)
|
||||
set(UUID_LIBRARY "")
|
||||
endif(NOT UUID_LIBRARY AND BSD)
|
||||
|
||||
set(UUID_INCLUDE_DIRS ${UUID_INCLUDE_DIR})
|
||||
set(UUID_LIBRARIES ${UUID_LIBRARY})
|
||||
|
||||
if(UUID_INCLUDE_DIRS)
|
||||
if(BSD OR UUID_LIBRARIES)
|
||||
set(UUID_FOUND TRUE)
|
||||
endif(BSD OR UUID_LIBRARIES)
|
||||
endif(UUID_INCLUDE_DIRS)
|
||||
|
||||
if(UUID_FOUND)
|
||||
if(NOT UUID_FIND_QUIETLY)
|
||||
message(STATUS "Found UUID: ${UUID_LIBRARIES}")
|
||||
endif(NOT UUID_FIND_QUIETLY)
|
||||
else(UUID_FOUND)
|
||||
if(UUID_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find UUID")
|
||||
endif(UUID_FIND_REQUIRED)
|
||||
endif(UUID_FOUND)
|
||||
|
||||
# show the UUID_INCLUDE_DIRS and UUID_LIBRARIES variables only in the advanced
|
||||
# view
|
||||
mark_as_advanced(UUID_INCLUDE_DIRS UUID_LIBRARIES)
|
||||
|
||||
endif(UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
|
||||
|
||||
if(UUID_FOUND)
|
||||
add_library(UUID_lib INTERFACE IMPORTED)
|
||||
set_target_properties(UUID_lib
|
||||
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
||||
"${UUID_INCLUDE_DIRS}"
|
||||
INTERFACE_LINK_LIBRARIES
|
||||
"${UUID_LIBRARIES}")
|
||||
else(UUID_FOUND)
|
||||
set(UUID_LIBRARIES)
|
||||
set(UUID_INCLUDE_DIRS)
|
||||
endif(UUID_FOUND)
|
@ -1,23 +0,0 @@
|
||||
find_path(COZ_INCLUDE_DIRS NAMES coz.h)
|
||||
|
||||
find_library(COZ_LIBRARIES NAMES coz PATH_SUFFIXES coz-profiler)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(coz-profiler
|
||||
DEFAULT_MSG
|
||||
COZ_LIBRARIES
|
||||
COZ_INCLUDE_DIRS)
|
||||
|
||||
if(COZ-PROFILER_FOUND)
|
||||
add_library(coz::coz INTERFACE IMPORTED)
|
||||
set_target_properties(coz::coz
|
||||
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
||||
${COZ_INCLUDE_DIRS}
|
||||
INTERFACE_LINK_LIBRARIES
|
||||
${COZ_LIBRARIES})
|
||||
else(COZ-PROFILER_FOUND)
|
||||
set(COZ_LIBRARIES)
|
||||
set(COZ_INCLUDE_DIRS)
|
||||
endif(COZ-PROFILER_FOUND)
|
||||
|
||||
mark_as_advanced(COZ_INCLUDE_DIRS COZ_LIBRARIES)
|
@ -1,27 +0,0 @@
|
||||
# Find PostgreSQL
|
||||
#
|
||||
# Find the PostgreSQL includes and library
|
||||
#
|
||||
# This module defines PG_INCLUDE_DIRS, where to find header, etc. PG_LIBRARIES,
|
||||
# the libraries needed to use PostgreSQL. pg_FOUND, If false, do not try to use
|
||||
# PostgreSQL.
|
||||
# pg_lib - The imported target library.
|
||||
|
||||
find_package(PostgreSQL)
|
||||
if(PostgreSQL_FOUND)
|
||||
set(PG_LIBRARIES ${PostgreSQL_LIBRARIES})
|
||||
set(PG_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIRS})
|
||||
message(STATUS "pg inc: " ${PostgreSQL_INCLUDE_DIRS})
|
||||
add_library(pg_lib INTERFACE IMPORTED)
|
||||
set_target_properties(pg_lib
|
||||
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
||||
"${PostgreSQL_INCLUDE_DIRS}"
|
||||
INTERFACE_LINK_LIBRARIES
|
||||
"${PostgreSQL_LIBRARIES}")
|
||||
mark_as_advanced(PG_INCLUDE_DIRS PG_LIBRARIES)
|
||||
endif(PostgreSQL_FOUND)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(pg
|
||||
DEFAULT_MSG
|
||||
PG_LIBRARIES
|
||||
PG_INCLUDE_DIRS)
|
@ -1,16 +0,0 @@
|
||||
[requires]
|
||||
jsoncpp/1.9.4
|
||||
zlib/1.2.11
|
||||
gtest/1.10.0
|
||||
sqlite3/3.34.1
|
||||
#libpq/13.2
|
||||
openssl/1.1.1j
|
||||
hiredis/1.0.0
|
||||
brotli/1.0.9
|
||||
|
||||
[generators]
|
||||
cmake_paths
|
||||
|
||||
[options]
|
||||
|
||||
[imports]
|
@ -1,21 +0,0 @@
|
||||
FROM archlinux:base-20210307.0.16708
|
||||
|
||||
RUN pacman -Syu --noconfirm && pacman -S wget sudo cmake make git gcc jsoncpp postgresql mariadb-clients --noconfirm
|
||||
|
||||
ENV LANG=en_US.UTF-8 \
|
||||
LANGUAGE=en_US:en \
|
||||
LC_ALL=en_US.UTF-8 \
|
||||
CC=gcc \
|
||||
CXX=g++ \
|
||||
AR=gcc-ar \
|
||||
RANLIB=gcc-ranlib \
|
||||
IROOT=/install
|
||||
|
||||
ENV DROGON_ROOT="$IROOT/drogon"
|
||||
|
||||
ADD https://api.github.com/repos/an-tao/drogon/git/refs/heads/master $IROOT/version.json
|
||||
RUN git clone https://github.com/an-tao/drogon $DROGON_ROOT
|
||||
|
||||
WORKDIR $DROGON_ROOT
|
||||
|
||||
RUN ./build.sh
|
@ -1,27 +0,0 @@
|
||||
FROM ubuntu:18.04
|
||||
|
||||
RUN apt-get update -yqq \
|
||||
&& apt-get install -yqq --no-install-recommends software-properties-common \
|
||||
sudo curl wget cmake pkg-config locales git gcc-8 g++-8 \
|
||||
openssl libssl-dev libjsoncpp-dev uuid-dev zlib1g-dev libc-ares-dev\
|
||||
postgresql-server-dev-all libmariadbclient-dev libsqlite3-dev \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& locale-gen en_US.UTF-8
|
||||
|
||||
ENV LANG=en_US.UTF-8 \
|
||||
LANGUAGE=en_US:en \
|
||||
LC_ALL=en_US.UTF-8 \
|
||||
CC=gcc-8 \
|
||||
CXX=g++-8 \
|
||||
AR=gcc-ar-8 \
|
||||
RANLIB=gcc-ranlib-8 \
|
||||
IROOT=/install
|
||||
|
||||
ENV DROGON_ROOT="$IROOT/drogon"
|
||||
|
||||
ADD https://api.github.com/repos/an-tao/drogon/git/refs/heads/master $IROOT/version.json
|
||||
RUN git clone https://github.com/an-tao/drogon $DROGON_ROOT
|
||||
|
||||
WORKDIR $DROGON_ROOT
|
||||
|
||||
RUN ./build.sh
|
Binary file not shown.
Before Width: | Height: | Size: 44 KiB |
@ -1,81 +0,0 @@
|
||||
set(ctl_sources
|
||||
cmd.cc
|
||||
create.cc
|
||||
create_controller.cc
|
||||
create_filter.cc
|
||||
create_model.cc
|
||||
create_plugin.cc
|
||||
create_project.cc
|
||||
create_view.cc
|
||||
help.cc
|
||||
main.cc
|
||||
press.cc
|
||||
version.cc)
|
||||
add_executable(_drogon_ctl
|
||||
main.cc
|
||||
cmd.cc
|
||||
create.cc
|
||||
create_view.cc)
|
||||
target_link_libraries(_drogon_ctl ${PROJECT_NAME})
|
||||
if (WIN32 AND BUILD_DROGON_SHARED)
|
||||
set(DROGON_FILE $<TARGET_FILE:drogon>)
|
||||
set(TRANTOR_FILE $<TARGET_FILE:trantor>)
|
||||
add_custom_command(TARGET _drogon_ctl POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCTL_FILE=${DROGON_FILE}
|
||||
-DINSTALL_BIN_DIR=$<TARGET_FILE_DIR:_drogon_ctl>
|
||||
-P
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CopyDlls.cmake)
|
||||
add_custom_command(TARGET _drogon_ctl POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCTL_FILE=${TRANTOR_FILE}
|
||||
-DINSTALL_BIN_DIR=$<TARGET_FILE_DIR:_drogon_ctl>
|
||||
-P
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CopyDlls.cmake)
|
||||
endif()
|
||||
file(GLOB SCP_LIST ${CMAKE_CURRENT_SOURCE_DIR}/templates/*.csp)
|
||||
foreach(cspFile ${SCP_LIST})
|
||||
message(STATUS "cspFile:" ${cspFile})
|
||||
get_filename_component(classname ${cspFile} NAME_WE)
|
||||
message(STATUS "view classname:" ${classname})
|
||||
add_custom_command(OUTPUT ${classname}.h ${classname}.cc
|
||||
COMMAND $<TARGET_FILE:_drogon_ctl>
|
||||
ARGS
|
||||
create
|
||||
view
|
||||
${cspFile}
|
||||
DEPENDS ${cspFile}
|
||||
VERBATIM)
|
||||
set(TEMPL_SRC ${TEMPL_SRC} ${classname}.cc)
|
||||
endforeach()
|
||||
add_executable(drogon_ctl ${ctl_sources} ${TEMPL_SRC})
|
||||
target_link_libraries(drogon_ctl PRIVATE ${PROJECT_NAME})
|
||||
target_include_directories(drogon_ctl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_dependencies(drogon_ctl _drogon_ctl)
|
||||
if(WIN32)
|
||||
target_link_libraries(drogon_ctl PRIVATE ws2_32 Rpcrt4)
|
||||
endif(WIN32)
|
||||
message(STATUS "bin:" ${INSTALL_BIN_DIR})
|
||||
install(TARGETS drogon_ctl RUNTIME DESTINATION ${INSTALL_BIN_DIR})
|
||||
if(WIN32)
|
||||
set(CTL_FILE $<TARGET_FILE:drogon_ctl>)
|
||||
add_custom_command(TARGET drogon_ctl POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCTL_FILE=${CTL_FILE}
|
||||
-DINSTALL_BIN_DIR=${INSTALL_BIN_DIR}
|
||||
-DRENAME_EXE=ON
|
||||
-P
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CopyDlls.cmake)
|
||||
else(WIN32)
|
||||
install(CODE "execute_process( \
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink \
|
||||
./drogon_ctl \
|
||||
./dg_ctl \
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/dg_ctl"
|
||||
DESTINATION ${INSTALL_BIN_DIR})
|
||||
endif(WIN32)
|
||||
set(ctl_targets _drogon_ctl drogon_ctl)
|
||||
set_property(TARGET ${ctl_targets} PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD})
|
||||
set_property(TARGET ${ctl_targets} PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
set_property(TARGET ${ctl_targets} PROPERTY CXX_EXTENSIONS OFF)
|
@ -1,35 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* CommandHandler.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <drogon/DrObject.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CommandHandler : public virtual drogon::DrObjectBase {
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) = 0;
|
||||
virtual bool isTopCommand() {
|
||||
return false;
|
||||
}
|
||||
virtual std::string script() {
|
||||
return "";
|
||||
}
|
||||
virtual std::string detail() {
|
||||
return "";
|
||||
}
|
||||
virtual ~CommandHandler() {
|
||||
}
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
make_directory("${INSTALL_BIN_DIR}")
|
||||
get_filename_component(CTL_PATH ${CTL_FILE} DIRECTORY)
|
||||
file(GLOB DLL_FILES ${CTL_PATH}/*.dll)
|
||||
file(COPY ${DLL_FILES} DESTINATION ${INSTALL_BIN_DIR})
|
||||
file(COPY ${CTL_FILE} DESTINATION ${INSTALL_BIN_DIR})
|
||||
if (RENAME_EXE)
|
||||
file(RENAME ${INSTALL_BIN_DIR}/drogon_ctl.exe ${INSTALL_BIN_DIR}/dg_ctl.exe)
|
||||
endif()
|
@ -1,48 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cmd.cc
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cmd.h"
|
||||
#include "CommandHandler.h"
|
||||
#include <drogon/DrClassMap.h>
|
||||
#include <memory>
|
||||
using namespace drogon;
|
||||
|
||||
void exeCommand(std::vector<std::string> ¶meters) {
|
||||
if (parameters.empty()) {
|
||||
std::cout << "incomplete command!use help command to get usage!"
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
std::string command = parameters[0];
|
||||
|
||||
std::string handlerName = std::string("drogon_ctl::").append(command);
|
||||
|
||||
parameters.erase(parameters.begin());
|
||||
|
||||
// new command handler to do cmd
|
||||
auto obj = std::shared_ptr<DrObjectBase>(
|
||||
drogon::DrClassMap::newObject(handlerName));
|
||||
if (obj) {
|
||||
auto ctl = std::dynamic_pointer_cast<CommandHandler>(obj);
|
||||
if (ctl) {
|
||||
ctl->handleCommand(parameters);
|
||||
} else {
|
||||
std::cout << "command not found!use help command to get usage!"
|
||||
<< std::endl;
|
||||
}
|
||||
} else {
|
||||
std::cout << "command error!use help command to get usage!"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* cmd.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#define ARGS_ERROR_STR "args error!use help command to get usage!"
|
||||
void exeCommand(std::vector<std::string> ¶meters);
|
@ -1,53 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* @file create.cc
|
||||
* @author An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "create.h"
|
||||
#include "cmd.h"
|
||||
#include <drogon/DrClassMap.h>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
using namespace drogon_ctl;
|
||||
std::string create::detail() {
|
||||
return "Use create command to create some source files of drogon webapp\n\n"
|
||||
"Usage:drogon_ctl create <view|controller|filter|project|model> "
|
||||
"[-options] <object name>\n\n"
|
||||
"drogon_ctl create view <csp file name> [-o <output path>] [-n "
|
||||
"<namespace>]|[--path-to-namespace]//create HttpView source files "
|
||||
"from csp files\n\n"
|
||||
"drogon_ctl create controller [-s] <[namespace::]class_name> //"
|
||||
"create HttpSimpleController source files\n\n"
|
||||
"drogon_ctl create controller -h <[namespace::]class_name> //"
|
||||
"create HttpController source files\n\n"
|
||||
"drogon_ctl create controller -w <[namespace::]class_name> //"
|
||||
"create WebSocketController source files\n\n"
|
||||
"drogon_ctl create controller -r <[namespace::]class_name> "
|
||||
"[--resource=...]//"
|
||||
"create restful controller source files\n\n"
|
||||
"drogon_ctl create filter <[namespace::]class_name> //"
|
||||
"create a filter named class_name\n\n"
|
||||
"drogon_ctl create plugin <[namespace::]class_name> //"
|
||||
"create a plugin named class_name\n\n"
|
||||
"drogon_ctl create project <project_name> //"
|
||||
"create a project named project_name\n\n"
|
||||
"drogon_ctl create model <model_path> [--table=<table_name>] [-f]//"
|
||||
"create model classes in model_path\n";
|
||||
}
|
||||
|
||||
void create::handleCommand(std::vector<std::string> ¶meters) {
|
||||
// std::cout<<"create!"<<std::endl;
|
||||
auto createObjName = parameters[0];
|
||||
createObjName = std::string("create_") + createObjName;
|
||||
parameters[0] = createObjName;
|
||||
exeCommand(parameters);
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* create.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CommandHandler.h"
|
||||
#include <drogon/DrObject.h>
|
||||
using namespace drogon;
|
||||
namespace drogon_ctl {
|
||||
class create : public DrObject<create>, public CommandHandler {
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
||||
virtual std::string script() override {
|
||||
return "create some source files(Use 'drogon_ctl help create' for more "
|
||||
"information)";
|
||||
}
|
||||
virtual bool isTopCommand() override {
|
||||
return true;
|
||||
}
|
||||
virtual std::string detail() override;
|
||||
};
|
||||
} // namespace drogon_ctl
|
@ -1,396 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* create_controller.cc
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "create_controller.h"
|
||||
#include "cmd.h"
|
||||
#include <drogon/DrTemplateBase.h>
|
||||
#include <drogon/utils/Utilities.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
|
||||
using namespace drogon_ctl;
|
||||
|
||||
void create_controller::handleCommand(std::vector<std::string> ¶meters) {
|
||||
// std::cout<<"create!"<<std::endl;
|
||||
ControllerType type = Simple;
|
||||
for (auto iter = parameters.begin(); iter != parameters.end(); ++iter) {
|
||||
if ((*iter)[0] == '-') {
|
||||
if (*iter == "-s" || (*iter == "--simple")) {
|
||||
parameters.erase(iter);
|
||||
break;
|
||||
} else if (*iter == "-a" || *iter == "-h" || *iter == "--http") {
|
||||
type = Http;
|
||||
parameters.erase(iter);
|
||||
break;
|
||||
} else if (*iter == "-w" || *iter == "--websocket") {
|
||||
type = WebSocket;
|
||||
parameters.erase(iter);
|
||||
break;
|
||||
} else if (*iter == "-r" || *iter == "--restful") {
|
||||
type = Restful;
|
||||
parameters.erase(iter);
|
||||
break;
|
||||
} else {
|
||||
std::cout << ARGS_ERROR_STR << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type != Restful)
|
||||
createController(parameters, type);
|
||||
else {
|
||||
std::string resource;
|
||||
for (auto iter = parameters.begin(); iter != parameters.end(); ++iter) {
|
||||
if ((*iter).find("--resource=") == 0) {
|
||||
resource = (*iter).substr(strlen("--resource="));
|
||||
parameters.erase(iter);
|
||||
break;
|
||||
}
|
||||
if ((*iter)[0] == '-') {
|
||||
std::cerr << "Error parameter for '" << (*iter) << "'"
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (parameters.size() > 1) {
|
||||
std::cerr << "Too many parameters" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
auto className = parameters[0];
|
||||
createARestfulController(className, resource);
|
||||
}
|
||||
}
|
||||
|
||||
void create_controller::newSimpleControllerHeaderFile(
|
||||
std::ofstream &file,
|
||||
const std::string &className) {
|
||||
file << "#pragma once\n";
|
||||
file << "#include <drogon/HttpSimpleController.h>\n";
|
||||
file << "using namespace drogon;\n";
|
||||
std::string class_name = className;
|
||||
std::string namepace_path = "/";
|
||||
auto pos = class_name.find("::");
|
||||
size_t namespaceCount = 0;
|
||||
while (pos != std::string::npos) {
|
||||
++namespaceCount;
|
||||
auto namespaceName = class_name.substr(0, pos);
|
||||
class_name = class_name.substr(pos + 2);
|
||||
file << "namespace " << namespaceName << "\n";
|
||||
namepace_path.append(namespaceName).append("/");
|
||||
file << "{\n";
|
||||
pos = class_name.find("::");
|
||||
}
|
||||
file << "class " << class_name << ":public drogon::HttpSimpleController<"
|
||||
<< class_name << ">\n";
|
||||
file << "{\n";
|
||||
file << " public:\n";
|
||||
file << " virtual void asyncHandleHttpRequest(const HttpRequestPtr& "
|
||||
"req, std::function<void (const HttpResponsePtr &)> &&callback) "
|
||||
"override;\n";
|
||||
|
||||
file << " PATH_LIST_BEGIN\n";
|
||||
file << " //list path definitions here;\n";
|
||||
file << " "
|
||||
"//PATH_ADD(\"/"
|
||||
"path\",\"filter1\",\"filter2\",HttpMethod1,HttpMethod2...);\n";
|
||||
file << " PATH_LIST_END\n";
|
||||
file << "};\n";
|
||||
while (namespaceCount > 0) {
|
||||
--namespaceCount;
|
||||
file << "}\n";
|
||||
}
|
||||
}
|
||||
void create_controller::newSimpleControllerSourceFile(
|
||||
std::ofstream &file,
|
||||
const std::string &className,
|
||||
const std::string &filename) {
|
||||
file << "#include \"" << filename << ".h\"\n";
|
||||
auto pos = className.rfind("::");
|
||||
auto class_name = className;
|
||||
if (pos != std::string::npos) {
|
||||
auto namespacename = className.substr(0, pos);
|
||||
file << "using namespace " << namespacename << ";\n";
|
||||
class_name = className.substr(pos + 2);
|
||||
}
|
||||
file << "void " << class_name
|
||||
<< "::asyncHandleHttpRequest(const HttpRequestPtr& req, "
|
||||
"std::function<void (const HttpResponsePtr &)> &&callback)\n";
|
||||
file << "{\n";
|
||||
file << " //write your application logic here\n";
|
||||
file << "}";
|
||||
}
|
||||
|
||||
void create_controller::newWebsockControllerHeaderFile(
|
||||
std::ofstream &file,
|
||||
const std::string &className) {
|
||||
file << "#pragma once\n";
|
||||
file << "#include <drogon/WebSocketController.h>\n";
|
||||
file << "using namespace drogon;\n";
|
||||
std::string class_name = className;
|
||||
std::string namepace_path = "/";
|
||||
auto pos = class_name.find("::");
|
||||
size_t namespaceCount = 0;
|
||||
while (pos != std::string::npos) {
|
||||
++namespaceCount;
|
||||
auto namespaceName = class_name.substr(0, pos);
|
||||
class_name = class_name.substr(pos + 2);
|
||||
file << "namespace " << namespaceName << "\n";
|
||||
namepace_path.append(namespaceName).append("/");
|
||||
file << "{\n";
|
||||
pos = class_name.find("::");
|
||||
}
|
||||
file << "class " << class_name << ":public drogon::WebSocketController<"
|
||||
<< class_name << ">\n";
|
||||
file << "{\n";
|
||||
file << " public:\n";
|
||||
file
|
||||
<< " virtual void handleNewMessage(const WebSocketConnectionPtr&,\n";
|
||||
file << " std::string &&,\n";
|
||||
file << " const WebSocketMessageType &) "
|
||||
"override;\n";
|
||||
file << " virtual void handleNewConnection(const HttpRequestPtr &,\n";
|
||||
file << " const "
|
||||
"WebSocketConnectionPtr&)override;\n";
|
||||
file << " virtual void handleConnectionClosed(const "
|
||||
"WebSocketConnectionPtr&)override;\n";
|
||||
file << " WS_PATH_LIST_BEGIN\n";
|
||||
file << " //list path definitions here;\n";
|
||||
file << " //WS_PATH_ADD(\"/path\",\"filter1\",\"filter2\",...);\n";
|
||||
file << " WS_PATH_LIST_END\n";
|
||||
file << "};\n";
|
||||
while (namespaceCount > 0) {
|
||||
--namespaceCount;
|
||||
file << "}\n";
|
||||
}
|
||||
}
|
||||
void create_controller::newWebsockControllerSourceFile(
|
||||
std::ofstream &file,
|
||||
const std::string &className,
|
||||
const std::string &filename) {
|
||||
file << "#include \"" << filename << ".h\"\n";
|
||||
auto pos = className.rfind("::");
|
||||
auto class_name = className;
|
||||
if (pos != std::string::npos) {
|
||||
auto namespacename = className.substr(0, pos);
|
||||
file << "using namespace " << namespacename << ";\n";
|
||||
class_name = className.substr(pos + 2);
|
||||
}
|
||||
file << "void " << class_name
|
||||
<< "::handleNewMessage(const WebSocketConnectionPtr& wsConnPtr, "
|
||||
"std::string &&message, const WebSocketMessageType &type)\n";
|
||||
file << "{\n";
|
||||
file << " //write your application logic here\n";
|
||||
file << "}\n";
|
||||
file << "void " << class_name
|
||||
<< "::handleNewConnection(const HttpRequestPtr &req,const "
|
||||
"WebSocketConnectionPtr& wsConnPtr)\n";
|
||||
file << "{\n";
|
||||
file << " //write your application logic here\n";
|
||||
file << "}\n";
|
||||
file << "void " << class_name
|
||||
<< "::handleConnectionClosed(const WebSocketConnectionPtr& "
|
||||
"wsConnPtr)\n";
|
||||
file << "{\n";
|
||||
file << " //write your application logic here\n";
|
||||
file << "}\n";
|
||||
}
|
||||
|
||||
void create_controller::newHttpControllerHeaderFile(
|
||||
std::ofstream &file,
|
||||
const std::string &className) {
|
||||
file << "#pragma once\n";
|
||||
file << "#include <drogon/HttpController.h>\n";
|
||||
file << "using namespace drogon;\n";
|
||||
std::string class_name = className;
|
||||
std::string namepace_path = "/";
|
||||
auto pos = class_name.find("::");
|
||||
size_t namespaceCount = 0;
|
||||
while (pos != std::string::npos) {
|
||||
++namespaceCount;
|
||||
auto namespaceName = class_name.substr(0, pos);
|
||||
class_name = class_name.substr(pos + 2);
|
||||
file << "namespace " << namespaceName << "\n";
|
||||
namepace_path.append(namespaceName).append("/");
|
||||
file << "{\n";
|
||||
pos = class_name.find("::");
|
||||
}
|
||||
file << "class " << class_name << ":public drogon::HttpController<"
|
||||
<< class_name << ">\n";
|
||||
file << "{\n";
|
||||
file << " public:\n";
|
||||
file << " METHOD_LIST_BEGIN\n";
|
||||
file << " //use METHOD_ADD to add your custom processing function "
|
||||
"here;\n";
|
||||
file << " //METHOD_ADD(" << class_name
|
||||
<< "::get,\"/{2}/{1}\",Get);"
|
||||
"//path is "
|
||||
<< namepace_path << class_name << "/{arg2}/{arg1}\n";
|
||||
file << " //METHOD_ADD(" << class_name
|
||||
<< "::your_method_name,\"/{1}/{2}/list\",Get);"
|
||||
"//path is "
|
||||
<< namepace_path << class_name << "/{arg1}/{arg2}/list\n";
|
||||
file << " //ADD_METHOD_TO(" << class_name
|
||||
<< "::your_method_name,\"/absolute/path/{1}/{2}/list\",Get);"
|
||||
"//path is /absolute/path/{arg1}/{arg2}/list\n";
|
||||
file << "\n";
|
||||
file << " METHOD_LIST_END\n";
|
||||
file << " // your declaration of processing function maybe like this:\n";
|
||||
file << " // void get(const HttpRequestPtr& req,"
|
||||
"std::function<void (const HttpResponsePtr &)> &&callback,int "
|
||||
"p1,std::string p2);\n";
|
||||
file << " // void your_method_name(const HttpRequestPtr& req,"
|
||||
"std::function<void (const HttpResponsePtr &)> &&callback,double "
|
||||
"p1,int p2) const;\n";
|
||||
file << "};\n";
|
||||
while (namespaceCount > 0) {
|
||||
--namespaceCount;
|
||||
file << "}\n";
|
||||
}
|
||||
}
|
||||
void create_controller::newHttpControllerSourceFile(
|
||||
std::ofstream &file,
|
||||
const std::string &className,
|
||||
const std::string &filename) {
|
||||
file << "#include \"" << filename << ".h\"\n";
|
||||
auto pos = className.rfind("::");
|
||||
auto class_name = className;
|
||||
if (pos != std::string::npos) {
|
||||
auto namespacename = className.substr(0, pos);
|
||||
file << "using namespace " << namespacename << ";\n";
|
||||
class_name = className.substr(pos + 2);
|
||||
}
|
||||
|
||||
file << "//add definition of your processing function here\n";
|
||||
}
|
||||
|
||||
void create_controller::createController(std::vector<std::string> &httpClasses,
|
||||
ControllerType type) {
|
||||
for (auto iter = httpClasses.begin(); iter != httpClasses.end(); ++iter) {
|
||||
if ((*iter)[0] == '-') {
|
||||
std::cout << ARGS_ERROR_STR << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (auto const &className : httpClasses) {
|
||||
createController(className, type);
|
||||
}
|
||||
}
|
||||
|
||||
void create_controller::createController(const std::string &className,
|
||||
ControllerType type) {
|
||||
std::regex regex("::");
|
||||
std::string ctlName =
|
||||
std::regex_replace(className, regex, std::string("_"));
|
||||
|
||||
std::string headFileName = ctlName + ".h";
|
||||
std::string sourceFilename = ctlName + ".cc";
|
||||
{
|
||||
std::ifstream iHeadFile(headFileName.c_str(), std::ifstream::in);
|
||||
std::ifstream iSourceFile(sourceFilename.c_str(), std::ifstream::in);
|
||||
|
||||
if (iHeadFile || iSourceFile) {
|
||||
std::cout << "The file you want to create already exists, "
|
||||
"overwrite it(y/n)?"
|
||||
<< std::endl;
|
||||
auto in = getchar();
|
||||
(void)getchar(); // get the return key
|
||||
if (in != 'Y' && in != 'y') {
|
||||
std::cout << "Abort!" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::ofstream oHeadFile(headFileName.c_str(), std::ofstream::out);
|
||||
std::ofstream oSourceFile(sourceFilename.c_str(), std::ofstream::out);
|
||||
if (!oHeadFile || !oSourceFile) {
|
||||
perror("");
|
||||
exit(1);
|
||||
}
|
||||
if (type == Http) {
|
||||
std::cout << "create a http controller:" << className << std::endl;
|
||||
newHttpControllerHeaderFile(oHeadFile, className);
|
||||
newHttpControllerSourceFile(oSourceFile, className, ctlName);
|
||||
} else if (type == Simple) {
|
||||
std::cout << "create a http simple controller:" << className
|
||||
<< std::endl;
|
||||
newSimpleControllerHeaderFile(oHeadFile, className);
|
||||
newSimpleControllerSourceFile(oSourceFile, className, ctlName);
|
||||
} else if (type == WebSocket) {
|
||||
std::cout << "create a websocket controller:" << className << std::endl;
|
||||
newWebsockControllerHeaderFile(oHeadFile, className);
|
||||
newWebsockControllerSourceFile(oSourceFile, className, ctlName);
|
||||
}
|
||||
}
|
||||
|
||||
void create_controller::createARestfulController(const std::string &className,
|
||||
const std::string &resource) {
|
||||
std::regex regex("::");
|
||||
std::string ctlName =
|
||||
std::regex_replace(className, regex, std::string("_"));
|
||||
|
||||
std::string headFileName = ctlName + ".h";
|
||||
std::string sourceFilename = ctlName + ".cc";
|
||||
{
|
||||
std::ifstream iHeadFile(headFileName.c_str(), std::ifstream::in);
|
||||
std::ifstream iSourceFile(sourceFilename.c_str(), std::ifstream::in);
|
||||
|
||||
if (iHeadFile || iSourceFile) {
|
||||
std::cout << "The file you want to create already exists, "
|
||||
"overwrite it(y/n)?"
|
||||
<< std::endl;
|
||||
auto in = getchar();
|
||||
(void)getchar(); // get the return key
|
||||
if (in != 'Y' && in != 'y') {
|
||||
std::cout << "Abort!" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::ofstream oHeadFile(headFileName.c_str(), std::ofstream::out);
|
||||
std::ofstream oSourceFile(sourceFilename.c_str(), std::ofstream::out);
|
||||
if (!oHeadFile || !oSourceFile) {
|
||||
perror("");
|
||||
exit(1);
|
||||
}
|
||||
auto v = utils::splitString(className, "::");
|
||||
drogon::DrTemplateData data;
|
||||
data.insert("className", v[v.size() - 1]);
|
||||
v.pop_back();
|
||||
data.insert("namespaceVector", v);
|
||||
data.insert("resource", resource);
|
||||
data.insert("fileName", ctlName);
|
||||
if (resource.empty()) {
|
||||
data.insert("ctlCommand",
|
||||
std::string("drogon_ctl create controller -r ") +
|
||||
className);
|
||||
} else {
|
||||
data.insert("ctlCommand",
|
||||
std::string("drogon_ctl create controller -r ") +
|
||||
className + " --resource=" + resource);
|
||||
}
|
||||
try {
|
||||
auto templ = DrTemplateBase::newTemplate("restful_controller_h.csp");
|
||||
oHeadFile << templ->genText(data);
|
||||
templ = DrTemplateBase::newTemplate("restful_controller_cc.csp");
|
||||
oSourceFile << templ->genText(data);
|
||||
} catch (const std::exception &err) {
|
||||
std::cerr << err.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
std::cout << "create a http restful API controller:" << className
|
||||
<< std::endl;
|
||||
std::cout << "file name: " << ctlName << ".h and " << ctlName << ".cc"
|
||||
<< std::endl;
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* create_controller.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CommandHandler.h"
|
||||
#include <drogon/DrObject.h>
|
||||
#include <drogon/DrTemplateBase.h>
|
||||
using namespace drogon;
|
||||
namespace drogon_ctl {
|
||||
class create_controller : public DrObject<create_controller>,
|
||||
public CommandHandler {
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
||||
virtual std::string script() override {
|
||||
return "create controller files";
|
||||
}
|
||||
|
||||
protected:
|
||||
enum ControllerType {
|
||||
Simple = 0,
|
||||
Http,
|
||||
WebSocket,
|
||||
Restful
|
||||
};
|
||||
|
||||
void createController(std::vector<std::string> &httpClasses,
|
||||
ControllerType type);
|
||||
void createController(const std::string &className, ControllerType type);
|
||||
void createARestfulController(const std::string &className,
|
||||
const std::string &resource);
|
||||
|
||||
void newSimpleControllerHeaderFile(std::ofstream &file,
|
||||
const std::string &className);
|
||||
void newSimpleControllerSourceFile(std::ofstream &file,
|
||||
const std::string &className,
|
||||
const std::string &filename);
|
||||
|
||||
void newWebsockControllerHeaderFile(std::ofstream &file,
|
||||
const std::string &className);
|
||||
void newWebsockControllerSourceFile(std::ofstream &file,
|
||||
const std::string &className,
|
||||
const std::string &filename);
|
||||
|
||||
void newHttpControllerHeaderFile(std::ofstream &file,
|
||||
const std::string &className);
|
||||
void newHttpControllerSourceFile(std::ofstream &file,
|
||||
const std::string &className,
|
||||
const std::string &filename);
|
||||
};
|
||||
} // namespace drogon_ctl
|
@ -1,103 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* create_filter.cc
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "create_filter.h"
|
||||
#include <drogon/DrTemplateBase.h>
|
||||
#include <drogon/utils/Utilities.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
using namespace drogon_ctl;
|
||||
|
||||
static void createFilterHeaderFile(std::ofstream &file,
|
||||
const std::string &className,
|
||||
const std::string &fileName) {
|
||||
auto templ = drogon::DrTemplateBase::newTemplate("filter_h");
|
||||
HttpViewData data;
|
||||
if (className.find("::") != std::string::npos) {
|
||||
auto namespaceVector = utils::splitString(className, "::");
|
||||
data.insert("className", namespaceVector.back());
|
||||
namespaceVector.pop_back();
|
||||
data.insert("namespaceVector", namespaceVector);
|
||||
} else {
|
||||
data.insert("className", className);
|
||||
}
|
||||
data.insert("filename", fileName);
|
||||
file << templ->genText(data);
|
||||
}
|
||||
|
||||
static void createFilterSourceFile(std::ofstream &file,
|
||||
const std::string &className,
|
||||
const std::string &fileName) {
|
||||
auto templ = drogon::DrTemplateBase::newTemplate("filter_cc");
|
||||
HttpViewData data;
|
||||
if (className.find("::") != std::string::npos) {
|
||||
auto pos = className.rfind("::");
|
||||
data.insert("namespaceString", className.substr(0, pos));
|
||||
data.insert("className", className.substr(pos + 2));
|
||||
} else {
|
||||
data.insert("className", className);
|
||||
}
|
||||
data.insert("filename", fileName);
|
||||
file << templ->genText(data);
|
||||
}
|
||||
void create_filter::handleCommand(std::vector<std::string> ¶meters) {
|
||||
if (parameters.size() < 1) {
|
||||
std::cout << "Invalid parameters!" << std::endl;
|
||||
}
|
||||
for (auto className : parameters) {
|
||||
std::regex regex("::");
|
||||
std::string fileName =
|
||||
std::regex_replace(className, regex, std::string("_"));
|
||||
|
||||
std::string headFileName = fileName + ".h";
|
||||
std::string sourceFilename = fileName + ".cc";
|
||||
{
|
||||
std::ifstream iHeadFile(headFileName.c_str(), std::ifstream::in);
|
||||
std::ifstream iSourceFile(sourceFilename.c_str(),
|
||||
std::ifstream::in);
|
||||
|
||||
if (iHeadFile || iSourceFile) {
|
||||
std::cout << "The file you want to create already exists, "
|
||||
"overwrite it(y/n)?"
|
||||
<< std::endl;
|
||||
auto in = getchar();
|
||||
(void)getchar(); // get the return key
|
||||
if (in != 'Y' && in != 'y') {
|
||||
std::cout << "Abort!" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::ofstream oHeadFile(headFileName.c_str(), std::ofstream::out);
|
||||
std::ofstream oSourceFile(sourceFilename.c_str(), std::ofstream::out);
|
||||
if (!oHeadFile || !oSourceFile) {
|
||||
perror("");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::cout << "create a http filter:" << className << std::endl;
|
||||
createFilterHeaderFile(oHeadFile, className, fileName);
|
||||
createFilterSourceFile(oSourceFile, className, fileName);
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* create_filter.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CommandHandler.h"
|
||||
#include <drogon/DrObject.h>
|
||||
using namespace drogon;
|
||||
namespace drogon_ctl {
|
||||
class create_filter : public DrObject<create_filter>, public CommandHandler {
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
||||
virtual std::string script() override {
|
||||
return "create filter class files";
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string outputPath_{ "." };
|
||||
};
|
||||
} // namespace drogon_ctl
|
File diff suppressed because it is too large
Load Diff
@ -1,345 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* create_model.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <drogon/DrTemplateBase.h>
|
||||
#include <drogon/config.h>
|
||||
#include <drogon/orm/DbClient.h>
|
||||
#include <json/json.h>
|
||||
using namespace drogon::orm;
|
||||
#include "CommandHandler.h"
|
||||
#include <drogon/DrObject.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
using namespace drogon;
|
||||
|
||||
namespace drogon_ctl {
|
||||
struct ColumnInfo {
|
||||
std::string colName_;
|
||||
std::string colValName_;
|
||||
std::string colTypeName_;
|
||||
std::string colType_;
|
||||
std::string colDatabaseType_;
|
||||
std::string dbType_;
|
||||
ssize_t colLength_{ 0 };
|
||||
size_t index_{ 0 };
|
||||
bool isAutoVal_{ false };
|
||||
bool isPrimaryKey_{ false };
|
||||
bool notNull_{ false };
|
||||
bool hasDefaultVal_{ false };
|
||||
};
|
||||
|
||||
inline std::string nameTransform(const std::string &origName, bool isType) {
|
||||
auto str = origName;
|
||||
std::transform(str.begin(), str.end(), str.begin(), tolower);
|
||||
std::string::size_type startPos = 0;
|
||||
std::string::size_type pos;
|
||||
std::string ret;
|
||||
do {
|
||||
pos = str.find("_", startPos);
|
||||
if (pos == std::string::npos) {
|
||||
pos = str.find(".", startPos);
|
||||
}
|
||||
if (pos != std::string::npos)
|
||||
ret += str.substr(startPos, pos - startPos);
|
||||
else {
|
||||
ret += str.substr(startPos);
|
||||
break;
|
||||
}
|
||||
while (str[pos] == '_' || str[pos] == '.')
|
||||
++pos;
|
||||
if (str[pos] >= 'a' && str[pos] <= 'z')
|
||||
str[pos] += ('A' - 'a');
|
||||
startPos = pos;
|
||||
} while (1);
|
||||
if (isType && ret[0] >= 'a' && ret[0] <= 'z')
|
||||
ret[0] += ('A' - 'a');
|
||||
return ret;
|
||||
}
|
||||
class PivotTable {
|
||||
public:
|
||||
PivotTable() = default;
|
||||
PivotTable(const Json::Value &json) :
|
||||
tableName_(json.get("table_name", "").asString()) {
|
||||
if (tableName_.empty()) {
|
||||
throw std::runtime_error("table_name can't be empty");
|
||||
}
|
||||
originalKey_ = json.get("original_key", "").asString();
|
||||
if (originalKey_.empty()) {
|
||||
throw std::runtime_error("original_key can't be empty");
|
||||
}
|
||||
targetKey_ = json.get("target_key", "").asString();
|
||||
if (targetKey_.empty()) {
|
||||
throw std::runtime_error("target_key can't be empty");
|
||||
}
|
||||
}
|
||||
PivotTable reverse() const {
|
||||
PivotTable pivot;
|
||||
pivot.tableName_ = tableName_;
|
||||
pivot.originalKey_ = targetKey_;
|
||||
pivot.targetKey_ = originalKey_;
|
||||
return pivot;
|
||||
}
|
||||
const std::string &tableName() const {
|
||||
return tableName_;
|
||||
}
|
||||
const std::string &originalKey() const {
|
||||
return originalKey_;
|
||||
}
|
||||
const std::string &targetKey() const {
|
||||
return targetKey_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string tableName_;
|
||||
std::string originalKey_;
|
||||
std::string targetKey_;
|
||||
};
|
||||
|
||||
class ConvertMethod {
|
||||
public:
|
||||
ConvertMethod(const Json::Value &convert) {
|
||||
tableName_ = convert.get("table", "*").asString();
|
||||
colName_ = convert.get("column", "*").asString();
|
||||
|
||||
auto method = convert["method"];
|
||||
if (method.isNull()) {
|
||||
throw std::runtime_error("method - object is missing.");
|
||||
} // endif
|
||||
if (!method.isObject()) {
|
||||
throw std::runtime_error("method is not an object.");
|
||||
} // endif
|
||||
methodBeforeDbWrite_ = method.get("before_db_write", "").asString();
|
||||
methodAfterDbRead_ = method.get("after_db_read", "").asString();
|
||||
|
||||
auto includeFiles = convert["includes"];
|
||||
if (includeFiles.isNull()) {
|
||||
return;
|
||||
} // endif
|
||||
if (!includeFiles.isArray()) {
|
||||
throw std::runtime_error("includes must be an array");
|
||||
} // endif
|
||||
for (auto &i : includeFiles) {
|
||||
includeFiles_.push_back(i.asString());
|
||||
} // for
|
||||
}
|
||||
ConvertMethod() = default;
|
||||
|
||||
bool shouldConvert(const std::string &tableName,
|
||||
const std::string &colName) const;
|
||||
|
||||
const std::string &tableName() const {
|
||||
return tableName_;
|
||||
}
|
||||
const std::string &colName() const {
|
||||
return colName_;
|
||||
}
|
||||
const std::string &methodBeforeDbWrite() const {
|
||||
return methodBeforeDbWrite_;
|
||||
}
|
||||
const std::string &methodAfterDbRead() const {
|
||||
return methodAfterDbRead_;
|
||||
}
|
||||
const std::vector<std::string> &includeFiles() const {
|
||||
return includeFiles_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string tableName_{ "*" };
|
||||
std::string colName_{ "*" };
|
||||
std::string methodBeforeDbWrite_;
|
||||
std::string methodAfterDbRead_;
|
||||
std::vector<std::string> includeFiles_;
|
||||
};
|
||||
|
||||
class Relationship {
|
||||
public:
|
||||
enum class Type {
|
||||
HasOne,
|
||||
HasMany,
|
||||
ManyToMany
|
||||
};
|
||||
Relationship(const Json::Value &relationship) {
|
||||
auto type = relationship.get("type", "has one").asString();
|
||||
if (type == "has one") {
|
||||
type_ = Relationship::Type::HasOne;
|
||||
} else if (type == "has many") {
|
||||
type_ = Relationship::Type::HasMany;
|
||||
} else if (type == "many to many") {
|
||||
type_ = Relationship::Type::ManyToMany;
|
||||
} else {
|
||||
char message[128];
|
||||
snprintf(message,
|
||||
sizeof(message),
|
||||
"Invalid relationship type: %s",
|
||||
type.data());
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
originalTableName_ =
|
||||
relationship.get("original_table_name", "").asString();
|
||||
if (originalTableName_.empty()) {
|
||||
throw std::runtime_error("original_table_name can't be empty");
|
||||
}
|
||||
originalKey_ = relationship.get("original_key", "").asString();
|
||||
if (originalKey_.empty()) {
|
||||
throw std::runtime_error("original_key can't be empty");
|
||||
}
|
||||
originalTableAlias_ =
|
||||
relationship.get("original_table_alias", "").asString();
|
||||
targetTableName_ = relationship.get("target_table_name", "").asString();
|
||||
if (targetTableName_.empty()) {
|
||||
throw std::runtime_error("target_table_name can't be empty");
|
||||
}
|
||||
targetKey_ = relationship.get("target_key", "").asString();
|
||||
if (targetKey_.empty()) {
|
||||
throw std::runtime_error("target_key can't be empty");
|
||||
}
|
||||
targetTableAlias_ =
|
||||
relationship.get("target_table_alias", "").asString();
|
||||
enableReverse_ = relationship.get("enable_reverse", false).asBool();
|
||||
if (type_ == Type::ManyToMany) {
|
||||
auto &pivot = relationship["pivot_table"];
|
||||
if (pivot.isNull()) {
|
||||
throw std::runtime_error(
|
||||
"ManyToMany relationship needs a pivot table");
|
||||
}
|
||||
pivotTable_ = PivotTable(pivot);
|
||||
}
|
||||
}
|
||||
Relationship() = default;
|
||||
Relationship reverse() const {
|
||||
Relationship r;
|
||||
if (type_ == Type::HasMany) {
|
||||
r.type_ = Type::HasOne;
|
||||
} else {
|
||||
r.type_ = type_;
|
||||
}
|
||||
r.originalTableName_ = targetTableName_;
|
||||
r.originalTableAlias_ = targetTableAlias_;
|
||||
r.originalKey_ = targetKey_;
|
||||
r.targetTableName_ = originalTableName_;
|
||||
r.targetTableAlias_ = originalTableAlias_;
|
||||
r.targetKey_ = originalKey_;
|
||||
r.enableReverse_ = enableReverse_;
|
||||
r.pivotTable_ = pivotTable_.reverse();
|
||||
return r;
|
||||
}
|
||||
Type type() const {
|
||||
return type_;
|
||||
}
|
||||
bool enableReverse() const {
|
||||
return enableReverse_;
|
||||
}
|
||||
const std::string &originalTableName() const {
|
||||
return originalTableName_;
|
||||
}
|
||||
const std::string &originalTableAlias() const {
|
||||
return originalTableAlias_;
|
||||
}
|
||||
const std::string &originalKey() const {
|
||||
return originalKey_;
|
||||
}
|
||||
const std::string &targetTableName() const {
|
||||
return targetTableName_;
|
||||
}
|
||||
const std::string &targetTableAlias() const {
|
||||
return targetTableAlias_;
|
||||
}
|
||||
const std::string &targetKey() const {
|
||||
return targetKey_;
|
||||
}
|
||||
const PivotTable &pivotTable() const {
|
||||
return pivotTable_;
|
||||
}
|
||||
|
||||
private:
|
||||
Type type_{ Type::HasOne };
|
||||
std::string originalTableName_;
|
||||
std::string originalTableAlias_;
|
||||
std::string targetTableName_;
|
||||
std::string targetTableAlias_;
|
||||
std::string originalKey_;
|
||||
std::string targetKey_;
|
||||
bool enableReverse_{ false };
|
||||
PivotTable pivotTable_;
|
||||
};
|
||||
class create_model : public DrObject<create_model>, public CommandHandler {
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
||||
virtual std::string script() override {
|
||||
return "create Model classes files";
|
||||
}
|
||||
|
||||
protected:
|
||||
void createModel(const std::string &path,
|
||||
const std::string &singleModelName);
|
||||
void createModel(const std::string &path,
|
||||
const Json::Value &config,
|
||||
const std::string &singleModelName);
|
||||
#if USE_POSTGRESQL
|
||||
void createModelClassFromPG(
|
||||
const std::string &path,
|
||||
const DbClientPtr &client,
|
||||
const std::string &tableName,
|
||||
const std::string &schema,
|
||||
const Json::Value &restfulApiConfig,
|
||||
const std::vector<Relationship> &relationships,
|
||||
const std::vector<ConvertMethod> &convertMethods);
|
||||
|
||||
void createModelFromPG(
|
||||
const std::string &path,
|
||||
const DbClientPtr &client,
|
||||
const std::string &schema,
|
||||
const Json::Value &restfulApiConfig,
|
||||
std::map<std::string, std::vector<Relationship> > &relationships,
|
||||
std::map<std::string, std::vector<ConvertMethod> > &convertMethods);
|
||||
#endif
|
||||
#if USE_MYSQL
|
||||
void createModelClassFromMysql(
|
||||
const std::string &path,
|
||||
const DbClientPtr &client,
|
||||
const std::string &tableName,
|
||||
const Json::Value &restfulApiConfig,
|
||||
const std::vector<Relationship> &relationships,
|
||||
const std::vector<ConvertMethod> &convertMethods);
|
||||
void createModelFromMysql(
|
||||
const std::string &path,
|
||||
const DbClientPtr &client,
|
||||
const Json::Value &restfulApiConfig,
|
||||
std::map<std::string, std::vector<Relationship> > &relationships,
|
||||
std::map<std::string, std::vector<ConvertMethod> > &convertMethods);
|
||||
#endif
|
||||
#if USE_SQLITE3
|
||||
void createModelClassFromSqlite3(
|
||||
const std::string &path,
|
||||
const DbClientPtr &client,
|
||||
const std::string &tableName,
|
||||
const Json::Value &restfulApiConfig,
|
||||
const std::vector<Relationship> &relationships,
|
||||
const std::vector<ConvertMethod> &convertMethod);
|
||||
void createModelFromSqlite3(
|
||||
const std::string &path,
|
||||
const DbClientPtr &client,
|
||||
const Json::Value &restfulApiConfig,
|
||||
std::map<std::string, std::vector<Relationship> > &relationships,
|
||||
std::map<std::string, std::vector<ConvertMethod> > &convertMethod);
|
||||
#endif
|
||||
void createRestfulAPIController(const DrTemplateData &tableInfo,
|
||||
const Json::Value &restfulApiConfig);
|
||||
std::string dbname_;
|
||||
bool forceOverwrite_{ false };
|
||||
};
|
||||
} // namespace drogon_ctl
|
@ -1,103 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* create_plugin.cc
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "create_plugin.h"
|
||||
#include <drogon/DrTemplateBase.h>
|
||||
#include <drogon/utils/Utilities.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
using namespace drogon_ctl;
|
||||
|
||||
static void createPluginHeaderFile(std::ofstream &file,
|
||||
const std::string &className,
|
||||
const std::string &fileName) {
|
||||
auto templ = drogon::DrTemplateBase::newTemplate("plugin_h");
|
||||
HttpViewData data;
|
||||
if (className.find("::") != std::string::npos) {
|
||||
auto namespaceVector = utils::splitString(className, "::");
|
||||
data.insert("className", namespaceVector.back());
|
||||
namespaceVector.pop_back();
|
||||
data.insert("namespaceVector", namespaceVector);
|
||||
} else {
|
||||
data.insert("className", className);
|
||||
}
|
||||
data.insert("filename", fileName);
|
||||
file << templ->genText(data);
|
||||
}
|
||||
|
||||
static void createPluginSourceFile(std::ofstream &file,
|
||||
const std::string &className,
|
||||
const std::string &fileName) {
|
||||
auto templ = drogon::DrTemplateBase::newTemplate("plugin_cc");
|
||||
HttpViewData data;
|
||||
if (className.find("::") != std::string::npos) {
|
||||
auto pos = className.rfind("::");
|
||||
data.insert("namespaceString", className.substr(0, pos));
|
||||
data.insert("className", className.substr(pos + 2));
|
||||
} else {
|
||||
data.insert("className", className);
|
||||
}
|
||||
data.insert("filename", fileName);
|
||||
file << templ->genText(data);
|
||||
}
|
||||
void create_plugin::handleCommand(std::vector<std::string> ¶meters) {
|
||||
if (parameters.size() < 1) {
|
||||
std::cout << "Invalid parameters!" << std::endl;
|
||||
}
|
||||
for (auto className : parameters) {
|
||||
std::regex regex("::");
|
||||
std::string fileName =
|
||||
std::regex_replace(className, regex, std::string("_"));
|
||||
|
||||
std::string headFileName = fileName + ".h";
|
||||
std::string sourceFilename = fileName + ".cc";
|
||||
{
|
||||
std::ifstream iHeadFile(headFileName.c_str(), std::ifstream::in);
|
||||
std::ifstream iSourceFile(sourceFilename.c_str(),
|
||||
std::ifstream::in);
|
||||
|
||||
if (iHeadFile || iSourceFile) {
|
||||
std::cout << "The file you want to create already exists, "
|
||||
"overwrite it(y/n)?"
|
||||
<< std::endl;
|
||||
auto in = getchar();
|
||||
(void)getchar(); // get the return key
|
||||
if (in != 'Y' && in != 'y') {
|
||||
std::cout << "Abort!" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::ofstream oHeadFile(headFileName.c_str(), std::ofstream::out);
|
||||
std::ofstream oSourceFile(sourceFilename.c_str(), std::ofstream::out);
|
||||
if (!oHeadFile || !oSourceFile) {
|
||||
perror("");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::cout << "create a plugin:" << className << std::endl;
|
||||
createPluginHeaderFile(oHeadFile, className, fileName);
|
||||
createPluginSourceFile(oSourceFile, className, fileName);
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* create_plugin.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CommandHandler.h"
|
||||
#include <drogon/DrObject.h>
|
||||
using namespace drogon;
|
||||
namespace drogon_ctl {
|
||||
class create_plugin : public DrObject<create_plugin>, public CommandHandler {
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
||||
virtual std::string script() override {
|
||||
return "create plugin class files";
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string outputPath_{ "." };
|
||||
};
|
||||
} // namespace drogon_ctl
|
@ -1,102 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* create_project.cc
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "create_project.h"
|
||||
#include <drogon/DrTemplateBase.h>
|
||||
#include <drogon/utils/Utilities.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <iostream>
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <fstream>
|
||||
|
||||
using namespace drogon_ctl;
|
||||
|
||||
void create_project::handleCommand(std::vector<std::string> ¶meters) {
|
||||
if (parameters.size() < 1) {
|
||||
std::cout << "please input project name" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
auto pName = parameters[0];
|
||||
createProject(pName);
|
||||
}
|
||||
static void newCmakeFile(std::ofstream &cmakeFile,
|
||||
const std::string &projectName) {
|
||||
HttpViewData data;
|
||||
data.insert("ProjectName", projectName);
|
||||
auto templ = DrTemplateBase::newTemplate("cmake.csp");
|
||||
cmakeFile << templ->genText(data);
|
||||
}
|
||||
static void newMainFile(std::ofstream &mainFile) {
|
||||
auto templ = DrTemplateBase::newTemplate("demoMain");
|
||||
mainFile << templ->genText();
|
||||
}
|
||||
static void newGitIgFile(std::ofstream &gitFile) {
|
||||
auto templ = DrTemplateBase::newTemplate("gitignore.csp");
|
||||
gitFile << templ->genText();
|
||||
}
|
||||
|
||||
static void newConfigFile(std::ofstream &configFile) {
|
||||
auto templ = DrTemplateBase::newTemplate("config");
|
||||
configFile << templ->genText();
|
||||
}
|
||||
static void newModelConfigFile(std::ofstream &configFile) {
|
||||
auto templ = DrTemplateBase::newTemplate("model_json");
|
||||
configFile << templ->genText();
|
||||
}
|
||||
void create_project::createProject(const std::string &projectName) {
|
||||
#ifdef _WIN32
|
||||
if (_access(projectName.data(), 0) == 0)
|
||||
#else
|
||||
if (access(projectName.data(), 0) == 0)
|
||||
#endif
|
||||
{
|
||||
std::cerr
|
||||
<< "The directory already exists, please use another project name!"
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
std::cout << "create a project named " << projectName << std::endl;
|
||||
|
||||
drogon::utils::createPath(projectName);
|
||||
// 1.create CMakeLists.txt
|
||||
#ifdef _WIN32
|
||||
auto r = _chdir(projectName.data());
|
||||
#else
|
||||
auto r = chdir(projectName.data());
|
||||
#endif
|
||||
(void)(r);
|
||||
std::ofstream cmakeFile("CMakeLists.txt", std::ofstream::out);
|
||||
newCmakeFile(cmakeFile, projectName);
|
||||
std::ofstream mainFile("main.cc", std::ofstream::out);
|
||||
newMainFile(mainFile);
|
||||
drogon::utils::createPath("views");
|
||||
drogon::utils::createPath("controllers");
|
||||
drogon::utils::createPath("filters");
|
||||
drogon::utils::createPath("plugins");
|
||||
drogon::utils::createPath("build");
|
||||
drogon::utils::createPath("models");
|
||||
|
||||
std::ofstream gitFile(".gitignore", std::ofstream::out);
|
||||
newGitIgFile(gitFile);
|
||||
std::ofstream configFile("config.json", std::ofstream::out);
|
||||
newConfigFile(configFile);
|
||||
std::ofstream modelConfigFile("models/model.json", std::ofstream::out);
|
||||
newModelConfigFile(modelConfigFile);
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* create_project.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CommandHandler.h"
|
||||
#include <drogon/DrObject.h>
|
||||
using namespace drogon;
|
||||
namespace drogon_ctl {
|
||||
class create_project : public DrObject<create_project>, public CommandHandler {
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
||||
virtual std::string script() override {
|
||||
return "create a project";
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string outputPath_{ "." };
|
||||
void createProject(const std::string &projectName);
|
||||
};
|
||||
} // namespace drogon_ctl
|
@ -1,456 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* @file create_view.cc
|
||||
* @author An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "create_view.h"
|
||||
#include "cmd.h"
|
||||
#include <drogon/utils/Utilities.h>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
static const std::string cxx_include = "<%inc";
|
||||
static const std::string cxx_end = "%>";
|
||||
static const std::string cxx_lang = "<%c++";
|
||||
static const std::string cxx_view_data = "@@";
|
||||
static const std::string cxx_output = "$$";
|
||||
static const std::string cxx_val_start = "[[";
|
||||
static const std::string cxx_val_end = "]]";
|
||||
static const std::string sub_view_start = "<%view";
|
||||
static const std::string sub_view_end = "%>";
|
||||
|
||||
using namespace drogon_ctl;
|
||||
|
||||
static std::string &replace_all(std::string &str,
|
||||
const std::string &old_value,
|
||||
const std::string &new_value) {
|
||||
std::string::size_type pos(0);
|
||||
while (true) {
|
||||
// std::cout<<str<<endl;
|
||||
// std::cout<<"pos="<<pos<<endl;
|
||||
if ((pos = str.find(old_value, pos)) != std::string::npos) {
|
||||
str = str.replace(pos, old_value.length(), new_value);
|
||||
pos += new_value.length() - old_value.length();
|
||||
++pos;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
static void parseCxxLine(std::ofstream &oSrcFile,
|
||||
const std::string &line,
|
||||
const std::string &streamName,
|
||||
const std::string &viewDataName) {
|
||||
if (line.length() > 0) {
|
||||
std::string tmp = line;
|
||||
replace_all(tmp, cxx_output, streamName);
|
||||
replace_all(tmp, cxx_view_data, viewDataName);
|
||||
oSrcFile << tmp << "\n";
|
||||
}
|
||||
}
|
||||
static void outputVal(std::ofstream &oSrcFile,
|
||||
const std::string &streamName,
|
||||
const std::string &viewDataName,
|
||||
const std::string &keyName) {
|
||||
oSrcFile << "{\n";
|
||||
oSrcFile << " auto & val=" << viewDataName << "[\"" << keyName
|
||||
<< "\"];\n";
|
||||
oSrcFile << " if(val.type()==typeid(const char *)){\n";
|
||||
oSrcFile << " " << streamName
|
||||
<< "<<*any_cast<const char *>(&val);\n";
|
||||
oSrcFile << " }else "
|
||||
"if(val.type()==typeid(std::string)||val.type()==typeid(const "
|
||||
"std::string)){\n";
|
||||
oSrcFile << " " << streamName
|
||||
<< "<<*any_cast<const std::string>(&val);\n";
|
||||
oSrcFile << " }\n";
|
||||
oSrcFile << "}\n";
|
||||
}
|
||||
|
||||
static void outputSubView(std::ofstream &oSrcFile,
|
||||
const std::string &streamName,
|
||||
const std::string &viewDataName,
|
||||
const std::string &keyName) {
|
||||
oSrcFile << "{\n";
|
||||
oSrcFile << " auto templ=DrTemplateBase::newTemplate(\"" << keyName
|
||||
<< "\");\n";
|
||||
oSrcFile << " if(templ){\n";
|
||||
oSrcFile << " " << streamName << "<< templ->genText(" << viewDataName
|
||||
<< ");\n";
|
||||
oSrcFile << " }\n";
|
||||
oSrcFile << "}\n";
|
||||
}
|
||||
|
||||
static void parseLine(std::ofstream &oSrcFile,
|
||||
std::string &line,
|
||||
const std::string &streamName,
|
||||
const std::string &viewDataName,
|
||||
int &cxx_flag,
|
||||
int returnFlag = 1) {
|
||||
std::string::size_type pos(0);
|
||||
// std::cout<<line<<"("<<line.length()<<")\n";
|
||||
if (line.length() > 0 && line[line.length() - 1] == '\r') {
|
||||
line.resize(line.length() - 1);
|
||||
}
|
||||
if (line.length() == 0) {
|
||||
// std::cout<<"blank line!"<<std::endl;
|
||||
// std::cout<<streamName<<"<<\"\\n\";\n";
|
||||
if (returnFlag)
|
||||
oSrcFile << streamName << "<<\"\\n\";\n";
|
||||
return;
|
||||
}
|
||||
if (cxx_flag == 0) {
|
||||
// find cxx lang begin
|
||||
if ((pos = line.find(cxx_lang)) != std::string::npos) {
|
||||
std::string oldLine = line.substr(0, pos);
|
||||
if (oldLine.length() > 0)
|
||||
parseLine(
|
||||
oSrcFile, oldLine, streamName, viewDataName, cxx_flag, 0);
|
||||
std::string newLine = line.substr(pos + cxx_lang.length());
|
||||
cxx_flag = 1;
|
||||
if (newLine.length() > 0)
|
||||
parseLine(oSrcFile,
|
||||
newLine,
|
||||
streamName,
|
||||
viewDataName,
|
||||
cxx_flag,
|
||||
returnFlag);
|
||||
} else {
|
||||
if ((pos = line.find(cxx_val_start)) != std::string::npos) {
|
||||
std::string oldLine = line.substr(0, pos);
|
||||
parseLine(
|
||||
oSrcFile, oldLine, streamName, viewDataName, cxx_flag, 0);
|
||||
std::string newLine = line.substr(pos + cxx_val_start.length());
|
||||
if ((pos = newLine.find(cxx_val_end)) != std::string::npos) {
|
||||
std::string keyName = newLine.substr(0, pos);
|
||||
auto iter = keyName.begin();
|
||||
while (iter != keyName.end() && *iter == ' ')
|
||||
++iter;
|
||||
auto iterEnd = iter;
|
||||
while (iterEnd != keyName.end() && *iterEnd != ' ')
|
||||
++iterEnd;
|
||||
keyName = std::string(iter, iterEnd);
|
||||
outputVal(oSrcFile, streamName, viewDataName, keyName);
|
||||
std::string tailLine =
|
||||
newLine.substr(pos + cxx_val_end.length());
|
||||
parseLine(oSrcFile,
|
||||
tailLine,
|
||||
streamName,
|
||||
viewDataName,
|
||||
cxx_flag,
|
||||
returnFlag);
|
||||
} else {
|
||||
std::cerr << "format err!" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
} else if ((pos = line.find(sub_view_start)) != std::string::npos) {
|
||||
std::string oldLine = line.substr(0, pos);
|
||||
parseLine(
|
||||
oSrcFile, oldLine, streamName, viewDataName, cxx_flag, 0);
|
||||
std::string newLine =
|
||||
line.substr(pos + sub_view_start.length());
|
||||
if ((pos = newLine.find(sub_view_end)) != std::string::npos) {
|
||||
std::string keyName = newLine.substr(0, pos);
|
||||
auto iter = keyName.begin();
|
||||
while (iter != keyName.end() && *iter == ' ')
|
||||
++iter;
|
||||
auto iterEnd = iter;
|
||||
while (iterEnd != keyName.end() && *iterEnd != ' ')
|
||||
++iterEnd;
|
||||
keyName = std::string(iter, iterEnd);
|
||||
outputSubView(oSrcFile, streamName, viewDataName, keyName);
|
||||
std::string tailLine =
|
||||
newLine.substr(pos + sub_view_end.length());
|
||||
parseLine(oSrcFile,
|
||||
tailLine,
|
||||
streamName,
|
||||
viewDataName,
|
||||
cxx_flag,
|
||||
returnFlag);
|
||||
} else {
|
||||
std::cerr << "format err!" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if (line.length() > 0) {
|
||||
replace_all(line, "\\", "\\\\");
|
||||
replace_all(line, "\"", "\\\"");
|
||||
oSrcFile << "\t" << streamName << " << \"" << line;
|
||||
}
|
||||
if (returnFlag)
|
||||
oSrcFile << "\\n\";\n";
|
||||
else
|
||||
oSrcFile << "\";\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((pos = line.find(cxx_end)) != std::string::npos) {
|
||||
std::string newLine = line.substr(0, pos);
|
||||
parseCxxLine(oSrcFile, newLine, streamName, viewDataName);
|
||||
std::string oldLine = line.substr(pos + cxx_end.length());
|
||||
cxx_flag = 0;
|
||||
if (oldLine.length() > 0)
|
||||
parseLine(oSrcFile,
|
||||
oldLine,
|
||||
streamName,
|
||||
viewDataName,
|
||||
cxx_flag,
|
||||
returnFlag);
|
||||
} else {
|
||||
parseCxxLine(oSrcFile, line, streamName, viewDataName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void create_view::handleCommand(std::vector<std::string> ¶meters) {
|
||||
for (auto iter = parameters.begin(); iter != parameters.end();) {
|
||||
auto &file = *iter;
|
||||
if (file == "-o" || file == "--output") {
|
||||
iter = parameters.erase(iter);
|
||||
if (iter != parameters.end()) {
|
||||
outputPath_ = *iter;
|
||||
iter = parameters.erase(iter);
|
||||
}
|
||||
continue;
|
||||
} else if (file == "-n" || file == "--namespace") {
|
||||
iter = parameters.erase(iter);
|
||||
if (iter != parameters.end()) {
|
||||
namespaces_ = utils::splitString(*iter, "::");
|
||||
iter = parameters.erase(iter);
|
||||
}
|
||||
continue;
|
||||
} else if (file == "--path-to-namespace") {
|
||||
iter = parameters.erase(iter);
|
||||
pathToNamespaceFlag_ = true;
|
||||
continue;
|
||||
} else if (file[0] == '-') {
|
||||
std::cout << ARGS_ERROR_STR << std::endl;
|
||||
return;
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
createViewFiles(parameters);
|
||||
}
|
||||
void create_view::createViewFiles(std::vector<std::string> &cspFileNames) {
|
||||
for (auto const &file : cspFileNames) {
|
||||
std::cout << "create view:" << file << std::endl;
|
||||
createViewFile(file);
|
||||
}
|
||||
}
|
||||
int create_view::createViewFile(const std::string &script_filename) {
|
||||
std::cout << "create HttpView Class file by " << script_filename
|
||||
<< std::endl;
|
||||
if (pathToNamespaceFlag_) {
|
||||
std::string::size_type pos1 = 0, pos2 = 0;
|
||||
if (script_filename.length() >= 2 && script_filename[0] == '.' &&
|
||||
(script_filename[1] == '/' || script_filename[1] == '\\')) {
|
||||
pos1 = pos2 = 2;
|
||||
} else if (script_filename.length() >= 1 &&
|
||||
(script_filename[0] == '/' || script_filename[0] == '\\')) {
|
||||
pos1 = pos2 = 1;
|
||||
}
|
||||
while (pos2 < script_filename.length() - 1) {
|
||||
if (script_filename[pos2] == '/' || script_filename[pos2] == '\\') {
|
||||
if (pos2 > pos1) {
|
||||
namespaces_.push_back(
|
||||
script_filename.substr(pos1, pos2 - pos1));
|
||||
}
|
||||
pos1 = ++pos2;
|
||||
} else {
|
||||
++pos2;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string npPrefix;
|
||||
for (auto &np : namespaces_) {
|
||||
npPrefix += np;
|
||||
npPrefix += "_";
|
||||
}
|
||||
std::ifstream infile(script_filename.c_str(), std::ifstream::in);
|
||||
if (infile) {
|
||||
std::string::size_type pos = script_filename.rfind('.');
|
||||
if (pos != std::string::npos) {
|
||||
std::string className = script_filename.substr(0, pos);
|
||||
if ((pos = className.rfind('/')) != std::string::npos) {
|
||||
className = className.substr(pos + 1);
|
||||
}
|
||||
std::cout << "className=" << className << std::endl;
|
||||
std::string headFileName =
|
||||
outputPath_ + "/" + npPrefix + className + ".h";
|
||||
std::string sourceFilename =
|
||||
outputPath_ + "/" + npPrefix + className + ".cc";
|
||||
std::ofstream oHeadFile(headFileName.c_str(), std::ofstream::out);
|
||||
std::ofstream oSourceFile(sourceFilename.c_str(),
|
||||
std::ofstream::out);
|
||||
if (!oHeadFile || !oSourceFile) {
|
||||
std::cerr << "Can't open " << headFileName << " or "
|
||||
<< sourceFilename << "\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
newViewHeaderFile(oHeadFile, className);
|
||||
newViewSourceFile(oSourceFile, className, npPrefix, infile);
|
||||
} else
|
||||
return -1;
|
||||
} else {
|
||||
std::cerr << "can't open file " << script_filename << std::endl;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void create_view::newViewHeaderFile(std::ofstream &file,
|
||||
const std::string &className) {
|
||||
file << "//this file is generated by program automatically,don't modify "
|
||||
"it!\n";
|
||||
file << "#include <drogon/DrTemplate.h>\n";
|
||||
for (auto &np : namespaces_) {
|
||||
file << "namespace " << np << "\n";
|
||||
file << "{\n";
|
||||
}
|
||||
file << "class " << className << ":public drogon::DrTemplate<" << className
|
||||
<< ">\n";
|
||||
file << "{\npublic:\n\t" << className << "(){};\n\tvirtual ~" << className
|
||||
<< "(){};\n\t"
|
||||
"virtual std::string genText(const drogon::DrTemplateData &) "
|
||||
"override;\n};\n";
|
||||
for (std::size_t i = 0; i < namespaces_.size(); ++i) {
|
||||
file << "}\n";
|
||||
}
|
||||
}
|
||||
|
||||
void create_view::newViewSourceFile(std::ofstream &file,
|
||||
const std::string &className,
|
||||
const std::string &namespacePrefix,
|
||||
std::ifstream &infile) {
|
||||
file << "//this file is generated by program(drogon_ctl) "
|
||||
"automatically,don't modify it!\n";
|
||||
file << "#include \"" << namespacePrefix << className << ".h\"\n";
|
||||
file << "#include <drogon/utils/OStringStream.h>\n";
|
||||
file << "#include <string>\n";
|
||||
file << "#include <map>\n";
|
||||
file << "#include <vector>\n";
|
||||
file << "#include <set>\n";
|
||||
file << "#include <iostream>\n";
|
||||
file << "#include <unordered_map>\n";
|
||||
file << "#include <unordered_set>\n";
|
||||
file << "#include <algorithm>\n";
|
||||
file << "#include <list>\n";
|
||||
file << "#include <deque>\n";
|
||||
file << "#include <queue>\n";
|
||||
|
||||
// Find layout tag
|
||||
std::string layoutName;
|
||||
std::regex layoutReg("<%layout[ \\t]+(((?!%\\}).)*[^ \\t])[ \\t]*%>");
|
||||
for (std::string buffer; std::getline(infile, buffer);) {
|
||||
std::smatch results;
|
||||
if (std::regex_search(buffer, results, layoutReg)) {
|
||||
if (results.size() > 1) {
|
||||
layoutName = results[1].str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
infile.clear();
|
||||
infile.seekg(0, std::ifstream::beg);
|
||||
bool import_flag{ false };
|
||||
for (std::string buffer; std::getline(infile, buffer);) {
|
||||
std::string::size_type pos(0);
|
||||
|
||||
if (!import_flag) {
|
||||
std::string lowerBuffer = buffer;
|
||||
std::transform(lowerBuffer.begin(),
|
||||
lowerBuffer.end(),
|
||||
lowerBuffer.begin(),
|
||||
::tolower);
|
||||
if ((pos = lowerBuffer.find(cxx_include)) != std::string::npos) {
|
||||
// std::cout<<"haha find it!"<<endl;
|
||||
std::string newLine = buffer.substr(pos + cxx_include.length());
|
||||
import_flag = true;
|
||||
if ((pos = newLine.find(cxx_end)) != std::string::npos) {
|
||||
newLine = newLine.substr(0, pos);
|
||||
file << newLine << "\n";
|
||||
break;
|
||||
} else {
|
||||
file << newLine << "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// std::cout<<buffer<<endl;
|
||||
if ((pos = buffer.find(cxx_end)) != std::string::npos) {
|
||||
std::string newLine = buffer.substr(0, pos);
|
||||
file << newLine << "\n";
|
||||
break;
|
||||
} else {
|
||||
// std::cout<<"to source file"<<buffer<<endl;
|
||||
file << buffer << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// std::cout<<"import_flag="<<import_flag<<std::endl;
|
||||
if (!import_flag) {
|
||||
infile.clear();
|
||||
infile.seekg(0, std::ifstream::beg);
|
||||
}
|
||||
|
||||
if (!namespaces_.empty()) {
|
||||
file << "using namespace ";
|
||||
for (std::size_t i = 0; i < namespaces_.size(); ++i) {
|
||||
if (i != namespaces_.size() - 1) {
|
||||
file << namespaces_[i] << "::";
|
||||
} else {
|
||||
file << namespaces_[i] << ";";
|
||||
}
|
||||
}
|
||||
file << "\n";
|
||||
}
|
||||
file << "using namespace drogon;\n";
|
||||
std::string viewDataName = className + "_view_data";
|
||||
// virtual std::string genText(const DrTemplateData &)
|
||||
file << "std::string " << className << "::genText(const DrTemplateData& "
|
||||
<< viewDataName << ")\n{\n";
|
||||
// std::string bodyName=className+"_bodystr";
|
||||
std::string streamName = className + "_tmp_stream";
|
||||
|
||||
// oSrcFile <<"\tstd::string "<<bodyName<<";\n";
|
||||
file << "\tdrogon::OStringStream " << streamName << ";\n";
|
||||
file << "\tstd::string layoutName{\"" << layoutName << "\"};\n";
|
||||
int cxx_flag = 0;
|
||||
for (std::string buffer; std::getline(infile, buffer);) {
|
||||
if (buffer.length() > 0) {
|
||||
std::smatch results;
|
||||
if (std::regex_search(buffer, results, layoutReg)) {
|
||||
if (results.size() > 1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::regex re("\\{%[ \\t]*(((?!%\\}).)*[^ \\t])[ \\t]*%\\}");
|
||||
buffer = std::regex_replace(buffer, re, "<%c++$$$$<<$1;%>");
|
||||
}
|
||||
parseLine(file, buffer, streamName, viewDataName, cxx_flag);
|
||||
}
|
||||
file << "if(layoutName.empty())\n{\n";
|
||||
file << "std::string ret{std::move(" << streamName << ".str())};\n";
|
||||
file << "return ret;\n}else\n{\n";
|
||||
file << "auto templ = DrTemplateBase::newTemplate(layoutName);\n";
|
||||
file << "if(!templ) return \"\";\n";
|
||||
file << "HttpViewData data = " << viewDataName << ";\n";
|
||||
file << "auto str = std::move(" << streamName << ".str());\n";
|
||||
file << "if(!str.empty() && str[str.length()-1] == '\\n') "
|
||||
"str.resize(str.length()-1);\n";
|
||||
file << "data[\"\"] = std::move(str);\n";
|
||||
file << "return templ->genText(data);\n";
|
||||
file << "}\n}\n";
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* @file create_view.h
|
||||
* @author An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CommandHandler.h"
|
||||
#include <drogon/DrObject.h>
|
||||
using namespace drogon;
|
||||
namespace drogon_ctl {
|
||||
class create_view : public DrObject<create_view>, public CommandHandler {
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
||||
virtual std::string script() override {
|
||||
return "create view class files";
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string outputPath_{ "." };
|
||||
std::vector<std::string> namespaces_;
|
||||
bool pathToNamespaceFlag_{ false };
|
||||
void createViewFiles(std::vector<std::string> &cspFileNames);
|
||||
int createViewFile(const std::string &script_filename);
|
||||
void newViewHeaderFile(std::ofstream &file, const std::string &className);
|
||||
void newViewSourceFile(std::ofstream &file,
|
||||
const std::string &className,
|
||||
const std::string &namespacePrefix,
|
||||
std::ifstream &infile);
|
||||
};
|
||||
} // namespace drogon_ctl
|
@ -1,59 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* help.cc
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "help.h"
|
||||
#include <drogon/DrClassMap.h>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
using namespace drogon_ctl;
|
||||
void help::handleCommand(std::vector<std::string> ¶meters) {
|
||||
if (parameters.size() == 0) {
|
||||
std::cout << "usage: drogon_ctl [-v | --version] [-h | --help] "
|
||||
"<command> [<args>]"
|
||||
<< std::endl;
|
||||
std::cout << "commands list:" << std::endl;
|
||||
for (auto &className : drogon::DrClassMap::getAllClassName()) {
|
||||
auto classPtr = std::shared_ptr<DrObjectBase>(
|
||||
drogon::DrClassMap::newObject(className));
|
||||
if (classPtr) {
|
||||
auto cmdHdlPtr =
|
||||
std::dynamic_pointer_cast<CommandHandler>(classPtr);
|
||||
if (cmdHdlPtr) {
|
||||
if (!cmdHdlPtr->isTopCommand())
|
||||
continue;
|
||||
auto pos = className.rfind("::");
|
||||
if (pos != std::string::npos) {
|
||||
className = className.substr(pos + 2);
|
||||
}
|
||||
while (className.length() < 24)
|
||||
className.append(" ");
|
||||
std::cout << className << cmdHdlPtr->script() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto cmd = std::string("drogon_ctl::") + parameters[0];
|
||||
|
||||
auto classPtr =
|
||||
std::shared_ptr<DrObjectBase>(drogon::DrClassMap::newObject(cmd));
|
||||
if (classPtr) {
|
||||
auto cmdHdlPtr =
|
||||
std::dynamic_pointer_cast<CommandHandler>(classPtr);
|
||||
if (cmdHdlPtr) {
|
||||
if (cmdHdlPtr->isTopCommand())
|
||||
std::cout << cmdHdlPtr->detail() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* help.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CommandHandler.h"
|
||||
#include <drogon/DrObject.h>
|
||||
using namespace drogon;
|
||||
namespace drogon_ctl {
|
||||
class help : public DrObject<help>, public CommandHandler {
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
||||
virtual std::string script() override {
|
||||
return "display this message";
|
||||
}
|
||||
virtual bool isTopCommand() override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace drogon_ctl
|
@ -1,42 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* @file main.cc
|
||||
* @author An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cmd.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
std::vector<std::string> args;
|
||||
if (argc < 2) {
|
||||
args = { "help" };
|
||||
exeCommand(args);
|
||||
return 0;
|
||||
}
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
args.push_back(argv[i]);
|
||||
}
|
||||
if (args.size() > 0) {
|
||||
auto &arg = args[0];
|
||||
if (arg == "-h" || arg == "--help") {
|
||||
arg = "help";
|
||||
} else if (arg == "-v" || arg == "--version") {
|
||||
arg = "version";
|
||||
}
|
||||
}
|
||||
|
||||
exeCommand(args);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,259 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* press.cc
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by the MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "press.h"
|
||||
#include "cmd.h"
|
||||
#include <drogon/DrClassMap.h>
|
||||
#include <stdlib.h>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
using namespace drogon_ctl;
|
||||
std::string press::detail() {
|
||||
return "Use press command to do stress testing\n"
|
||||
"Usage:drogon_ctl press <options> <url>\n"
|
||||
" -n num number of requests(default : 1)\n"
|
||||
" -t num number of threads(default : 1)\n"
|
||||
" -c num concurrent connections(default : 1)\n"
|
||||
// " -k keep alive(default: no)\n"
|
||||
" -q no progress indication(default: no)\n\n"
|
||||
"example: drogon_ctl press -n 10000 -c 100 -t 4 -q "
|
||||
"http://localhost:8080/index.html\n";
|
||||
}
|
||||
|
||||
void outputErrorAndExit(const string_view &err) {
|
||||
std::cout << err << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
void press::handleCommand(std::vector<std::string> ¶meters) {
|
||||
for (auto iter = parameters.begin(); iter != parameters.end(); iter++) {
|
||||
auto ¶m = *iter;
|
||||
if (param.find("-n") == 0) {
|
||||
if (param == "-n") {
|
||||
++iter;
|
||||
if (iter == parameters.end()) {
|
||||
outputErrorAndExit("No number of requests!");
|
||||
}
|
||||
auto &num = *iter;
|
||||
try {
|
||||
numOfRequests_ = std::stoll(num);
|
||||
} catch (...) {
|
||||
outputErrorAndExit("Invalid number of requests!");
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
auto num = param.substr(2);
|
||||
try {
|
||||
numOfRequests_ = std::stoll(num);
|
||||
} catch (...) {
|
||||
outputErrorAndExit("Invalid number of requests!");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else if (param.find("-t") == 0) {
|
||||
if (param == "-t") {
|
||||
++iter;
|
||||
if (iter == parameters.end()) {
|
||||
outputErrorAndExit("No number of threads!");
|
||||
}
|
||||
auto &num = *iter;
|
||||
try {
|
||||
numOfThreads_ = std::stoll(num);
|
||||
} catch (...) {
|
||||
outputErrorAndExit("Invalid number of threads!");
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
auto num = param.substr(2);
|
||||
try {
|
||||
numOfThreads_ = std::stoll(num);
|
||||
} catch (...) {
|
||||
outputErrorAndExit("Invalid number of threads!");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else if (param.find("-c") == 0) {
|
||||
if (param == "-c") {
|
||||
++iter;
|
||||
if (iter == parameters.end()) {
|
||||
outputErrorAndExit("No number of connections!");
|
||||
}
|
||||
auto &num = *iter;
|
||||
try {
|
||||
numOfConnections_ = std::stoll(num);
|
||||
} catch (...) {
|
||||
outputErrorAndExit("Invalid number of connections!");
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
auto num = param.substr(2);
|
||||
try {
|
||||
numOfConnections_ = std::stoll(num);
|
||||
} catch (...) {
|
||||
outputErrorAndExit("Invalid number of connections!");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// else if (param == "-k")
|
||||
// {
|
||||
// keepAlive_ = true;
|
||||
// continue;
|
||||
// }
|
||||
else if (param == "-q") {
|
||||
processIndication_ = false;
|
||||
} else if (param[0] != '-') {
|
||||
url_ = param;
|
||||
}
|
||||
}
|
||||
// std::cout << "n=" << numOfRequests_ << std::endl;
|
||||
// std::cout << "t=" << numOfThreads_ << std::endl;
|
||||
// std::cout << "c=" << numOfConnections_ << std::endl;
|
||||
// std::cout << "q=" << processIndication_ << std::endl;
|
||||
// std::cout << "url=" << url_ << std::endl;
|
||||
if (url_.empty() || url_.compare(0, 4, "http") != 0 ||
|
||||
(url_.compare(4, 3, "://") != 0 && url_.compare(4, 4, "s://") != 0)) {
|
||||
outputErrorAndExit("Invalid URL");
|
||||
} else {
|
||||
auto pos = url_.find("://");
|
||||
auto posOfPath = url_.find("/", pos + 3);
|
||||
if (posOfPath == std::string::npos) {
|
||||
host_ = url_;
|
||||
path_ = "/";
|
||||
} else {
|
||||
host_ = url_.substr(0, posOfPath);
|
||||
path_ = url_.substr(posOfPath);
|
||||
}
|
||||
}
|
||||
// std::cout << "host=" << host_ << std::endl;
|
||||
// std::cout << "path=" << path_ << std::endl;
|
||||
doTesting();
|
||||
}
|
||||
|
||||
void press::doTesting() {
|
||||
createRequestAndClients();
|
||||
if (clients_.empty()) {
|
||||
outputErrorAndExit("No connection!");
|
||||
}
|
||||
statistics_.startDate_ = trantor::Date::now();
|
||||
for (auto &client : clients_) {
|
||||
sendRequest(client);
|
||||
}
|
||||
loopPool_->wait();
|
||||
}
|
||||
|
||||
void press::createRequestAndClients() {
|
||||
loopPool_ = std::make_unique<trantor::EventLoopThreadPool>(numOfThreads_);
|
||||
loopPool_->start();
|
||||
for (size_t i = 0; i < numOfConnections_; ++i) {
|
||||
auto client =
|
||||
HttpClient::newHttpClient(host_, loopPool_->getNextLoop());
|
||||
client->enableCookies();
|
||||
clients_.push_back(client);
|
||||
}
|
||||
}
|
||||
|
||||
void press::sendRequest(const HttpClientPtr &client) {
|
||||
auto numOfRequest = statistics_.numOfRequestsSent_++;
|
||||
if (numOfRequest >= numOfRequests_) {
|
||||
return;
|
||||
}
|
||||
auto request = HttpRequest::newHttpRequest();
|
||||
request->setPath(path_);
|
||||
request->setMethod(Get);
|
||||
// std::cout << "send!" << std::endl;
|
||||
client->sendRequest(
|
||||
request,
|
||||
[this, client, request](ReqResult r, const HttpResponsePtr &resp) {
|
||||
size_t goodNum, badNum;
|
||||
if (r == ReqResult::Ok) {
|
||||
// std::cout << "OK" << std::endl;
|
||||
goodNum = ++statistics_.numOfGoodResponse_;
|
||||
badNum = statistics_.numOfBadResponse_;
|
||||
statistics_.bytesRecieved_ += resp->body().length();
|
||||
auto delay = trantor::Date::now().microSecondsSinceEpoch() -
|
||||
request->creationDate().microSecondsSinceEpoch();
|
||||
statistics_.totalDelay_ += delay;
|
||||
} else {
|
||||
goodNum = statistics_.numOfGoodResponse_;
|
||||
badNum = ++statistics_.numOfBadResponse_;
|
||||
if (badNum > numOfRequests_ / 10) {
|
||||
outputErrorAndExit("Too many errors");
|
||||
}
|
||||
}
|
||||
if (goodNum + badNum >= numOfRequests_) {
|
||||
outputResults();
|
||||
}
|
||||
if (r == ReqResult::Ok)
|
||||
sendRequest(client);
|
||||
else {
|
||||
client->getLoop()->runAfter(1, [this, client]() {
|
||||
sendRequest(client);
|
||||
});
|
||||
}
|
||||
|
||||
if (processIndication_) {
|
||||
auto rec = goodNum + badNum;
|
||||
if (rec % 100000 == 0) {
|
||||
std::cout << rec << " responses are received" << std::endl
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void press::outputResults() {
|
||||
static std::mutex mtx;
|
||||
size_t totalSent = 0;
|
||||
size_t totalRecv = 0;
|
||||
for (auto &client : clients_) {
|
||||
totalSent += client->bytesSent();
|
||||
totalRecv += client->bytesReceived();
|
||||
}
|
||||
auto now = trantor::Date::now();
|
||||
auto microSecs = now.microSecondsSinceEpoch() -
|
||||
statistics_.startDate_.microSecondsSinceEpoch();
|
||||
double seconds = (double)microSecs / 1000000.0;
|
||||
size_t rps = static_cast<size_t>(statistics_.numOfGoodResponse_ / seconds);
|
||||
std::cout << std::endl;
|
||||
std::cout << "TOTALS: " << numOfConnections_ << " connect, "
|
||||
<< numOfRequests_ << " requests, "
|
||||
<< statistics_.numOfGoodResponse_ << " success, "
|
||||
<< statistics_.numOfBadResponse_ << " fail" << std::endl;
|
||||
|
||||
std::cout << "TRAFFIC: "
|
||||
<< statistics_.bytesRecieved_ / statistics_.numOfGoodResponse_
|
||||
<< " avg bytes, "
|
||||
<< (totalRecv - statistics_.bytesRecieved_) /
|
||||
statistics_.numOfGoodResponse_
|
||||
<< " avg overhead, " << statistics_.bytesRecieved_ << " bytes, "
|
||||
<< totalRecv - statistics_.bytesRecieved_ << " overhead"
|
||||
<< std::endl;
|
||||
|
||||
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
|
||||
<< "TIMING: " << seconds << " seconds, " << rps << " rps, "
|
||||
<< (double)(statistics_.totalDelay_) /
|
||||
statistics_.numOfGoodResponse_ / 1000
|
||||
<< " ms avg req time" << std::endl;
|
||||
|
||||
std::cout << "SPEED: download " << totalRecv / seconds / 1000
|
||||
<< " kBps, upload " << totalSent / seconds / 1000 << " kBps"
|
||||
<< std::endl
|
||||
<< std::endl;
|
||||
exit(0);
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* press.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by the MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CommandHandler.h"
|
||||
#include <drogon/DrObject.h>
|
||||
#include <drogon/HttpAppFramework.h>
|
||||
#include <drogon/HttpClient.h>
|
||||
#include <trantor/net/EventLoopThreadPool.h>
|
||||
#include <trantor/utils/Date.h>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace drogon;
|
||||
|
||||
namespace drogon_ctl {
|
||||
struct Statistics {
|
||||
std::atomic_size_t numOfRequestsSent_{ 0 };
|
||||
std::atomic_size_t bytesRecieved_{ 0 };
|
||||
std::atomic_size_t numOfGoodResponse_{ 0 };
|
||||
std::atomic_size_t numOfBadResponse_{ 0 };
|
||||
std::atomic_size_t totalDelay_{ 0 };
|
||||
trantor::Date startDate_;
|
||||
trantor::Date endDate_;
|
||||
};
|
||||
class press : public DrObject<press>, public CommandHandler {
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
||||
virtual std::string script() override {
|
||||
return "Do stress testing(Use 'drogon_ctl help press' for more "
|
||||
"information)";
|
||||
}
|
||||
virtual bool isTopCommand() override {
|
||||
return true;
|
||||
}
|
||||
virtual std::string detail() override;
|
||||
|
||||
private:
|
||||
size_t numOfThreads_{ 1 };
|
||||
size_t numOfRequests_{ 1 };
|
||||
size_t numOfConnections_{ 1 };
|
||||
// bool keepAlive_ = false;
|
||||
bool processIndication_{ true };
|
||||
std::string url_;
|
||||
std::string host_;
|
||||
std::string path_;
|
||||
void doTesting();
|
||||
void createRequestAndClients();
|
||||
void sendRequest(const HttpClientPtr &client);
|
||||
void outputResults();
|
||||
std::unique_ptr<trantor::EventLoopThreadPool> loopPool_;
|
||||
std::vector<HttpClientPtr> clients_;
|
||||
Statistics statistics_;
|
||||
};
|
||||
} // namespace drogon_ctl
|
@ -1,68 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project([[ProjectName]] CXX)
|
||||
|
||||
include(CheckIncludeFileCXX)
|
||||
|
||||
check_include_file_cxx(any HAS_ANY)
|
||||
check_include_file_cxx(string_view HAS_STRING_VIEW)
|
||||
check_include_file_cxx(coroutine HAS_COROUTINE)
|
||||
if (HAS_ANY AND HAS_STRING_VIEW AND HAS_COROUTINE)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
elseif (HAS_ANY AND HAS_STRING_VIEW)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
else ()
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
endif ()
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
add_executable(${PROJECT_NAME} main.cc)
|
||||
|
||||
# ##############################################################################
|
||||
# If you include the drogon source code locally in your project, use this method
|
||||
# to add drogon
|
||||
# add_subdirectory(drogon)
|
||||
# target_link_libraries(${PROJECT_NAME} PRIVATE drogon)
|
||||
#
|
||||
# and comment out the following lines
|
||||
find_package(Drogon CONFIG REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon)
|
||||
|
||||
# ##############################################################################
|
||||
|
||||
if (CMAKE_CXX_STANDARD LESS 17)
|
||||
# With C++14, use boost to support any and string_view
|
||||
message(STATUS "use c++14")
|
||||
find_package(Boost 1.61.0 REQUIRED)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
|
||||
elseif (CMAKE_CXX_STANDARD LESS 20)
|
||||
message(STATUS "use c++17")
|
||||
else ()
|
||||
message(STATUS "use c++20")
|
||||
endif ()
|
||||
|
||||
aux_source_directory(controllers CTL_SRC)
|
||||
aux_source_directory(filters FILTER_SRC)
|
||||
aux_source_directory(plugins PLUGIN_SRC)
|
||||
aux_source_directory(models MODEL_SRC)
|
||||
|
||||
drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
|
||||
${CMAKE_CURRENT_BINARY_DIR})
|
||||
# use the following line to create views with namespaces.
|
||||
# drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
|
||||
# ${CMAKE_CURRENT_BINARY_DIR} TRUE)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/models)
|
||||
target_sources(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
${SRC_DIR}
|
||||
${CTL_SRC}
|
||||
${FILTER_SRC}
|
||||
${PLUGIN_SRC}
|
||||
${MODEL_SRC})
|
||||
# ##############################################################################
|
||||
# uncomment the following line for dynamically loading views
|
||||
# set_property(TARGET ${PROJECT_NAME} PROPERTY ENABLE_EXPORTS ON)
|
@ -1,297 +0,0 @@
|
||||
/* This is a JSON format configuration file
|
||||
*/
|
||||
{
|
||||
/*
|
||||
//ssl:The global SSL settings. "key" and "cert" are the path to the SSL key and certificate. While
|
||||
// "conf" is an array of 1 or 2-element tuples that supplies file style options for `SSL_CONF_cmd`.
|
||||
"ssl": {
|
||||
"cert": "../../trantor/trantor/tests/server.pem",
|
||||
"key": "../../trantor/trantor/tests/server.pem",
|
||||
"conf": [
|
||||
//["Options", "-SessionTicket"],
|
||||
//["Options", "Compression"]
|
||||
]
|
||||
},
|
||||
"listeners": [
|
||||
{
|
||||
//address: Ip address,0.0.0.0 by default
|
||||
"address": "0.0.0.0",
|
||||
//port: Port number
|
||||
"port": 80,
|
||||
//https: If true, use https for security,false by default
|
||||
"https": false
|
||||
},
|
||||
{
|
||||
"address": "0.0.0.0",
|
||||
"port": 443,
|
||||
"https": true,
|
||||
//cert,key: Cert file path and key file path, empty by default,
|
||||
//if empty, use the global setting
|
||||
"cert": "",
|
||||
"key": "",
|
||||
//use_old_tls: enable the TLS1.0/1.1, false by default
|
||||
"use_old_tls": false,
|
||||
"ssl_conf": [
|
||||
//["MinProtocol", "TLSv1.3"]
|
||||
]
|
||||
}
|
||||
],
|
||||
"db_clients": [
|
||||
{
|
||||
//name: Name of the client,'default' by default
|
||||
//"name":"",
|
||||
//rdbms: Server type, postgresql,mysql or sqlite3, "postgresql" by default
|
||||
"rdbms": "postgresql",
|
||||
//filename: Sqlite3 db file name
|
||||
//"filename":"",
|
||||
//host: Server address,localhost by default
|
||||
"host": "127.0.0.1",
|
||||
//port: Server port, 5432 by default
|
||||
"port": 5432,
|
||||
//dbname: Database name
|
||||
"dbname": "test",
|
||||
//user: 'postgres' by default
|
||||
"user": "",
|
||||
//passwd: '' by default
|
||||
"passwd": "",
|
||||
//is_fast: false by default, if it is true, the client is faster but user can't call
|
||||
//any synchronous interface of it.
|
||||
"is_fast": false,
|
||||
//client_encoding: The character set used by the client. it is empty string by default which
|
||||
//means use the default character set.
|
||||
//"client_encoding": "",
|
||||
//number_of_connections: 1 by default, if the 'is_fast' is true, the number is the number of
|
||||
//connections per IO thread, otherwise it is the total number of all connections.
|
||||
"number_of_connections": 1,
|
||||
//timeout: -1.0 by default, in seconds, the timeout for executing a SQL query.
|
||||
//zero or negative value means no timeout.
|
||||
"timeout": -1.0
|
||||
}
|
||||
],
|
||||
"redis_clients": [
|
||||
{
|
||||
//name: Name of the client,'default' by default
|
||||
//"name":"",
|
||||
//host: Server IP, 127.0.0.1 by default
|
||||
"host": "127.0.0.1",
|
||||
//port: Server port, 6379 by default
|
||||
"port": 6379,
|
||||
//passwd: '' by default
|
||||
"passwd": "",
|
||||
//db index: 0 by default
|
||||
"db": 0,
|
||||
//is_fast: false by default, if it is true, the client is faster but user can't call
|
||||
//any synchronous interface of it.
|
||||
"is_fast": false,
|
||||
//number_of_connections: 1 by default, if the 'is_fast' is true, the number is the number of
|
||||
//connections per IO thread, otherwise it is the total number of all connections.
|
||||
"number_of_connections": 1,
|
||||
//timeout: -1.0 by default, in seconds, the timeout for executing a command.
|
||||
//zero or negative value means no timeout.
|
||||
"timeout": -1.0
|
||||
}
|
||||
],*/
|
||||
"app": {
|
||||
//number_of_threads: The number of IO threads, 1 by default, if the value is set to 0, the number of threads
|
||||
//is the number of CPU cores
|
||||
"number_of_threads": 1,
|
||||
//enable_session: False by default
|
||||
"enable_session": false,
|
||||
"session_timeout": 0,
|
||||
//document_root: Root path of HTTP document, defaut path is ./
|
||||
"document_root": "./",
|
||||
//home_page: Set the HTML file of the home page, the default value is "index.html"
|
||||
//If there isn't any handler registered to the path "/", the home page file in the "document_root" is send to clients as a response
|
||||
//to the request for "/".
|
||||
"home_page": "index.html",
|
||||
//use_implicit_page: enable implicit pages if true, true by default
|
||||
"use_implicit_page": true,
|
||||
//implicit_page: Set the file which would the server access in a directory that a user accessed.
|
||||
//For example, by default, http://localhost/a-directory resolves to http://localhost/a-directory/index.html.
|
||||
"implicit_page": "index.html",
|
||||
//static_file_headers: Headers for static files
|
||||
/*"static_file_headers": [
|
||||
{
|
||||
"name": "field-name",
|
||||
"value": "field-value"
|
||||
}
|
||||
],*/
|
||||
//upload_path: The path to save the uploaded file. "uploads" by default.
|
||||
//If the path isn't prefixed with /, ./ or ../,
|
||||
//it is relative path of document_root path
|
||||
"upload_path": "uploads",
|
||||
/* file_types:
|
||||
* HTTP download file types,The file types supported by drogon
|
||||
* by default are "html", "js", "css", "xml", "xsl", "txt", "svg",
|
||||
* "ttf", "otf", "woff2", "woff" , "eot", "png", "jpg", "jpeg",
|
||||
* "gif", "bmp", "ico", "icns", etc. */
|
||||
"file_types": [
|
||||
"gif",
|
||||
"png",
|
||||
"jpg",
|
||||
"js",
|
||||
"css",
|
||||
"html",
|
||||
"ico",
|
||||
"swf",
|
||||
"xap",
|
||||
"apk",
|
||||
"cur",
|
||||
"xml"
|
||||
],
|
||||
//locations: An array of locations of static files for GET requests.
|
||||
"locations": [
|
||||
{
|
||||
//uri_prefix: The URI prefix of the location prefixed with "/", the default value is "" that disables the location.
|
||||
//"uri_prefix": "/.well-known/acme-challenge/",
|
||||
//default_content_type: The default content type of the static files without
|
||||
//an extension. empty string by default.
|
||||
"default_content_type": "text/plain",
|
||||
//alias: The location in file system, if it is prefixed with "/", it
|
||||
//presents an absolute path, otherwise it presents a relative path to
|
||||
//the document_root path.
|
||||
//The default value is "" which means use the document root path as the location base path.
|
||||
"alias": "",
|
||||
//is_case_sensitive: indicates whether the URI prefix is case sensitive.
|
||||
"is_case_sensitive": false,
|
||||
//allow_all: true by default. If it is set to false, only static files with a valid extension can be accessed.
|
||||
"allow_all": true,
|
||||
//is_recursive: true by default. If it is set to false, files in sub directories can't be accessed.
|
||||
"is_recursive": true,
|
||||
//filters: string array, the filters applied to the location.
|
||||
"filters": []
|
||||
}
|
||||
],
|
||||
//max_connections: maximum number of connections, 100000 by default
|
||||
"max_connections": 100000,
|
||||
//max_connections_per_ip: maximum number of connections per clinet, 0 by default which means no limit
|
||||
"max_connections_per_ip": 0,
|
||||
//Load_dynamic_views: False by default, when set to true, drogon
|
||||
//compiles and loads dynamically "CSP View Files" in directories defined
|
||||
//by "dynamic_views_path"
|
||||
"load_dynamic_views": false,
|
||||
//dynamic_views_path: If the path isn't prefixed with /, ./ or ../,
|
||||
//it is relative path of document_root path
|
||||
"dynamic_views_path": [
|
||||
"./views"
|
||||
],
|
||||
//dynamic_views_output_path: Default by an empty string which means the output path of source
|
||||
//files is the path where the csp files locate. If the path isn't prefixed with /, it is relative
|
||||
//path of the current working directory.
|
||||
"dynamic_views_output_path": "",
|
||||
//enable_unicode_escaping_in_json: true by default, enable unicode escaping in json.
|
||||
"enable_unicode_escaping_in_json": true,
|
||||
//float_precision_in_json: set precision of float number in json.
|
||||
"float_precision_in_json": {
|
||||
//precision: 0 by default, 0 means use the default precision of the jsoncpp lib.
|
||||
"precision": 0,
|
||||
//precision_type: must be "significant" or "decimal", defaults to "significant" that means
|
||||
//setting max number of significant digits in string, "decimal" means setting max number of
|
||||
//digits after "." in string
|
||||
"precision_type": "significant"
|
||||
},
|
||||
//log: Set log output, drogon output logs to stdout by default
|
||||
"log": {
|
||||
//log_path: Log file path,empty by default,in which case,logs are output to the stdout
|
||||
//"log_path": "./",
|
||||
//logfile_base_name: Log file base name,empty by default which means drogon names logfile as
|
||||
//drogon.log ...
|
||||
"logfile_base_name": "",
|
||||
//log_size_limit: 100000000 bytes by default,
|
||||
//When the log file size reaches "log_size_limit", the log file is switched.
|
||||
"log_size_limit": 100000000,
|
||||
//log_level: "DEBUG" by default,options:"TRACE","DEBUG","INFO","WARN"
|
||||
//The TRACE level is only valid when built in DEBUG mode.
|
||||
"log_level": "DEBUG"
|
||||
},
|
||||
//run_as_daemon: False by default
|
||||
"run_as_daemon": false,
|
||||
//handle_sig_term: True by default
|
||||
"handle_sig_term": true,
|
||||
//relaunch_on_error: False by default, if true, the program will be restart by the parent after exiting;
|
||||
"relaunch_on_error": false,
|
||||
//use_sendfile: True by default, if true, the program
|
||||
//uses sendfile() system-call to send static files to clients;
|
||||
"use_sendfile": true,
|
||||
//use_gzip: True by default, use gzip to compress the response body's content;
|
||||
"use_gzip": true,
|
||||
//use_brotli: False by default, use brotli to compress the response body's content;
|
||||
"use_brotli": false,
|
||||
//static_files_cache_time: 5 (seconds) by default, the time in which the static file response is cached,
|
||||
//0 means cache forever, the negative value means no cache
|
||||
"static_files_cache_time": 5,
|
||||
//simple_controllers_map: Used to configure mapping from path to simple controller
|
||||
"simple_controllers_map": [
|
||||
{
|
||||
"path": "/path/name",
|
||||
"controller": "controllerClassName",
|
||||
"http_methods": [
|
||||
"get",
|
||||
"post"
|
||||
],
|
||||
"filters": [
|
||||
"FilterClassName"
|
||||
]
|
||||
}
|
||||
],
|
||||
//idle_connection_timeout: Defaults to 60 seconds, the lifetime
|
||||
//of the connection without read or write
|
||||
"idle_connection_timeout": 60,
|
||||
//server_header_field: Set the 'Server' header field in each response sent by drogon,
|
||||
//empty string by default with which the 'Server' header field is set to "Server: drogon/version string\r\n"
|
||||
"server_header_field": "",
|
||||
//enable_server_header: Set true to force drogon to add a 'Server' header to each HTTP response. The default
|
||||
//value is true.
|
||||
"enable_server_header": true,
|
||||
//enable_date_header: Set true to force drogon to add a 'Date' header to each HTTP response. The default
|
||||
//value is true.
|
||||
"enable_date_header": true,
|
||||
//keepalive_requests: Set the maximum number of requests that can be served through one keep-alive connection.
|
||||
//After the maximum number of requests are made, the connection is closed.
|
||||
//The default value of 0 means no limit.
|
||||
"keepalive_requests": 0,
|
||||
//pipelining_requests: Set the maximum number of unhandled requests that can be cached in pipelining buffer.
|
||||
//After the maximum number of requests are made, the connection is closed.
|
||||
//The default value of 0 means no limit.
|
||||
"pipelining_requests": 0,
|
||||
//gzip_static: If it is set to true, when the client requests a static file, drogon first finds the compressed
|
||||
//file with the extension ".gz" in the same path and send the compressed file to the client.
|
||||
//The default value of gzip_static is true.
|
||||
"gzip_static": true,
|
||||
//br_static: If it is set to true, when the client requests a static file, drogon first finds the compressed
|
||||
//file with the extension ".br" in the same path and send the compressed file to the client.
|
||||
//The default value of br_static is true.
|
||||
"br_static": true,
|
||||
//client_max_body_size: Set the maximum body size of HTTP requests received by drogon. The default value is "1M".
|
||||
//One can set it to "1024", "1k", "10M", "1G", etc. Setting it to "" means no limit.
|
||||
"client_max_body_size": "1M",
|
||||
//max_memory_body_size: Set the maximum body size in memory of HTTP requests received by drogon. The default value is "64K" bytes.
|
||||
//If the body size of a HTTP request exceeds this limit, the body is stored to a temporary file for processing.
|
||||
//Setting it to "" means no limit.
|
||||
"client_max_memory_body_size": "64K",
|
||||
//client_max_websocket_message_size: Set the maximum size of messages sent by WebSocket client. The default value is "128K".
|
||||
//One can set it to "1024", "1k", "10M", "1G", etc. Setting it to "" means no limit.
|
||||
"client_max_websocket_message_size": "128K",
|
||||
//reuse_port: Defaults to false, users can run multiple processes listening on the same port at the same time.
|
||||
"reuse_port": false
|
||||
},
|
||||
//plugins: Define all plugins running in the application
|
||||
"plugins": [
|
||||
{
|
||||
//name: The class name of the plugin
|
||||
//"name": "drogon::plugin::SecureSSLRedirector",
|
||||
//dependencies: Plugins that the plugin depends on. It can be commented out
|
||||
"dependencies": [],
|
||||
//config: The configuration of the plugin. This json object is the parameter to initialize the plugin.
|
||||
//It can be commented out
|
||||
"config": {
|
||||
"ssl_redirect_exempt": [
|
||||
".*\\.jpg"
|
||||
],
|
||||
"secure_ssl_host": "localhost:8849"
|
||||
}
|
||||
}
|
||||
],
|
||||
//custom_config: custom configuration for users. This object can be get by the app().getCustomConfig() method.
|
||||
"custom_config": {}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#include <drogon/drogon.h>
|
||||
int main() {
|
||||
//Set HTTP listener address and port
|
||||
drogon::app().addListener("0.0.0.0",80);
|
||||
//Load config file
|
||||
//drogon::app().loadConfigFile("../config.json");
|
||||
//Run HTTP framework,the method will block in the internal event loop
|
||||
drogon::app().run();
|
||||
return 0;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* [[filename]].cc
|
||||
*
|
||||
*/
|
||||
|
||||
#include "[[filename]].h"
|
||||
|
||||
using namespace drogon;
|
||||
<%c++auto namespaceStr=@@.get<std::string>("namespaceString");
|
||||
if(!namespaceStr.empty())
|
||||
$$<<"using namespace "<<namespaceStr<<";\n";
|
||||
%>
|
||||
|
||||
void [[className]]::doFilter(const HttpRequestPtr &req,
|
||||
FilterCallback &&fcb,
|
||||
FilterChainCallback &&fccb)
|
||||
{
|
||||
//Edit your logic here
|
||||
if (1)
|
||||
{
|
||||
//Passed
|
||||
fccb();
|
||||
return;
|
||||
}
|
||||
//Check failed
|
||||
auto res = drogon::HttpResponse::newHttpResponse();
|
||||
res->setStatusCode(k500InternalServerError);
|
||||
fcb(res);
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* [[filename]].h
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <drogon/HttpFilter.h>
|
||||
using namespace drogon;
|
||||
<%c++
|
||||
auto namespaceVector=@@.get<std::vector<std::string>>("namespaceVector");
|
||||
if(namespaceVector.empty())
|
||||
$$<<"\n";
|
||||
for(auto &namespaceName:namespaceVector){%>
|
||||
namespace {%namespaceName%}
|
||||
|
||||
{
|
||||
<%c++}
|
||||
$$<<"\n";%>
|
||||
class [[className]] : public HttpFilter<[[className]]>
|
||||
{
|
||||
public:
|
||||
[[className]]() {}
|
||||
virtual void doFilter(const HttpRequestPtr &req,
|
||||
FilterCallback &&fcb,
|
||||
FilterChainCallback &&fccb) override;
|
||||
};
|
||||
|
||||
<%c++for(size_t i=0;i<namespaceVector.size();i++){%>
|
||||
}
|
||||
<%c++}%>
|
@ -1,561 +0,0 @@
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/intellij+all,visualstudio,visualstudiocode,cmake,c,c++
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=intellij+all,visualstudio,visualstudiocode,cmake,c,c++
|
||||
|
||||
### C ###
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Linker output
|
||||
*.ilk
|
||||
*.map
|
||||
*.exp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
### C++ ###
|
||||
# Prerequisites
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
|
||||
# Precompiled Headers
|
||||
|
||||
# Linker files
|
||||
|
||||
# Debugger Files
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
|
||||
# Executables
|
||||
|
||||
### CMake ###
|
||||
CMakeLists.txt.user
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Testing
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
CMakeUserPresets.json
|
||||
|
||||
### CMake Patch ###
|
||||
# External projects
|
||||
*-prefix/
|
||||
|
||||
### Intellij+all ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### Intellij+all Patch ###
|
||||
# Ignores the whole .idea folder and all .iml files
|
||||
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||
|
||||
.idea/
|
||||
|
||||
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||
|
||||
*.iml
|
||||
modules.xml
|
||||
.idea/misc.xml
|
||||
*.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
.idea/sonarlint
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
*.code-workspace
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
.ionide
|
||||
|
||||
### VisualStudio ###
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.meta
|
||||
*.iobj
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*[.json, .xml, .info]
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
### VisualStudio Patch ###
|
||||
# Additional files built by Visual Studio
|
||||
*.tlog
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/intellij+all,visualstudio,visualstudiocode,cmake,c,c++
|
File diff suppressed because it is too large
Load Diff
@ -1,558 +0,0 @@
|
||||
<%inc#include "create_model.h"
|
||||
using namespace drogon_ctl;
|
||||
%>
|
||||
/**
|
||||
*
|
||||
* [[className]].h
|
||||
* DO NOT EDIT. This file is generated by drogon_ctl
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <drogon/orm/Result.h>
|
||||
#include <drogon/orm/Row.h>
|
||||
#include <drogon/orm/Field.h>
|
||||
#include <drogon/orm/SqlBinder.h>
|
||||
#include <drogon/orm/Mapper.h>
|
||||
#ifdef __cpp_impl_coroutine
|
||||
#include <drogon/orm/CoroMapper.h>
|
||||
#endif
|
||||
#include <trantor/utils/Date.h>
|
||||
#include <trantor/utils/Logger.h>
|
||||
#include <json/json.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <stdint.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace drogon::orm;
|
||||
namespace drogon
|
||||
{
|
||||
namespace orm
|
||||
{
|
||||
class DbClient;
|
||||
using DbClientPtr = std::shared_ptr<DbClient>;
|
||||
}
|
||||
}
|
||||
namespace drogon_model
|
||||
{
|
||||
namespace [[dbName]]
|
||||
{
|
||||
<%c++
|
||||
auto &schema=@@.get<std::string>("schema");
|
||||
if(!schema.empty())
|
||||
{
|
||||
$$<<"namespace "<<schema<<"\n";
|
||||
$$<<"{\n";
|
||||
}
|
||||
std::vector<std::string> relationshipClassNames;
|
||||
auto &relationships=@@.get<std::vector<Relationship>>("relationships");
|
||||
for(auto &relationship : relationships)
|
||||
{
|
||||
auto &name = relationship.targetTableName();
|
||||
auto relationshipClassName = nameTransform(name, true);
|
||||
relationshipClassNames.push_back(relationshipClassName);
|
||||
if(relationship.type() == Relationship::Type::ManyToMany)
|
||||
{
|
||||
auto &pivotTableName = relationship.pivotTable().tableName();
|
||||
auto pivotTableClassName = nameTransform(pivotTableName, true);
|
||||
relationshipClassNames.push_back(pivotTableClassName);
|
||||
}
|
||||
}
|
||||
std::sort(relationshipClassNames.begin(), relationshipClassNames.end());
|
||||
relationshipClassNames.erase(std::unique(relationshipClassNames.begin(), relationshipClassNames.end()), relationshipClassNames.end());
|
||||
for(std::string &relationshipClassName : relationshipClassNames)
|
||||
{
|
||||
%>
|
||||
class {%relationshipClassName%};
|
||||
<%c++
|
||||
}
|
||||
%>
|
||||
|
||||
class [[className]]
|
||||
{
|
||||
public:
|
||||
struct Cols
|
||||
{
|
||||
<%c++
|
||||
auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
||||
for(size_t i=0;i<cols.size();i++)
|
||||
{
|
||||
$$<<" static const std::string _"<<cols[i].colName_<<";\n";
|
||||
}
|
||||
%>
|
||||
};
|
||||
|
||||
const static int primaryKeyNumber;
|
||||
const static std::string tableName;
|
||||
const static bool hasPrimaryKey;
|
||||
<%c++if(@@.get<int>("hasPrimaryKey")<=1){%>
|
||||
const static std::string primaryKeyName;
|
||||
<%c++if(!@@.get<std::string>("primaryKeyType").empty()){%>
|
||||
using PrimaryKeyType = [[primaryKeyType]];
|
||||
const PrimaryKeyType &getPrimaryKey() const;
|
||||
<%c++}else{%>
|
||||
using PrimaryKeyType = void;
|
||||
int getPrimaryKey() const { assert(false); return 0; }
|
||||
<%c++}%>
|
||||
<%c++}else{
|
||||
auto pkTypes=@@.get<std::vector<std::string>>("primaryKeyType");
|
||||
std::string typelist;
|
||||
for(size_t i=0;i<pkTypes.size();i++)
|
||||
{
|
||||
typelist += pkTypes[i];
|
||||
if(i<(pkTypes.size()-1))
|
||||
typelist += ",";
|
||||
}
|
||||
%>
|
||||
const static std::vector<std::string> primaryKeyName;
|
||||
using PrimaryKeyType = std::tuple<{%typelist%}>;//<%c++
|
||||
auto pkName=@@.get<std::vector<std::string>>("primaryKeyName");
|
||||
for(size_t i=0;i<pkName.size();i++)
|
||||
{
|
||||
$$<<pkName[i];
|
||||
if(i<(pkName.size()-1))
|
||||
$$<<",";
|
||||
}
|
||||
%>
|
||||
|
||||
PrimaryKeyType getPrimaryKey() const;
|
||||
<%c++}%>
|
||||
|
||||
/**
|
||||
* @brief constructor
|
||||
* @param r One row of records in the SQL query result.
|
||||
* @param indexOffset Set the offset to -1 to access all columns by column names,
|
||||
* otherwise access all columns by offsets.
|
||||
* @note If the SQL is not a style of 'select * from table_name ...' (select all
|
||||
* columns by an asterisk), please set the offset to -1.
|
||||
*/
|
||||
explicit [[className]](const Row &r, const ssize_t indexOffset = 0) noexcept;
|
||||
|
||||
/**
|
||||
* @brief constructor
|
||||
* @param pJson The json object to construct a new instance.
|
||||
*/
|
||||
explicit [[className]](const Json::Value &pJson) noexcept(false);
|
||||
|
||||
/**
|
||||
* @brief constructor
|
||||
* @param pJson The json object to construct a new instance.
|
||||
* @param pMasqueradingVector The aliases of table columns.
|
||||
*/
|
||||
[[className]](const Json::Value &pJson, const std::vector<std::string> &pMasqueradingVector) noexcept(false);
|
||||
|
||||
[[className]]() = default;
|
||||
|
||||
void updateByJson(const Json::Value &pJson) noexcept(false);
|
||||
void updateByMasqueradedJson(const Json::Value &pJson,
|
||||
const std::vector<std::string> &pMasqueradingVector) noexcept(false);
|
||||
static bool validateJsonForCreation(const Json::Value &pJson, std::string &err);
|
||||
static bool validateMasqueradedJsonForCreation(const Json::Value &,
|
||||
const std::vector<std::string> &pMasqueradingVector,
|
||||
std::string &err);
|
||||
static bool validateJsonForUpdate(const Json::Value &pJson, std::string &err);
|
||||
static bool validateMasqueradedJsonForUpdate(const Json::Value &,
|
||||
const std::vector<std::string> &pMasqueradingVector,
|
||||
std::string &err);
|
||||
static bool validJsonOfField(size_t index,
|
||||
const std::string &fieldName,
|
||||
const Json::Value &pJson,
|
||||
std::string &err,
|
||||
bool isForCreation);
|
||||
|
||||
<%c++
|
||||
for(const auto &col:cols)
|
||||
{
|
||||
$$<<" /** For column "<<col.colName_<<" */\n";
|
||||
if(!col.colType_.empty())
|
||||
{
|
||||
$$<<" ///Get the value of the column "<<col.colName_<<", returns the default value if the column is null\n";
|
||||
$$<<" const "<<col.colType_<<" &getValueOf"<<col.colTypeName_<<"() const noexcept;\n";
|
||||
if(col.colType_=="std::vector<char>")
|
||||
{
|
||||
$$<<" ///Return the column value by std::string with binary data\n";
|
||||
$$<<" std::string getValueOf"<<col.colTypeName_<<"AsString() const noexcept;\n";
|
||||
}
|
||||
$$<<" ///Return a shared_ptr object pointing to the column const value, or an empty shared_ptr object if the column is null\n";
|
||||
$$<<" const std::shared_ptr<"<<col.colType_<<"> &get"<<col.colTypeName_<<"() const noexcept;\n";
|
||||
|
||||
$$<<" ///Set the value of the column "<<col.colName_<<"\n";
|
||||
$$<<" void set"<<col.colTypeName_<<"(const "<<col.colType_<<" &p"<<col.colTypeName_<<") noexcept;\n";
|
||||
if(col.colType_=="std::string")
|
||||
$$<<" void set"<<col.colTypeName_<<"("<<col.colType_<<" &&p"<<col.colTypeName_<<") noexcept;\n";
|
||||
if(col.colType_=="std::vector<char>")
|
||||
{
|
||||
$$<<" void set"<<col.colTypeName_<<"(const std::string &p"<<col.colTypeName_<<") noexcept;\n";
|
||||
}
|
||||
if(!col.notNull_)
|
||||
{
|
||||
$$<<" void set"<<col.colTypeName_<<"ToNull() noexcept;\n";
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
$$<<" //FIXME!!"<<" getValueOf"<<col.colTypeName_<<"() const noexcept;\n";
|
||||
$$<<"\n";
|
||||
}
|
||||
%>
|
||||
|
||||
static size_t getColumnNumber() noexcept { return {% cols.size() %}; }
|
||||
static const std::string &getColumnName(size_t index) noexcept(false);
|
||||
|
||||
Json::Value toJson() const;
|
||||
Json::Value toMasqueradedJson(const std::vector<std::string> &pMasqueradingVector) const;
|
||||
/// Relationship interfaces
|
||||
<%c++
|
||||
for(auto &relationship : relationships)
|
||||
{
|
||||
if(relationship.targetKey().empty() || relationship.originalKey().empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto &name=relationship.targetTableName();
|
||||
auto relationshipClassName=nameTransform(name, true);
|
||||
auto relationshipValName=nameTransform(name, false);
|
||||
auto alias=relationship.targetTableAlias();
|
||||
auto aliasValName=nameTransform(alias, false);
|
||||
if(relationship.type() == Relationship::Type::HasOne)
|
||||
{
|
||||
if(!alias.empty())
|
||||
{
|
||||
if(alias[0] <= 'z' && alias[0] >= 'a')
|
||||
{
|
||||
alias[0] += ('A' - 'a');
|
||||
}
|
||||
std::string alind(alias.length(), ' ');
|
||||
%>
|
||||
void get{%alias%}(const DbClientPtr &clientPtr,
|
||||
{%alind%} const std::function<void({%relationshipClassName%})> &rcb,
|
||||
{%alind%} const ExceptionCallback &ecb) const;
|
||||
<%c++
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
||||
%>
|
||||
void get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
||||
{%relationshipClassInde%} const std::function<void({%relationshipClassName%})> &rcb,
|
||||
{%relationshipClassInde%} const ExceptionCallback &ecb) const;
|
||||
<%c++
|
||||
}
|
||||
}
|
||||
else if(relationship.type() == Relationship::Type::HasMany)
|
||||
{
|
||||
if(!alias.empty())
|
||||
{
|
||||
if(alias[0] <= 'z' && alias[0] >= 'a')
|
||||
{
|
||||
alias[0] += ('A' - 'a');
|
||||
}
|
||||
std::string alind(alias.length(), ' ');
|
||||
%>
|
||||
void get{%alias%}(const DbClientPtr &clientPtr,
|
||||
{%alind%} const std::function<void(std::vector<{%relationshipClassName%}>)> &rcb,
|
||||
{%alind%} const ExceptionCallback &ecb) const;
|
||||
<%c++
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
||||
%>
|
||||
void get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
||||
{%relationshipClassInde%} const std::function<void(std::vector<{%relationshipClassName%}>)> &rcb,
|
||||
{%relationshipClassInde%} const ExceptionCallback &ecb) const;
|
||||
<%c++
|
||||
}
|
||||
}
|
||||
else if(relationship.type() == Relationship::Type::ManyToMany)
|
||||
{
|
||||
auto &pivotTableName=relationship.pivotTable().tableName();
|
||||
auto pivotTableClassName=nameTransform(pivotTableName, true);
|
||||
if(!alias.empty())
|
||||
{
|
||||
if(alias[0] <= 'z' && alias[0] >= 'a')
|
||||
{
|
||||
alias[0] += ('A' - 'a');
|
||||
}
|
||||
std::string alind(alias.length(), ' ');
|
||||
%>
|
||||
void get{%alias%}(const DbClientPtr &clientPtr,
|
||||
{%alind%} const std::function<void(std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>>)> &rcb,
|
||||
{%alind%} const ExceptionCallback &ecb) const;
|
||||
<%c++
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
||||
%>
|
||||
void get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
||||
{%relationshipClassInde%} const std::function<void(std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>>)> &rcb,
|
||||
{%relationshipClassInde%} const ExceptionCallback &ecb) const;
|
||||
<%c++
|
||||
}
|
||||
}
|
||||
}
|
||||
%>
|
||||
private:
|
||||
friend Mapper<[[className]]>;
|
||||
#ifdef __cpp_impl_coroutine
|
||||
friend CoroMapper<[[className]]>;
|
||||
#endif
|
||||
static const std::vector<std::string> &insertColumns() noexcept;
|
||||
void outputArgs(drogon::orm::internal::SqlBinder &binder) const;
|
||||
const std::vector<std::string> updateColumns() const;
|
||||
void updateArgs(drogon::orm::internal::SqlBinder &binder) const;
|
||||
///For mysql or sqlite3
|
||||
void updateId(const uint64_t id);
|
||||
<%c++
|
||||
for(auto col:cols)
|
||||
{
|
||||
if(!col.colType_.empty())
|
||||
$$<<" std::shared_ptr<"<<col.colType_<<"> "<<col.colValName_<<"_;\n";
|
||||
}
|
||||
%>
|
||||
struct MetaData
|
||||
{
|
||||
const std::string colName_;
|
||||
const std::string colType_;
|
||||
const std::string colDatabaseType_;
|
||||
const ssize_t colLength_;
|
||||
const bool isAutoVal_;
|
||||
const bool isPrimaryKey_;
|
||||
const bool notNull_;
|
||||
};
|
||||
static const std::vector<MetaData> metaData_;
|
||||
bool dirtyFlag_[{%cols.size()%}]={ false };
|
||||
public:
|
||||
static const std::string &sqlForFindingByPrimaryKey()
|
||||
{
|
||||
<%c++
|
||||
auto rdbms=@@.get<std::string>("rdbms");
|
||||
if(@@.get<int>("hasPrimaryKey")<=1){
|
||||
if(!@@.get<std::string>("primaryKeyType").empty()){%>
|
||||
static const std::string sql="select * from " + tableName + " where [[primaryKeyName]] = {%(rdbms=="postgresql"?"$1":"?")%}";
|
||||
<%c++}else{%>
|
||||
static const std::string sql="";
|
||||
<%c++}%>
|
||||
<%c++}else{
|
||||
auto pkName=@@.get<std::vector<std::string>>("primaryKeyName");
|
||||
%>
|
||||
static const std::string sql="select * from " + tableName + " where <%c++
|
||||
for(size_t i=0;i<pkName.size();i++)
|
||||
{
|
||||
if(rdbms=="postgresql")
|
||||
{
|
||||
$$<<pkName[i]<<" = $"<<i+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$$<<pkName[i]<<" = ?";
|
||||
}
|
||||
if(i<(pkName.size()-1))
|
||||
$$<<" and ";
|
||||
}
|
||||
$$<<"\";\n";
|
||||
}
|
||||
%>
|
||||
return sql;
|
||||
}
|
||||
|
||||
static const std::string &sqlForDeletingByPrimaryKey()
|
||||
{
|
||||
<%c++
|
||||
if(@@.get<int>("hasPrimaryKey")<=1){
|
||||
if(!@@.get<std::string>("primaryKeyType").empty()){%>
|
||||
static const std::string sql="delete from " + tableName + " where [[primaryKeyName]] = {%(rdbms=="postgresql"?"$1":"?")%}";
|
||||
<%c++}else{%>
|
||||
static const std::string sql="";
|
||||
<%c++}%>
|
||||
<%c++}else{
|
||||
auto pkName=@@.get<std::vector<std::string>>("primaryKeyName");
|
||||
%>
|
||||
static const std::string sql="delete from " + tableName + " where <%c++
|
||||
for(size_t i=0;i<pkName.size();i++)
|
||||
{
|
||||
if(rdbms=="postgresql")
|
||||
{
|
||||
$$<<pkName[i]<<" = $"<<i+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$$<<pkName[i]<<" = ?";
|
||||
}
|
||||
if(i<(pkName.size()-1))
|
||||
$$<<" and ";
|
||||
}
|
||||
$$<<"\";\n";
|
||||
}
|
||||
%>
|
||||
return sql;
|
||||
}
|
||||
std::string sqlForInserting(bool &needSelection) const
|
||||
{
|
||||
std::string sql="insert into " + tableName + " (";
|
||||
size_t parametersCount = 0;
|
||||
needSelection = false;
|
||||
<%c++
|
||||
bool selFlag=false;
|
||||
for(size_t i=0;i<cols.size();i++)
|
||||
{
|
||||
if(cols[i].isAutoVal_)
|
||||
{
|
||||
if(@@.get<std::string>("rdbms")=="sqlite3")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(@@.get<int>("hasPrimaryKey")>0)
|
||||
{
|
||||
selFlag = true;
|
||||
}
|
||||
$$<<" sql += \""<<cols[i].colName_<<",\";\n";
|
||||
$$<<" ++parametersCount;\n";
|
||||
continue;
|
||||
}
|
||||
if(cols[i].colType_.empty())
|
||||
continue;
|
||||
if(cols[i].hasDefaultVal_)
|
||||
{
|
||||
if(@@.get<std::string>("rdbms")!="sqlite3")
|
||||
{
|
||||
$$<<" sql += \""<<cols[i].colName_<<",\";\n";
|
||||
$$<<" ++parametersCount;\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
%>
|
||||
if(dirtyFlag_[{%i%}])
|
||||
{
|
||||
sql += "{%cols[i].colName_%},";
|
||||
++parametersCount;
|
||||
}
|
||||
<%c++
|
||||
}
|
||||
if(@@.get<int>("hasPrimaryKey")>0||@@.get<std::string>("rdbms")=="postgresql")
|
||||
{
|
||||
%>
|
||||
if(!dirtyFlag_[{%i%}])
|
||||
{
|
||||
needSelection=true;
|
||||
}
|
||||
<%c++
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
%>
|
||||
if(dirtyFlag_[{%i%}])
|
||||
{
|
||||
sql += "{%cols[i].colName_%},";
|
||||
++parametersCount;
|
||||
}
|
||||
<%c++
|
||||
}
|
||||
}
|
||||
if(selFlag)
|
||||
{
|
||||
$$<<" needSelection=true;\n";
|
||||
}
|
||||
%>
|
||||
if(parametersCount > 0)
|
||||
{
|
||||
sql[sql.length()-1]=')';
|
||||
sql += " values (";
|
||||
}
|
||||
else
|
||||
sql += ") values (";
|
||||
|
||||
<%c++
|
||||
if(@@.get<std::string>("rdbms")=="postgresql")
|
||||
{
|
||||
%>
|
||||
int placeholder=1;
|
||||
char placeholderStr[64];
|
||||
size_t n=0;
|
||||
<%c++
|
||||
}
|
||||
for(size_t i=0;i<cols.size();i++)
|
||||
{
|
||||
if(cols[i].isAutoVal_)
|
||||
{
|
||||
if(@@.get<std::string>("rdbms")!="sqlite3")
|
||||
{
|
||||
%>
|
||||
sql +="default,";
|
||||
<%c++
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(cols[i].colType_.empty())
|
||||
continue;
|
||||
%>
|
||||
if(dirtyFlag_[{%i%}])
|
||||
{
|
||||
<%c++
|
||||
if(@@.get<std::string>("rdbms")=="postgresql")
|
||||
{
|
||||
%>
|
||||
n = sprintf(placeholderStr,"$%d,",placeholder++);
|
||||
sql.append(placeholderStr, n);
|
||||
<%c++
|
||||
}else
|
||||
{
|
||||
%>
|
||||
sql.append("?,");
|
||||
|
||||
<%c++
|
||||
}
|
||||
%>
|
||||
}
|
||||
<%c++
|
||||
if(cols[i].hasDefaultVal_&&@@.get<std::string>("rdbms")!="sqlite3")
|
||||
{
|
||||
%>
|
||||
else
|
||||
{
|
||||
sql +="default,";
|
||||
}
|
||||
<%c++
|
||||
}
|
||||
}
|
||||
%>
|
||||
if(parametersCount > 0)
|
||||
{
|
||||
sql.resize(sql.length() - 1);
|
||||
}
|
||||
<%c++
|
||||
if(rdbms=="postgresql")
|
||||
{
|
||||
%>
|
||||
if(needSelection)
|
||||
{
|
||||
sql.append(") returning *");
|
||||
}
|
||||
else
|
||||
{
|
||||
sql.append(1, ')');
|
||||
}
|
||||
<%c++
|
||||
}
|
||||
else
|
||||
{
|
||||
$$<<" sql.append(1, ')');\n";
|
||||
}
|
||||
%>
|
||||
LOG_TRACE << sql;
|
||||
return sql;
|
||||
}
|
||||
};
|
||||
<%c++
|
||||
if(!schema.empty())
|
||||
{
|
||||
$$<<"} // namespace "<<schema<<"\n";
|
||||
}
|
||||
%>
|
||||
} // namespace [[dbName]]
|
||||
} // namespace drogon_model
|
@ -1,104 +0,0 @@
|
||||
{
|
||||
//rdbms: server type, postgresql,mysql or sqlite3
|
||||
"rdbms": "postgresql",
|
||||
//filename: sqlite3 db file name
|
||||
//"filename":"",
|
||||
//host: server address,localhost by default;
|
||||
"host": "127.0.0.1",
|
||||
//port: server port, 5432 by default;
|
||||
"port": 5432,
|
||||
//dbname: Database name;
|
||||
"dbname": "",
|
||||
//schema: valid for postgreSQL, "public" by default;
|
||||
"schema": "public",
|
||||
//user: User name
|
||||
"user": "",
|
||||
//password or passwd: Password
|
||||
"password": "",
|
||||
//client_encoding: The character set used by drogon_ctl. it is empty string by default which
|
||||
//means use the default character set.
|
||||
//"client_encoding": "",
|
||||
//table: An array of tables to be modelized. if the array is empty, all revealed tables are modelized.
|
||||
"tables": [],
|
||||
//convert: the value can be changed by a function call before it is stored into database or
|
||||
//after it is read from database
|
||||
"convert": {
|
||||
"enabled": false,
|
||||
"items":[{
|
||||
"table": "user",
|
||||
"column": "password",
|
||||
"method": {
|
||||
//after_db_read: name of the method which is called after reading from database, signature: void([const] std::shared_ptr [&])
|
||||
"after_db_read": "decrypt_password",
|
||||
//before_db_write: name of the method which is called before writing to database, signature: void([const] std::shared_ptr [&])
|
||||
"before_db_write": "encrypt_password"
|
||||
},
|
||||
"includes": [
|
||||
"\"file_local_search_path.h\"","<file_in_global_search_path.h>"
|
||||
]
|
||||
}]
|
||||
},
|
||||
"relationships": {
|
||||
"enabled": false,
|
||||
"items": [{
|
||||
"type": "has one",
|
||||
"original_table_name": "products",
|
||||
"original_table_alias": "product",
|
||||
"original_key": "id",
|
||||
"target_table_name": "skus",
|
||||
"target_table_alias": "SKU",
|
||||
"target_key": "product_id",
|
||||
"enable_reverse": true
|
||||
},
|
||||
{
|
||||
"type": "has many",
|
||||
"original_table_name": "products",
|
||||
"original_table_alias": "product",
|
||||
"original_key": "id",
|
||||
"target_table_name": "reviews",
|
||||
"target_table_alias": "",
|
||||
"target_key": "product_id",
|
||||
"enable_reverse": true
|
||||
},
|
||||
{
|
||||
"type": "many to many",
|
||||
"original_table_name": "products",
|
||||
"original_table_alias": "",
|
||||
"original_key": "id",
|
||||
"pivot_table": {
|
||||
"table_name": "carts_products",
|
||||
"original_key": "product_id",
|
||||
"target_key": "cart_id"
|
||||
},
|
||||
"target_table_name": "carts",
|
||||
"target_table_alias": "",
|
||||
"target_key": "id",
|
||||
"enable_reverse": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"restful_api_controllers": {
|
||||
"enabled": false,
|
||||
// resource_uri: The URI to access the resource, the default value
|
||||
// is '/*' in which the asterisk represents the table name.
|
||||
// If this option is set to a empty string, the URI is composed of the namespaces and the class name.
|
||||
"resource_uri": "/*",
|
||||
// class_name: "Restful*Ctrl" by default, the asterisk represents the table name.
|
||||
// This option can contain namespaces.
|
||||
"class_name": "Restful*Ctrl",
|
||||
// filters: an array of filter names.
|
||||
"filters": [],
|
||||
// db_client: the database client used by the controller. this option must be consistent with
|
||||
// the configuration of the application.
|
||||
"db_client": {
|
||||
//name: Name of the client,'default' by default
|
||||
"name": "default",
|
||||
//is_fast:
|
||||
"is_fast": false
|
||||
},
|
||||
// directory: The directory where the controller source files are stored.
|
||||
"directory": "controllers",
|
||||
// generate_base_only: false by default. Set to true to avoid overwriting custom subclasses.
|
||||
"generate_base_only": false
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* [[filename]].cc
|
||||
*
|
||||
*/
|
||||
|
||||
#include "[[filename]].h"
|
||||
|
||||
using namespace drogon;
|
||||
<%c++auto namespaceStr=@@.get<std::string>("namespaceString");
|
||||
if(!namespaceStr.empty())
|
||||
$$<<"using namespace "<<namespaceStr<<";\n";
|
||||
%>
|
||||
|
||||
void [[className]]::initAndStart(const Json::Value &config)
|
||||
{
|
||||
/// Initialize and start the plugin
|
||||
}
|
||||
|
||||
void [[className]]::shutdown()
|
||||
{
|
||||
/// Shutdown the plugin
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* [[filename]].h
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <drogon/plugins/Plugin.h>
|
||||
<%c++
|
||||
auto namespaceVector=@@.get<std::vector<std::string>>("namespaceVector");
|
||||
if(namespaceVector.empty())
|
||||
$$<<"\n";
|
||||
for(auto &namespaceName:namespaceVector){%>
|
||||
namespace {%namespaceName%}
|
||||
|
||||
{
|
||||
<%c++}
|
||||
$$<<"\n";%>
|
||||
class [[className]] : public drogon::Plugin<[[className]]>
|
||||
{
|
||||
public:
|
||||
[[className]]() {}
|
||||
/// This method must be called by drogon to initialize and start the plugin.
|
||||
/// It must be implemented by the user.
|
||||
virtual void initAndStart(const Json::Value &config) override;
|
||||
|
||||
/// This method must be called by drogon to shutdown the plugin.
|
||||
/// It must be implemented by the user.
|
||||
virtual void shutdown() override;
|
||||
};
|
||||
|
||||
<%c++for(size_t i=0;i<namespaceVector.size();i++){%>
|
||||
}
|
||||
<%c++}%>
|
@ -1,494 +0,0 @@
|
||||
<%inc#include "create_model.h"
|
||||
using namespace drogon_ctl;
|
||||
%>
|
||||
|
||||
/**
|
||||
*
|
||||
* [[fileName]]Base.cc
|
||||
* DO NOT EDIT. This file is generated by drogon_ctl automatically.
|
||||
* Users should implement business logic in the derived class.
|
||||
*/
|
||||
|
||||
#include "[[fileName]]Base.h"
|
||||
#include <string>
|
||||
|
||||
<%c++
|
||||
auto tableInfo = @@.get<DrTemplateData>("tableInfo");
|
||||
auto modelName = tableInfo.get<std::string>("className");
|
||||
bool hasPrimaryKey = (tableInfo.get<int>("hasPrimaryKey")==1);
|
||||
auto namespaceVector=@@.get<std::vector<std::string>>("namespaceVector");
|
||||
std::string namespaceStr;
|
||||
for(auto &name:namespaceVector)
|
||||
{
|
||||
namespaceStr.append(name);
|
||||
namespaceStr.append("::");
|
||||
}
|
||||
if(!namespaceStr.empty())
|
||||
{
|
||||
namespaceStr.resize(namespaceStr.length()-2);
|
||||
$$<<"using namespace "<<namespaceStr<<";\n";
|
||||
}
|
||||
std::string indentStr(@@.get<std::string>("className").length(), ' ');
|
||||
%>
|
||||
<%c++
|
||||
if(hasPrimaryKey)
|
||||
{%>
|
||||
void [[className]]Base::getOne(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%indentStr%} {%modelName%}::PrimaryKeyType &&id)
|
||||
{
|
||||
|
||||
auto dbClientPtr = getDbClient();
|
||||
auto callbackPtr =
|
||||
std::make_shared<std::function<void(const HttpResponsePtr &)>>(
|
||||
std::move(callback));
|
||||
drogon::orm::Mapper<{%modelName%}> mapper(dbClientPtr);
|
||||
mapper.findByPrimaryKey(
|
||||
id,
|
||||
[req, callbackPtr, this]({%modelName%} r) {
|
||||
(*callbackPtr)(HttpResponse::newHttpJsonResponse(makeJson(req, r)));
|
||||
},
|
||||
[callbackPtr](const DrogonDbException &e) {
|
||||
const drogon::orm::UnexpectedRows *s=dynamic_cast<const drogon::orm::UnexpectedRows *>(&e.base());
|
||||
if(s)
|
||||
{
|
||||
auto resp = HttpResponse::newHttpResponse();
|
||||
resp->setStatusCode(k404NotFound);
|
||||
(*callbackPtr)(resp);
|
||||
return;
|
||||
}
|
||||
LOG_ERROR<<e.base().what();
|
||||
Json::Value ret;
|
||||
ret["error"] = "database error";
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k500InternalServerError);
|
||||
(*callbackPtr)(resp);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void [[className]]Base::updateOne(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%indentStr%} {%modelName%}::PrimaryKeyType &&id)
|
||||
{
|
||||
auto jsonPtr=req->jsonObject();
|
||||
if(!jsonPtr)
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["error"]="No json object is found in the request";
|
||||
auto resp= HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
{%modelName%} object;
|
||||
std::string err;
|
||||
if(!doCustomValidations(*jsonPtr, err))
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["error"] = err;
|
||||
auto resp= HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
if(isMasquerading())
|
||||
{
|
||||
if(!{%modelName%}::validateMasqueradedJsonForUpdate(*jsonPtr, masqueradingVector(), err))
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["error"] = err;
|
||||
auto resp= HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
object.updateByMasqueradedJson(*jsonPtr, masqueradingVector());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!{%modelName%}::validateJsonForUpdate(*jsonPtr, err))
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["error"] = err;
|
||||
auto resp= HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
object.updateByJson(*jsonPtr);
|
||||
}
|
||||
}
|
||||
catch(const Json::Exception &e)
|
||||
{
|
||||
LOG_ERROR << e.what();
|
||||
Json::Value ret;
|
||||
ret["error"]="Field type error";
|
||||
auto resp= HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
if(object.getPrimaryKey() != id)
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["error"]="Bad primary key";
|
||||
auto resp= HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
|
||||
auto dbClientPtr = getDbClient();
|
||||
auto callbackPtr =
|
||||
std::make_shared<std::function<void(const HttpResponsePtr &)>>(
|
||||
std::move(callback));
|
||||
drogon::orm::Mapper<{%modelName%}> mapper(dbClientPtr);
|
||||
|
||||
mapper.update(
|
||||
object,
|
||||
[callbackPtr](const size_t count)
|
||||
{
|
||||
if(count == 1)
|
||||
{
|
||||
auto resp = HttpResponse::newHttpResponse();
|
||||
resp->setStatusCode(k202Accepted);
|
||||
(*callbackPtr)(resp);
|
||||
}
|
||||
else if(count == 0)
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["error"]="No resources are updated";
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k404NotFound);
|
||||
(*callbackPtr)(resp);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_FATAL << "More than one resource is updated: " << count;
|
||||
Json::Value ret;
|
||||
ret["error"] = "database error";
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k500InternalServerError);
|
||||
(*callbackPtr)(resp);
|
||||
}
|
||||
},
|
||||
[callbackPtr](const DrogonDbException &e) {
|
||||
LOG_ERROR << e.base().what();
|
||||
Json::Value ret;
|
||||
ret["error"] = "database error";
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k500InternalServerError);
|
||||
(*callbackPtr)(resp);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void [[className]]Base::deleteOne(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%indentStr%} {%modelName%}::PrimaryKeyType &&id)
|
||||
{
|
||||
|
||||
auto dbClientPtr = getDbClient();
|
||||
auto callbackPtr =
|
||||
std::make_shared<std::function<void(const HttpResponsePtr &)>>(
|
||||
std::move(callback));
|
||||
drogon::orm::Mapper<{%modelName%}> mapper(dbClientPtr);
|
||||
mapper.deleteByPrimaryKey(
|
||||
id,
|
||||
[callbackPtr](const size_t count) {
|
||||
if(count == 1)
|
||||
{
|
||||
auto resp = HttpResponse::newHttpResponse();
|
||||
resp->setStatusCode(k204NoContent);
|
||||
(*callbackPtr)(resp);
|
||||
}
|
||||
else if(count == 0)
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["error"] = "No resources deleted";
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k404NotFound);
|
||||
(*callbackPtr)(resp);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_FATAL << "Delete more than one records: " << count;
|
||||
Json::Value ret;
|
||||
ret["error"] = "Database error";
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k500InternalServerError);
|
||||
(*callbackPtr)(resp);
|
||||
}
|
||||
},
|
||||
[callbackPtr](const DrogonDbException &e) {
|
||||
LOG_ERROR << e.base().what();
|
||||
Json::Value ret;
|
||||
ret["error"] = "database error";
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k500InternalServerError);
|
||||
(*callbackPtr)(resp);
|
||||
});
|
||||
}
|
||||
<%c++}%>
|
||||
|
||||
void [[className]]Base::get(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
auto dbClientPtr = getDbClient();
|
||||
drogon::orm::Mapper<{%modelName%}> mapper(dbClientPtr);
|
||||
auto ¶meters = req->parameters();
|
||||
auto iter = parameters.find("sort");
|
||||
if(iter != parameters.end())
|
||||
{
|
||||
auto sortFields = drogon::utils::splitString(iter->second, ",");
|
||||
for(auto &field : sortFields)
|
||||
{
|
||||
if(field.empty())
|
||||
continue;
|
||||
if(field[0] == '+')
|
||||
{
|
||||
field = field.substr(1);
|
||||
mapper.orderBy(field, SortOrder::ASC);
|
||||
}
|
||||
else if(field[0] == '-')
|
||||
{
|
||||
field = field.substr(1);
|
||||
mapper.orderBy(field, SortOrder::DESC);
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.orderBy(field, SortOrder::ASC);
|
||||
}
|
||||
}
|
||||
}
|
||||
iter = parameters.find("offset");
|
||||
if(iter != parameters.end())
|
||||
{
|
||||
try{
|
||||
auto offset = std::stoll(iter->second);
|
||||
mapper.offset(offset);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
auto resp = HttpResponse::newHttpResponse();
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
iter = parameters.find("limit");
|
||||
if(iter != parameters.end())
|
||||
{
|
||||
try{
|
||||
auto limit = std::stoll(iter->second);
|
||||
mapper.limit(limit);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
auto resp = HttpResponse::newHttpResponse();
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto callbackPtr =
|
||||
std::make_shared<std::function<void(const HttpResponsePtr &)>>(
|
||||
std::move(callback));
|
||||
auto jsonPtr = req->jsonObject();
|
||||
if(jsonPtr && jsonPtr->isMember("filter"))
|
||||
{
|
||||
try{
|
||||
auto criteria = makeCriteria((*jsonPtr)["filter"]);
|
||||
mapper.findBy(criteria,
|
||||
[req, callbackPtr, this](const std::vector<{%modelName%}> &v) {
|
||||
Json::Value ret;
|
||||
ret.resize(0);
|
||||
for (auto &obj : v)
|
||||
{
|
||||
ret.append(makeJson(req, obj));
|
||||
}
|
||||
(*callbackPtr)(HttpResponse::newHttpJsonResponse(ret));
|
||||
},
|
||||
[callbackPtr](const DrogonDbException &e) {
|
||||
LOG_ERROR << e.base().what();
|
||||
Json::Value ret;
|
||||
ret["error"] = "database error";
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k500InternalServerError);
|
||||
(*callbackPtr)(resp);
|
||||
});
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
LOG_ERROR << e.what();
|
||||
Json::Value ret;
|
||||
ret["error"] = e.what();
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
(*callbackPtr)(resp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mapper.findAll([req, callbackPtr, this](const std::vector<{%modelName%}> &v) {
|
||||
Json::Value ret;
|
||||
ret.resize(0);
|
||||
for (auto &obj : v)
|
||||
{
|
||||
ret.append(makeJson(req, obj));
|
||||
}
|
||||
(*callbackPtr)(HttpResponse::newHttpJsonResponse(ret));
|
||||
},
|
||||
[callbackPtr](const DrogonDbException &e) {
|
||||
LOG_ERROR << e.base().what();
|
||||
Json::Value ret;
|
||||
ret["error"] = "database error";
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k500InternalServerError);
|
||||
(*callbackPtr)(resp);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void [[className]]Base::create(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
auto jsonPtr=req->jsonObject();
|
||||
if(!jsonPtr)
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["error"]="No json object is found in the request";
|
||||
auto resp= HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
std::string err;
|
||||
if(!doCustomValidations(*jsonPtr, err))
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["error"] = err;
|
||||
auto resp= HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
if(isMasquerading())
|
||||
{
|
||||
if(!{%modelName%}::validateMasqueradedJsonForCreation(*jsonPtr, masqueradingVector(), err))
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["error"] = err;
|
||||
auto resp= HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!{%modelName%}::validateJsonForCreation(*jsonPtr, err))
|
||||
{
|
||||
Json::Value ret;
|
||||
ret["error"] = err;
|
||||
auto resp= HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
{%modelName%} object =
|
||||
(isMasquerading()?
|
||||
{%modelName%}(*jsonPtr, masqueradingVector()) :
|
||||
{%modelName%}(*jsonPtr));
|
||||
auto dbClientPtr = getDbClient();
|
||||
auto callbackPtr =
|
||||
std::make_shared<std::function<void(const HttpResponsePtr &)>>(
|
||||
std::move(callback));
|
||||
drogon::orm::Mapper<{%modelName%}> mapper(dbClientPtr);
|
||||
mapper.insert(
|
||||
object,
|
||||
[req, callbackPtr, this]({%modelName%} newObject){
|
||||
(*callbackPtr)(HttpResponse::newHttpJsonResponse(
|
||||
makeJson(req, newObject)));
|
||||
},
|
||||
[callbackPtr](const DrogonDbException &e){
|
||||
LOG_ERROR << e.base().what();
|
||||
Json::Value ret;
|
||||
ret["error"] = "database error";
|
||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k500InternalServerError);
|
||||
(*callbackPtr)(resp);
|
||||
});
|
||||
}
|
||||
catch(const Json::Exception &e)
|
||||
{
|
||||
LOG_ERROR << e.what();
|
||||
Json::Value ret;
|
||||
ret["error"]="Field type error";
|
||||
auto resp= HttpResponse::newHttpJsonResponse(ret);
|
||||
resp->setStatusCode(k400BadRequest);
|
||||
callback(resp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void [[className]]Base::update(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
|
||||
}*/
|
||||
|
||||
[[className]]Base::[[className]]Base()
|
||||
: RestfulController({
|
||||
<%c++
|
||||
tableInfo = @@.get<DrTemplateData>("tableInfo");
|
||||
const auto &cols=tableInfo.get<std::vector<ColumnInfo>>("columns");
|
||||
for(size_t i=0; i<cols.size(); ++i)
|
||||
{
|
||||
auto &col = cols[i];
|
||||
if(i < (cols.size()-1))
|
||||
{
|
||||
%>
|
||||
"{%col.colName_%}",
|
||||
<%c++
|
||||
}else{
|
||||
%>
|
||||
"{%col.colName_%}"
|
||||
<%c++
|
||||
}
|
||||
}
|
||||
%>
|
||||
})
|
||||
{
|
||||
/**
|
||||
* The items in the vector are aliases of column names in the table.
|
||||
* if one item is set to an empty string, the related column is not sent
|
||||
* to clients.
|
||||
*/
|
||||
enableMasquerading({
|
||||
<%c++
|
||||
for(size_t i=0; i<cols.size(); ++i)
|
||||
{
|
||||
auto &col = cols[i];
|
||||
if(i < (cols.size()-1))
|
||||
{
|
||||
%>
|
||||
"{%col.colName_%}", // the alias for the {%col.colName_%} column.
|
||||
<%c++
|
||||
}else{
|
||||
%>
|
||||
"{%col.colName_%}" // the alias for the {%col.colName_%} column.
|
||||
<%c++
|
||||
}
|
||||
}
|
||||
%>
|
||||
});
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
<%inc#include "create_model.h"
|
||||
using namespace drogon_ctl;
|
||||
%>
|
||||
/**
|
||||
*
|
||||
* [[fileName]]Base.h
|
||||
* DO NOT EDIT. This file is generated by drogon_ctl automatically.
|
||||
* Users should implement business logic in the derived class.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <drogon/HttpController.h>
|
||||
#include <drogon/orm/RestfulController.h>
|
||||
|
||||
<%c++
|
||||
auto tableInfo = @@.get<DrTemplateData>("tableInfo");
|
||||
auto modelName = tableInfo.get<std::string>("className");
|
||||
$$<<"#include \""<<modelName<<".h\"\n";
|
||||
bool hasPrimaryKey = (tableInfo.get<int>("hasPrimaryKey")==1);
|
||||
$$<<"using namespace drogon;\n";
|
||||
|
||||
$$<<"using namespace drogon_model::"<<tableInfo.get<std::string>("dbName");
|
||||
auto &schema=tableInfo.get<std::string>("schema");
|
||||
if(!schema.empty())
|
||||
{
|
||||
$$<<"::"<<schema<<";\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$$<<";\n";
|
||||
}
|
||||
|
||||
auto namespaceVector=@@.get<std::vector<std::string>>("namespaceVector");
|
||||
for(auto &name:namespaceVector)
|
||||
{
|
||||
%>
|
||||
namespace {%name%}
|
||||
{
|
||||
<%c++}%>
|
||||
/**
|
||||
* @brief this class is created by the drogon_ctl command.
|
||||
* this class is a restful API controller for reading and writing the [[tableName]] table.
|
||||
*/
|
||||
|
||||
class [[className]]Base : public RestfulController
|
||||
{
|
||||
public:
|
||||
<%c++if(hasPrimaryKey)
|
||||
{
|
||||
%>
|
||||
void getOne(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%modelName%}::PrimaryKeyType &&id);
|
||||
void updateOne(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%modelName%}::PrimaryKeyType &&id);
|
||||
void deleteOne(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%modelName%}::PrimaryKeyType &&id);
|
||||
<%c++}
|
||||
%>
|
||||
void get(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback);
|
||||
void create(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback);
|
||||
|
||||
|
||||
// void update(const HttpRequestPtr &req,
|
||||
// std::function<void(const HttpResponsePtr &)> &&callback);
|
||||
|
||||
orm::DbClientPtr getDbClient()
|
||||
{
|
||||
return drogon::app().get{%(@@.get<bool>("isFastDbClient")?"Fast":"")%}DbClient(dbClientName_);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Ensure that subclasses inherited from this class are instantiated.
|
||||
[[className]]Base();
|
||||
const std::string dbClientName_{"[[dbClientName]]"};
|
||||
};
|
||||
<%c++ for(size_t i=0;i<namespaceVector.size();++i)
|
||||
{
|
||||
$$<<"}\n";
|
||||
}
|
||||
%>
|
@ -1,58 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* [[fileName]].cc
|
||||
* This file is generated by drogon_ctl
|
||||
*
|
||||
*/
|
||||
|
||||
#include "[[fileName]].h"
|
||||
#include <string>
|
||||
|
||||
<%c++
|
||||
auto namespaceVector=@@.get<std::vector<std::string>>("namespaceVector");
|
||||
std::string namespaceStr;
|
||||
for(auto &name:namespaceVector)
|
||||
{
|
||||
namespaceStr.append(name);
|
||||
namespaceStr.append("::");
|
||||
}
|
||||
if(!namespaceStr.empty())
|
||||
{
|
||||
namespaceStr.resize(namespaceStr.length()-2);
|
||||
$$<<"using namespace "<<namespaceStr<<";\n";
|
||||
}
|
||||
std::string indentStr(@@.get<std::string>("className").length(), ' ');
|
||||
%>
|
||||
|
||||
void [[className]]::getOne(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%indentStr%} std::string &&id)
|
||||
{
|
||||
}
|
||||
|
||||
void [[className]]::get(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
}
|
||||
void [[className]]::create(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
}
|
||||
void [[className]]::updateOne(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%indentStr%} std::string &&id)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
void [[className]]::update(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
|
||||
}*/
|
||||
|
||||
void [[className]]::deleteOne(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%indentStr%} std::string &&id)
|
||||
{
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* [[fileName]].cc
|
||||
* This file is generated by drogon_ctl
|
||||
*
|
||||
*/
|
||||
|
||||
#include "[[fileName]].h"
|
||||
#include <string>
|
||||
|
||||
<%c++
|
||||
|
||||
auto tableInfo = @@.get<DrTemplateData>("tableInfo");
|
||||
auto modelName = tableInfo.get<std::string>("className");
|
||||
bool hasPrimaryKey = (tableInfo.get<int>("hasPrimaryKey")==1);
|
||||
|
||||
|
||||
auto namespaceVector=@@.get<std::vector<std::string>>("namespaceVector");
|
||||
std::string namespaceStr;
|
||||
for(auto &name:namespaceVector)
|
||||
{
|
||||
namespaceStr.append(name);
|
||||
namespaceStr.append("::");
|
||||
}
|
||||
if(!namespaceStr.empty())
|
||||
{
|
||||
namespaceStr.resize(namespaceStr.length()-2);
|
||||
$$<<"using namespace "<<namespaceStr<<";\n";
|
||||
}
|
||||
std::string indentStr(@@.get<std::string>("className").length(), ' ');
|
||||
%>
|
||||
|
||||
<%c++
|
||||
if(hasPrimaryKey)
|
||||
{%>
|
||||
void [[className]]::getOne(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%indentStr%} {%modelName%}::PrimaryKeyType &&id)
|
||||
{
|
||||
[[className]]Base::getOne(req, std::move(callback), std::move(id));
|
||||
}
|
||||
|
||||
|
||||
void [[className]]::updateOne(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%indentStr%} {%modelName%}::PrimaryKeyType &&id)
|
||||
{
|
||||
[[className]]Base::updateOne(req, std::move(callback), std::move(id));
|
||||
}
|
||||
|
||||
|
||||
void [[className]]::deleteOne(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%indentStr%} {%modelName%}::PrimaryKeyType &&id)
|
||||
{
|
||||
[[className]]Base::deleteOne(req, std::move(callback), std::move(id));
|
||||
}
|
||||
<%c++}%>
|
||||
|
||||
void [[className]]::get(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
[[className]]Base::get(req, std::move(callback));
|
||||
}
|
||||
|
||||
void [[className]]::create(const HttpRequestPtr &req,
|
||||
{%indentStr%} std::function<void(const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
[[className]]Base::create(req, std::move(callback));
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
<%inc#include "create_model.h"
|
||||
using namespace drogon_ctl;
|
||||
%>
|
||||
/**
|
||||
*
|
||||
* [[fileName]].h
|
||||
* This file is generated by drogon_ctl
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <drogon/HttpController.h>
|
||||
#include "[[className]]Base.h"
|
||||
|
||||
<%c++
|
||||
auto tableInfo = @@.get<DrTemplateData>("tableInfo");
|
||||
auto modelName = tableInfo.get<std::string>("className");
|
||||
$$<<"#include \""<<modelName<<".h\"\n";
|
||||
bool hasPrimaryKey = (tableInfo.get<int>("hasPrimaryKey")==1);
|
||||
$$<<"using namespace drogon;\n";
|
||||
|
||||
$$<<"using namespace drogon_model::"<<tableInfo.get<std::string>("dbName");
|
||||
auto &schema=tableInfo.get<std::string>("schema");
|
||||
if(!schema.empty())
|
||||
{
|
||||
$$<<"::"<<schema<<";\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$$<<";\n";
|
||||
}
|
||||
|
||||
auto namespaceVector=@@.get<std::vector<std::string>>("namespaceVector");
|
||||
for(auto &name:namespaceVector)
|
||||
{
|
||||
%>
|
||||
namespace {%name%}
|
||||
{
|
||||
<%c++}%>
|
||||
/**
|
||||
* @brief this class is created by the drogon_ctl command.
|
||||
* this class is a restful API controller for reading and writing the [[tableName]] table.
|
||||
*/
|
||||
|
||||
class [[className]]: public drogon::HttpController<[[className]]>, public [[className]]Base
|
||||
{
|
||||
public:
|
||||
METHOD_LIST_BEGIN
|
||||
<%c++
|
||||
auto resource=@@.get<std::string>("resource");
|
||||
if(resource.empty())
|
||||
{
|
||||
if(hasPrimaryKey)
|
||||
{
|
||||
%>
|
||||
METHOD_ADD([[className]]::getOne,"/{1}",Get,Options[[filters]]);
|
||||
METHOD_ADD([[className]]::updateOne,"/{1}",Put,Options[[filters]]);
|
||||
METHOD_ADD([[className]]::deleteOne,"/{1}",Delete,Options[[filters]]);
|
||||
<%c++}%>
|
||||
METHOD_ADD([[className]]::get,"",Get,Options[[filters]]);
|
||||
METHOD_ADD([[className]]::create,"",Post,Options[[filters]]);
|
||||
//METHOD_ADD([[className]]::update,"",Put,Options[[filters]]);
|
||||
<%c++
|
||||
}else
|
||||
{
|
||||
if(hasPrimaryKey)
|
||||
{
|
||||
%>
|
||||
ADD_METHOD_TO([[className]]::getOne,"{%resource%}/{1}",Get,Options[[filters]]);
|
||||
ADD_METHOD_TO([[className]]::updateOne,"{%resource%}/{1}",Put,Options[[filters]]);
|
||||
ADD_METHOD_TO([[className]]::deleteOne,"{%resource%}/{1}",Delete,Options[[filters]]);
|
||||
<%c++}%>
|
||||
ADD_METHOD_TO([[className]]::get,"{%resource%}",Get,Options[[filters]]);
|
||||
ADD_METHOD_TO([[className]]::create,"{%resource%}",Post,Options[[filters]]);
|
||||
//ADD_METHOD_TO([[className]]::update,"{%resource%}",Put,Options[[filters]]);
|
||||
<%c++}%>
|
||||
METHOD_LIST_END
|
||||
|
||||
<%c++if(hasPrimaryKey)
|
||||
{
|
||||
%>
|
||||
void getOne(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%modelName%}::PrimaryKeyType &&id);
|
||||
void updateOne(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%modelName%}::PrimaryKeyType &&id);
|
||||
void deleteOne(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
{%modelName%}::PrimaryKeyType &&id);
|
||||
<%c++}
|
||||
%>
|
||||
void get(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback);
|
||||
void create(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback);
|
||||
|
||||
};
|
||||
<%c++ for(size_t i=0;i<namespaceVector.size();++i)
|
||||
{
|
||||
$$<<"}\n";
|
||||
}
|
||||
%>
|
@ -1,80 +0,0 @@
|
||||
<%inc#include "create_model.h"
|
||||
using namespace drogon_ctl;
|
||||
%>
|
||||
/**
|
||||
*
|
||||
* [[fileName]].h
|
||||
* This file is generated by drogon_ctl
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <drogon/HttpController.h>
|
||||
<%c++
|
||||
$$<<"using namespace drogon;\n";
|
||||
auto namespaceVector=@@.get<std::vector<std::string>>("namespaceVector");
|
||||
for(auto &name:namespaceVector)
|
||||
{
|
||||
%>
|
||||
namespace {%name%}
|
||||
{
|
||||
<%c++
|
||||
}
|
||||
%>
|
||||
/**
|
||||
* @brief this class is created by the drogon_ctl command ([[ctlCommand]]).
|
||||
* this class is a restful API controller.
|
||||
*/
|
||||
class [[className]]: public drogon::HttpController<[[className]]>
|
||||
{
|
||||
public:
|
||||
METHOD_LIST_BEGIN
|
||||
// use METHOD_ADD to add your custom processing function here;
|
||||
<%c++
|
||||
auto resource=@@.get<std::string>("resource");
|
||||
if(resource.empty())
|
||||
{
|
||||
%>
|
||||
METHOD_ADD([[className]]::getOne,"/{1}",Get,Options[[filters]]);
|
||||
METHOD_ADD([[className]]::get,"",Get,Options[[filters]]);
|
||||
METHOD_ADD([[className]]::create,"",Post,Options[[filters]]);
|
||||
METHOD_ADD([[className]]::updateOne,"/{1}",Put,Options[[filters]]);
|
||||
//METHOD_ADD([[className]]::update,"",Put,Options[[filters]]);
|
||||
METHOD_ADD([[className]]::deleteOne,"/{1}",Delete,Options[[filters]]);
|
||||
<%c++
|
||||
}else
|
||||
{
|
||||
%>
|
||||
ADD_METHOD_TO([[className]]::getOne,"{%resource%}/{1}",Get,Options[[filters]]);
|
||||
ADD_METHOD_TO([[className]]::updateOne,"{%resource%}/{1}",Put,Options[[filters]]);
|
||||
ADD_METHOD_TO([[className]]::deleteOne,"{%resource%}/{1}",Delete,Options[[filters]]);
|
||||
ADD_METHOD_TO([[className]]::get,"{%resource%}",Get,Options[[filters]]);
|
||||
ADD_METHOD_TO([[className]]::create,"{%resource%}",Post,Options[[filters]]);
|
||||
//ADD_METHOD_TO([[className]]::update,"{%resource%}",Put,Options[[filters]]);
|
||||
<%c++}%>
|
||||
METHOD_LIST_END
|
||||
|
||||
void getOne(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
std::string &&id);
|
||||
void updateOne(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
std::string &&id);
|
||||
void deleteOne(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
std::string &&id);
|
||||
void get(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback);
|
||||
void create(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback);
|
||||
|
||||
// void update(const HttpRequestPtr &req,
|
||||
// std::function<void(const HttpResponsePtr &)> &&callback);
|
||||
|
||||
};
|
||||
<%c++ for(size_t i=0;i<namespaceVector.size();++i)
|
||||
{
|
||||
$$<<"}\n";
|
||||
}
|
||||
%>
|
@ -1,66 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* version.cc
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "version.h"
|
||||
#include <drogon/config.h>
|
||||
#include <drogon/version.h>
|
||||
#include <trantor/net/Resolver.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace drogon_ctl;
|
||||
static const char banner[] =
|
||||
" _ \n"
|
||||
" __| |_ __ ___ __ _ ___ _ __ \n"
|
||||
" / _` | '__/ _ \\ / _` |/ _ \\| '_ \\ \n"
|
||||
"| (_| | | | (_) | (_| | (_) | | | |\n"
|
||||
" \\__,_|_| \\___/ \\__, |\\___/|_| |_|\n"
|
||||
" |___/ \n";
|
||||
|
||||
void version::handleCommand(std::vector<std::string> ¶meters) {
|
||||
std::cout << banner << std::endl;
|
||||
std::cout << "A utility for drogon" << std::endl;
|
||||
std::cout << "Version: " << DROGON_VERSION << std::endl;
|
||||
std::cout << "Git commit: " << DROGON_VERSION_SHA1 << std::endl;
|
||||
std::cout << "Compilation: \n Compiler: " << COMPILER_COMMAND
|
||||
<< "\n Compiler ID: " << COMPILER_ID
|
||||
<< "\n Compilation flags: " << COMPILATION_FLAGS
|
||||
<< INCLUDING_DIRS << std::endl;
|
||||
std::cout << "Libraries: \n postgresql: "
|
||||
<< (USE_POSTGRESQL ? "yes" : "no") << " (batch mode: "
|
||||
<< (LIBPQ_SUPPORTS_BATCH_MODE ? "yes)\n" : "no)\n")
|
||||
<< " mariadb: " << (USE_MYSQL ? "yes\n" : "no\n")
|
||||
<< " sqlite3: " << (USE_SQLITE3 ? "yes\n" : "no\n");
|
||||
#ifdef OpenSSL_FOUND
|
||||
std::cout << " openssl: yes\n";
|
||||
#else
|
||||
std::cout << " openssl: no\n";
|
||||
#endif
|
||||
#ifdef USE_BROTLI
|
||||
std::cout << " brotli: yes\n";
|
||||
#else
|
||||
std::cout << " brotli: no\n";
|
||||
#endif
|
||||
#ifdef Boost_FOUND
|
||||
std::cout << " boost: yes\n";
|
||||
#else
|
||||
std::cout << " boost: no\n";
|
||||
#endif
|
||||
#ifdef USE_REDIS
|
||||
std::cout << " hiredis: yes\n";
|
||||
#else
|
||||
std::cout << " hiredis: no\n";
|
||||
#endif
|
||||
std::cout << " c-ares: "
|
||||
<< (trantor::Resolver::isCAresUsed() ? "yes\n" : "no\n");
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* version.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CommandHandler.h"
|
||||
#include <drogon/DrObject.h>
|
||||
using namespace drogon;
|
||||
namespace drogon_ctl {
|
||||
class version : public DrObject<version>, public CommandHandler {
|
||||
public:
|
||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
||||
virtual std::string script() override {
|
||||
return "display version of this tool";
|
||||
}
|
||||
virtual bool isTopCommand() override {
|
||||
return true;
|
||||
}
|
||||
version() {
|
||||
}
|
||||
};
|
||||
} // namespace drogon_ctl
|
Loading…
Reference in New Issue
Block a user