Remove config.h

Modify the CMakeLists.txt

Remove the USE_ORM macro

Update trantor

Remove some std::dynamic_pointer_cast calls
This commit is contained in:
antao 2019-07-26 22:22:12 +08:00
parent 4599abf2f5
commit 40087fba9c
92 changed files with 1182 additions and 805 deletions

View File

@ -15,6 +15,7 @@ addons:
sources:
- xenial
- sourceline: 'deb http://archive.ubuntu.com/ubuntu xenial main'
- sourceline: 'ppa:mhier/libboost-latest'
packages:
- gcc
- g++
@ -27,6 +28,7 @@ addons:
- libsqlite3-dev
- build-essential
- cmake
- boost1.67
homebrew:
packages:
- jsoncpp

View File

@ -1,127 +1,158 @@
cmake_minimum_required (VERSION 3.2)
CMAKE_MINIMUM_REQUIRED (VERSION 3.2)
project (DROGON CXX)
message (STATUS "os:" ${CMAKE_SYSTEM_NAME})
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
#Clang, use c++17
set(CMAKE_CXX_STD_FLAGS c++17)
set(CXX_STD 17)
else()
EXEC_PROGRAM (gcc ARGS "--version | grep '^gcc'|awk '{print $3}' | sed s'/)//g' | sed s'/-.*//g'" OUTPUT_VARIABLE version)
MESSAGE(STATUS "This is gcc version:: " ${version})
if(version LESS 5.4.0)
MESSAGE(STATUS "gcc is too old")
stop()
elseif(version LESS 7.1.0)
set(CMAKE_CXX_STD_FLAGS c++14)
set(CXX_STD 14)
MESSAGE(STATUS "c++14")
else()
set(CMAKE_CXX_STD_FLAGS c++17)
set(CXX_STD 17)
MESSAGE(STATUS "c++17")
endif()
endif()
PROJECT (DROGON CXX)
MESSAGE (STATUS "os:" ${CMAKE_SYSTEM_NAME})
include_directories(${PROJECT_SOURCE_DIR}/trantor ${PROJECT_SOURCE_DIR}/lib/inc ${PROJECT_SOURCE_DIR}/orm_lib/inc)
include(CheckIncludeFileCXX)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules/)
CHECK_INCLUDE_FILE_CXX(any HAS_ANY)
CHECK_INCLUDE_FILE_CXX(string_view HAS_STRING_VIEW)
IF(HAS_ANY AND HAS_STRING_VIEW)
SET(DROGON_CXX_STANDARD 17)
ELSE()
SET(DROGON_CXX_STANDARD 14)
ENDIF()
IF(DROGON_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)
IF(Boost_FOUND)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
ENDIF()
ELSE()
MESSAGE(STATUS "use c++17")
ENDIF()
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/trantor
${PROJECT_SOURCE_DIR}/lib/inc
${PROJECT_SOURCE_DIR}/orm_lib/inc)
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules/)
#jsoncpp
find_package (Jsoncpp REQUIRED)
include_directories(${JSONCPP_INCLUDE_DIRS})
link_libraries(${JSONCPP_LIBRARIES})
FIND_PACKAGE (Jsoncpp REQUIRED)
INCLUDE_DIRECTORIES(${JSONCPP_INCLUDE_DIRS})
LINK_LIBRARIES(${JSONCPP_LIBRARIES})
message(STATUS "jsoncpp inc path:" ${JSONCPP_INCLUDE_DIRS})
MESSAGE(STATUS "jsoncpp inc path:" ${JSONCPP_INCLUDE_DIRS})
#MESSAGE(STATUS ${JSONCPP_LIBRARIES})
IF(NOT EXISTS ${JSONCPP_INCLUDE_DIRS}/json/version.h)
MESSAGE(FATAL_ERROR "Error: jsoncpp lib is too old.....stop")
ENDIF()
#message(STATUS ${JSONCPP_LIBRARIES})
if(NOT EXISTS ${JSONCPP_INCLUDE_DIRS}/json/version.h)
message(STATUS "jsoncpp lib is too old.....stop")
stop()
endif()
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(STATUS "jsoncpp lib is too old,please get new version from https://github.com/open-source-parsers/jsoncpp")
stop()
endif()
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()
find_package (UUID REQUIRED)
include_directories(${UUID_INCLUDE_DIR})
link_libraries(${UUID_LIBRARIES})
FIND_PACKAGE (UUID REQUIRED)
INCLUDE_DIRECTORIES(${UUID_INCLUDE_DIR})
LINK_LIBRARIES(${UUID_LIBRARIES})
find_package (OpenSSL)
if(OpenSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIR})
link_libraries(${OPENSSL_LIBRARIES})
message(STATUS "openssl inc path:" ${OPENSSL_INCLUDE_DIR})
else()
aux_source_directory(${PROJECT_SOURCE_DIR}/lib/src/ssl_funcs DIR_SRCS)
endif()
FIND_PACKAGE(ZLIB REQUIRED)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
LINK_LIBRARIES(${ZLIB_LIBRARIES})
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/HttpClientImpl.cc
lib/src/HttpControllersRouter.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/HttpViewBase.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/SessionManager.cc
lib/src/SharedLibManager.cc
lib/src/StaticFileRouter.cc
lib/src/Utilities.cc
lib/src/WebSocketClientImpl.cc
lib/src/WebSocketConnectionImpl.cc
lib/src/WebsocketControllersRouter.cc)
FIND_PACKAGE (OpenSSL)
IF(OpenSSL_FOUND)
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
LINK_LIBRARIES(${OPENSSL_LIBRARIES})
MESSAGE(STATUS "openssl inc path:" ${OPENSSL_INCLUDE_DIR})
ELSE()
SET(drogon_sources ${drogon_sources} lib/src/ssl_funcs/Md5.cc
lib/src/ssl_funcs/Sha1.cc)
ENDIF()
find_package(ZLIB REQUIRED)
include_directories(${ZLIB_INCLUDE_DIR})
link_libraries(${ZLIB_LIBRARIES})
message(STATUS "zlib inc path:" ${ZLIB_INCLUDE_DIR})
if(NOT BUILD_ORM)
set(BUILD_ORM TRUE CACHE BOOL INTERNAL)
endif()
if(BUILD_ORM)
IF(NOT BUILD_ORM)
SET(BUILD_ORM TRUE CACHE BOOL INTERNAL)
ENDIF()
IF(BUILD_ORM)
#find postgres
find_package(PostgreSQL)
if(PostgreSQL_FOUND)
include_directories(${PostgreSQL_INCLUDE_DIR})
message(STATUS "libpq inc path:" ${PostgreSQL_INCLUDE_DIR})
link_libraries(${PostgreSQL_LIBRARIES})
aux_source_directory(${PROJECT_SOURCE_DIR}/orm_lib/src/postgresql_impl DIR_SRCS)
set(USE_ORM TRUE)
endif()
FIND_PACKAGE(PostgreSQL)
IF(PostgreSQL_FOUND)
INCLUDE_DIRECTORIES(${PostgreSQL_INCLUDE_DIR})
MESSAGE(STATUS "libpq inc path:" ${PostgreSQL_INCLUDE_DIR})
LINK_LIBRARIES(${PostgreSQL_LIBRARIES})
SET(drogon_sources ${drogon_sources}
orm_lib/src/postgresql_impl/PgConnection.cc
orm_lib/src/postgresql_impl/PostgreSQLResultImpl.cc)
ENDIF()
#Find mysql, only mariadb client liberary is supported
find_package(MySQL)
if(MYSQL_FOUND)
message(STATUS "inc:" ${MYSQL_INCLUDE_DIR})
message(STATUS "libs:" ${MYSQL_CLIENT_LIBS})
message(STATUS "version:" ${MYSQL_VERSION_STRING})
if(MYSQL_VERSION_STRING STREQUAL "")
set(MYSQL_FOUND false)
message(STATUS "The mysql in your system is not the mariadb, so we can't use it in drogon")
else()
message(STATUS "Ok! We find the mariadb!")
include_directories(${MYSQL_INCLUDE_DIR})
link_libraries(${MYSQL_CLIENT_LIBS})
aux_source_directory(${PROJECT_SOURCE_DIR}/orm_lib/src/mysql_impl DIR_SRCS)
set(USE_ORM TRUE)
endif()
endif()
FIND_PACKAGE(MySQL)
IF(MYSQL_FOUND)
MESSAGE(STATUS "inc:" ${MYSQL_INCLUDE_DIR})
MESSAGE(STATUS "libs:" ${MYSQL_CLIENT_LIBS})
MESSAGE(STATUS "version:" ${MYSQL_VERSION_STRING})
IF(MYSQL_VERSION_STRING STREQUAL "")
SET(MYSQL_FOUND false)
MESSAGE(STATUS "The mysql in your system is not the mariadb, so we can't use it in drogon")
ELSE()
MESSAGE(STATUS "Ok! We find the mariadb!")
INCLUDE_DIRECTORIES(${MYSQL_INCLUDE_DIR})
LINK_LIBRARIES(${MYSQL_CLIENT_LIBS})
SET(drogon_sources ${drogon_sources}
orm_lib/src/mysql_impl/MysqlConnection.cc
orm_lib/src/mysql_impl/MysqlResultImpl.cc)
ENDIF()
ENDIF()
#Find sqlite3.
find_package (SQLite3)
FIND_PACKAGE (SQLite3)
if (SQLITE3_FOUND)
include_directories(${SQLITE3_INCLUDE_DIRS})
link_libraries(${SQLITE3_LIBRARIES})
aux_source_directory(${PROJECT_SOURCE_DIR}/orm_lib/src/sqlite3_impl DIR_SRCS)
set(USE_ORM TRUE)
endif()
MESSAGE(STATUS "SQLite3 inc:" ${SQLITE3_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${SQLITE3_INCLUDE_DIRS})
LINK_LIBRARIES(${SQLITE3_LIBRARIES})
SET(drogon_sources ${drogon_sources}
orm_lib/src/sqlite3_impl/Sqlite3Connection.cc
orm_lib/src/sqlite3_impl/Sqlite3ResultImpl.cc)
ENDIF()
ENDIF()
endif()
#message(STATUS ${DIR_SRCS})
if(CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -std=${CMAKE_CXX_STD_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -std=${CMAKE_CXX_STD_FLAGS}")
add_subdirectory(trantor)
ADD_SUBDIRECTORY(trantor)
add_custom_target(makeVersion)
add_custom_command(TARGET makeVersion
@ -130,117 +161,179 @@ add_custom_command(TARGET makeVersion
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
VERBATIM )
if(NOT BUILD_EXAMPLES)
set(BUILD_EXAMPLES TRUE CACHE BOOL INTERNAL)
endif()
IF(NOT BUILD_EXAMPLES)
SET(BUILD_EXAMPLES TRUE CACHE BOOL INTERNAL)
ENDIF()
if(BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
IF(BUILD_EXAMPLES)
ADD_SUBDIRECTORY(examples)
ENDIF()
if(NOT BUILD_CTL)
set(BUILD_CTL TRUE CACHE BOOL INTERNAL)
endif()
IF(NOT BUILD_CTL)
SET(BUILD_CTL TRUE CACHE BOOL INTERNAL)
ENDIF()
if(BUILD_CTL)
add_subdirectory(drogon_ctl)
endif()
IF(BUILD_CTL)
ADD_SUBDIRECTORY(drogon_ctl)
ENDIF()
aux_source_directory(${PROJECT_SOURCE_DIR}/lib/src DIR_SRCS)
IF(PostgreSQL_FOUND OR MYSQL_FOUND OR SQLITE3_FOUND)
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/DbClientManager.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)
ELSE()
SET(drogon_sources ${drogon_sources} lib/src/DbClientManagerSkipped.cc)
ENDIF()
if(BUILD_ORM)
aux_source_directory(${PROJECT_SOURCE_DIR}/orm_lib/src DIR_SRCS)
endif()
ADD_LIBRARY(drogon ${drogon_sources})
ADD_LIBRARY(drogon ${DIR_SRCS})
SET_PROPERTY(TARGET drogon PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD})
SET_PROPERTY(TARGET drogon PROPERTY CXX_STANDARD_REQUIRED ON)
SET_PROPERTY(TARGET drogon PROPERTY CXX_EXTENSIONS OFF)
add_dependencies(drogon trantor makeVersion)
ADD_DEPENDENCIES(drogon trantor makeVersion)
IF(PostgreSQL_FOUND OR MYSQL_FOUND OR SQLITE3_FOUND)
IF(PostgreSQL_FOUND)
OPTION(USE_POSTGRESQL "Enable PostgreSQL" ON)
ELSE()
OPTION(USE_POSTGRESQL "Disable PostgreSQL" OFF)
ENDIF()
IF(MYSQL_FOUND)
OPTION(USE_MYSQL "Enable Mysql" ON)
ELSE()
OPTION(USE_MYSQL "DisableMysql" OFF)
ENDIF()
IF(SQLITE3_FOUND)
OPTION(USE_SQLITE3 "Enable Sqlite3" ON)
ELSE()
OPTION(USE_SQLITE3 "Disable Sqlite3" OFF)
ENDIF()
ENDIF()
SET(COMPILER_COMMAND ${CMAKE_CXX_COMPILER})
SET(COMPILER_ID ${CMAKE_CXX_COMPILER_ID})
SET(CONFIG_HEADER "${PROJECT_SOURCE_DIR}/config.h")
file(WRITE "${CONFIG_HEADER}" "#pragma once\n")
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()
SET(COMPILATION_FLAGS "-std=c++")
ENDIF()
file(APPEND "${CONFIG_HEADER}" "#include <trantor/utils/config.h>\n")
file(APPEND "${CONFIG_HEADER}" "#define CXX_STD " ${CXX_STD} "\n")
if(USE_ORM)
file(APPEND "${CONFIG_HEADER}" "#define USE_ORM 1\n")
if(PostgreSQL_FOUND)
file(APPEND "${CONFIG_HEADER}" "#define USE_POSTGRESQL 1\n")
else()
file(APPEND "${CONFIG_HEADER}" "#define USE_POSTGRESQL 0\n")
endif()
GET_TARGET_PROPERTY(INS drogon INCLUDE_DIRECTORIES)
SET(TMP_INS "")
SET(INS_STRING "")
FOREACH(loop_var ${INS})
IF(TMP_INS MATCHES ";${loop_var};")
ELSE()
SET(TMP_INS ";${loop_var};${TMP_INS}")
SET(INS_STRING "${INS_STRING} -I${loop_var}")
ENDIF()
ENDFOREACH(loop_var)
if(MYSQL_FOUND)
file(APPEND "${CONFIG_HEADER}" "#define USE_MYSQL 1\n")
else()
file(APPEND "${CONFIG_HEADER}" "#define USE_MYSQL 0\n")
endif()
SET(INCLUDING_DIRS ${INS_STRING})
if(SQLITE3_FOUND)
file(APPEND "${CONFIG_HEADER}" "#define USE_SQLITE3 1\n")
else()
file(APPEND "${CONFIG_HEADER}" "#define USE_SQLITE3 0\n")
endif()
else()
file(APPEND "${CONFIG_HEADER}" "#define USE_ORM 0\n")
endif()
string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER)
if(CMAKE_BUILD_TYPE_LOWER STREQUAL release)
file(APPEND "${CONFIG_HEADER}" "\n" "const char compileFlags[] = \"" ${CMAKE_CXX_FLAGS_RELEASE} "\";\n")
else()
file(APPEND "${CONFIG_HEADER}" "\n" "const char compileFlags[] = \"" ${CMAKE_CXX_FLAGS_DEBUG} "\";\n")
endif()
file(APPEND "${CONFIG_HEADER}" "const char compilerCommand[] = \"${CMAKE_CXX_COMPILER}\";\n")
file(APPEND "${CONFIG_HEADER}" "const char compilerId[] = \"${CMAKE_CXX_COMPILER_ID}\";\n")
get_target_property(INS drogon INCLUDE_DIRECTORIES)
file(APPEND "${CONFIG_HEADER}" "\nconst char includeDirs[]=\"")
set(TMP_INS,"")
foreach(loop_var ${INS})
if(TMP_INS MATCHES ";${loop_var};")
else()
set(TMP_INS ";${loop_var};${TMP_INS}")
file(APPEND "${CONFIG_HEADER}" "-I" ${loop_var} " ")
endif()
endforeach(loop_var)
file(APPEND "${CONFIG_HEADER}" "\";\n")
EXEC_PROGRAM(${PROJECT_SOURCE_DIR}/update_config.sh ARGS "${CONFIG_HEADER} ${PROJECT_SOURCE_DIR}/lib/inc/drogon/config.h")
configure_file(${PROJECT_SOURCE_DIR}/lib/inc/drogon/config.h.in
${PROJECT_SOURCE_DIR}/lib/inc/drogon/config.h @ONLY)
if (MAKETEST STREQUAL YES)
ADD_SUBDIRECTORY(lib/tests)
if(PostgreSQL_FOUND)
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/postgresql_impl/test)
endif()
if(MYSQL_FOUND)
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/mysql_impl/test)
endif()
if(SQLITE3_FOUND)
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/sqlite3_impl/test)
endif()
if(USE_ORM)
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/tests)
endif()
IF(PostgreSQL_FOUND)
ADD_SUBDIRECTORY(${PROJECT_SOURCE_DIR}/orm_lib/src/postgresql_impl/test)
ADD_SUBDIRECTORY(${PROJECT_SOURCE_DIR}/orm_lib/tests)
ENDIF()
IF(MYSQL_FOUND)
ADD_SUBDIRECTORY(${PROJECT_SOURCE_DIR}/orm_lib/src/mysql_impl/test)
ENDIF()
IF(SQLITE3_FOUND)
ADD_SUBDIRECTORY(${PROJECT_SOURCE_DIR}/orm_lib/src/sqlite3_impl/test)
ENDIF()
endif ()
#Installation
install(TARGETS drogon DESTINATION lib)
INSTALL(TARGETS drogon DESTINATION lib)
file(GLOB drogon_headers "${CMAKE_CURRENT_SOURCE_DIR}/lib/inc/drogon/*.h")
install(FILES ${drogon_headers} DESTINATION include/drogon)
if(USE_ORM)
file(GLOB orm_headers "${CMAKE_CURRENT_SOURCE_DIR}/orm_lib/inc/drogon/orm/*.h")
install(FILES ${orm_headers} DESTINATION include/drogon/orm)
endif()
file(GLOB drogon_util_headers "${CMAKE_CURRENT_SOURCE_DIR}/lib/inc/drogon/utils/*.h")
install(FILES ${drogon_util_headers}
SET(drogon_headers
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/HttpViewBase.h
lib/inc/drogon/HttpViewData.h
lib/inc/drogon/IntranetIpFilter.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)
INSTALL(FILES ${drogon_headers} DESTINATION include/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/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/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)
INSTALL(FILES ${orm_headers} DESTINATION include/drogon/orm)
SET(drogon_util_headers
lib/inc/drogon/utils/ClassTraits.h
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/HttpConstraint.h)
INSTALL(FILES ${drogon_util_headers}
DESTINATION include/drogon/utils)
file(GLOB drogon_plugin_headers "${CMAKE_CURRENT_SOURCE_DIR}/lib/inc/drogon/plugins/*.h")
install(FILES ${drogon_plugin_headers}
SET(drogon_plugin_headers lib/inc/drogon/plugins/Plugin.h)
INSTALL(FILES ${drogon_plugin_headers}
DESTINATION include/drogon/plugins)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/lib/inc/drogon/version.h"
DESTINATION include/drogon)
SOURCE_GROUP( "Public API" FILES ${drogon_headers}
${orm_headers}
${drogon_util_headers}
${drogon_plugin_headers})

View File

@ -1,21 +1,37 @@
link_libraries(drogon trantor pthread dl)
LINK_LIBRARIES(drogon trantor pthread dl)
AUX_SOURCE_DIRECTORY(. SRC_DIR)
add_executable(_drogon_ctl main.cc cmd.cc create.cc create_view.cc)
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)
FILE(GLOB SCP_LIST ${CMAKE_CURRENT_SOURCE_DIR}/templates/*.csp)
foreach(cspFile ${SCP_LIST})
message(STATUS "cspFile:" ${cspFile})
FOREACH(cspFile ${SCP_LIST})
MESSAGE(STATUS "cspFile:" ${cspFile})
EXEC_PROGRAM(basename ARGS "${cspFile} .csp" OUTPUT_VARIABLE classname)
message(STATUS "view classname:" ${classname})
add_custom_command(OUTPUT ${classname}.h ${classname}.cc
MESSAGE(STATUS "view classname:" ${classname})
ADD_CUSTOM_COMMAND(OUTPUT ${classname}.h ${classname}.cc
COMMAND _drogon_ctl
ARGS create view ${cspFile}
DEPENDS ${cspFile}
VERBATIM )
set(TEMPL_SRC ${TEMPL_SRC} ${classname}.cc)
endforeach()
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_executable(drogon_ctl ${SRC_DIR} ${TEMPL_SRC})
add_dependencies(drogon_ctl trantor makeVersion _drogon_ctl)
install(TARGETS drogon_ctl DESTINATION bin)
install(PROGRAMS $<TARGET_FILE_DIR:drogon_ctl>/drogon_ctl DESTINATION bin RENAME dg_ctl)
SET(TEMPL_SRC ${TEMPL_SRC} ${classname}.cc)
ENDFOREACH()
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
ADD_EXECUTABLE(drogon_ctl ${ctl_sources} ${TEMPL_SRC})
ADD_DEPENDENCIES(drogon_ctl trantor makeVersion _drogon_ctl)
INSTALL(TARGETS drogon_ctl DESTINATION bin)
INSTALL(PROGRAMS $<TARGET_FILE_DIR:drogon_ctl>/drogon_ctl DESTINATION bin RENAME dg_ctl)
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)

View File

@ -341,7 +341,7 @@ void create_controller::createController(const std::string &className,
if (!oHeadFile || !oSourceFile)
{
perror("");
exit(-1);
exit(1);
}
if (type == Http)
{

View File

@ -105,7 +105,7 @@ void create_filter::handleCommand(std::vector<std::string> &parameters)
if (!oHeadFile || !oSourceFile)
{
perror("");
exit(-1);
exit(1);
}
std::cout << "create a http filter:" << className << std::endl;

View File

@ -768,6 +768,10 @@ void create_model::createModel(const std::string &path,
createModelClassFromSqlite3(path, client, tableName);
}
}
#else
std::cerr << "Drogon does not support Sqlite3, please install Sqlite3 "
"development environment before installing drogon"
<< std::endl;
#endif
}
else if (dbType == "no dbms")
@ -825,7 +829,6 @@ void create_model::createModel(const std::string &path)
void create_model::handleCommand(std::vector<std::string> &parameters)
{
#if USE_ORM
std::cout << "Create model" << std::endl;
if (parameters.size() == 0)
{
@ -835,10 +838,4 @@ void create_model::handleCommand(std::vector<std::string> &parameters)
{
createModel(path);
}
#else
std::cout
<< "No database can be found in your system, please install one first!"
<< std::endl;
exit(1);
#endif
}

View File

@ -16,10 +16,8 @@
#include <drogon/config.h>
#include <json/json.h>
#if USE_ORM
#include <drogon/orm/DbClient.h>
using namespace drogon::orm;
#endif
#include <drogon/DrObject.h>
#include "CommandHandler.h"
#include <string>

View File

@ -105,7 +105,7 @@ void create_plugin::handleCommand(std::vector<std::string> &parameters)
if (!oHeadFile || !oSourceFile)
{
perror("");
exit(-1);
exit(1);
}
std::cout << "create a plugin:" << className << std::endl;

View File

@ -330,7 +330,6 @@ void create_view::newViewSourceFile(std::ofstream &file,
file << "//this file is generated by program(drogon_ctl) "
"automatically,don't modify it!\n";
file << "#include \"" << className << ".h\"\n";
file << "#include <drogon/config.h>\n";
file << "#include <string>\n";
file << "#include <sstream>\n";
file << "#include <map>\n";

View File

@ -38,7 +38,7 @@ std::string press::detail()
void outputErrorAndExit(const string_view &err)
{
std::cout << err << std::endl;
exit(-1);
exit(1);
}
void press::handleCommand(std::vector<std::string> &parameters)
{

View File

@ -1,85 +1,85 @@
cmake_minimum_required (VERSION 3.2)
Project([[ProjectName]])
PROJECT([[ProjectName]])
link_directories(/usr/local/lib)
link_libraries(drogon trantor pthread dl)
LINK_DIRECTORIES(/usr/local/lib)
LINK_LIBRARIES(drogon trantor pthread dl)
IF (CMAKE_SYSTEM_NAME MATCHES "Linux")
EXEC_PROGRAM (gcc ARGS "--version | grep '^gcc'|awk '{print $3}' | sed s'/)//g' | sed s'/-.*//g'" OUTPUT_VARIABLE version)
MESSAGE(STATUS "This is gcc version:: " ${version})
if(version LESS 5.4.0)
MESSAGE(STATUS "gcc is too old")
stop()
elseif(version LESS 7.1.0)
set(CMAKE_CXX_STD_FLAGS c++14)
MESSAGE(STATUS "c++14")
else()
set(CMAKE_CXX_STD_FLAGS c++17)
MESSAGE(STATUS "c++17")
endif()
else()
set(CMAKE_CXX_STD_FLAGS c++17)
endif()
INCLUDE(CheckIncludeFileCXX)
if(CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE Release)
endif()
CHECK_INCLUDE_FILE_CXX(any HAS_ANY)
CHECK_INCLUDE_FILE_CXX(string_view HAS_STRING_VIEW)
IF(HAS_ANY AND HAS_STRING_VIEW)
SET(CMAKE_CXX_STANDARD 17)
ELSE()
SET(CMAKE_CXX_STANDARD 14)
ENDIF()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -std=${CMAKE_CXX_STD_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -std=${CMAKE_CXX_STD_FLAGS}")
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules/)
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 REQUIRED)
IF(Boost_FOUND)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
ENDIF()
ELSE()
MESSAGE(STATUS "use c++17")
ENDIF()
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules/)
#jsoncpp
find_package (Jsoncpp REQUIRED)
include_directories(${JSONCPP_INCLUDE_DIRS})
link_libraries(${JSONCPP_LIBRARIES})
FIND_PACKAGE (Jsoncpp REQUIRED)
INCLUDE_DIRECTORIES(${JSONCPP_INCLUDE_DIRS})
LINK_LIBRARIES(${JSONCPP_LIBRARIES})
#uuid
find_package (UUID REQUIRED)
include_directories(${UUID_INCLUDE_DIR})
link_libraries(${UUID_LIBRARIES})
FIND_PACKAGE (UUID REQUIRED)
INCLUDE_DIRECTORIES(${UUID_INCLUDE_DIR})
LINK_LIBRARIES(${UUID_LIBRARIES})
#OpenSSL
find_package (OpenSSL)
if(OpenSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIR})
link_libraries(${OPENSSL_LIBRARIES})
endif()
FIND_PACKAGE (OpenSSL)
IF(OpenSSL_FOUND)
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
LINK_LIBRARIES(${OPENSSL_LIBRARIES})
ENDIF()
#zlib
find_package(ZLIB REQUIRED)
include_directories(${ZLIB_INCLUDE_DIR})
link_libraries(${ZLIB_LIBRARIES})
FIND_PACKAGE(ZLIB REQUIRED)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
LINK_LIBRARIES(${ZLIB_LIBRARIES})
#find postgres
find_package(PostgreSQL)
if(PostgreSQL_FOUND)
include_directories(${PostgreSQL_INCLUDE_DIR})
link_libraries(${PostgreSQL_LIBRARIES})
endif()
FIND_PACKAGE(PostgreSQL)
IF(PostgreSQL_FOUND)
INCLUDE_DIRECTORIES(${PostgreSQL_INCLUDE_DIR})
LINK_LIBRARIES(${PostgreSQL_LIBRARIES})
ENDIF()
#Find mysql, only mariadb client liberary is supported
find_package(MySQL)
if(MYSQL_FOUND)
message(STATUS "inc:" ${MYSQL_INCLUDE_DIR})
message(STATUS "libs:" ${MYSQL_CLIENT_LIBS})
message(STATUS "version:" ${MYSQL_VERSION_STRING})
if(MYSQL_VERSION_STRING STREQUAL "")
message(STATUS "The mysql in your system is not the mariadb, so we can't use it in drogon")
else()
message(STATUS "Ok! We find the mariadb!")
include_directories(${MYSQL_INCLUDE_DIR})
link_libraries(${MYSQL_CLIENT_LIBS})
endif()
endif()
FIND_PACKAGE(MySQL)
IF(MYSQL_FOUND)
MESSAGE(STATUS "inc:" ${MYSQL_INCLUDE_DIR})
MESSAGE(STATUS "libs:" ${MYSQL_CLIENT_LIBS})
MESSAGE(STATUS "version:" ${MYSQL_VERSION_STRING})
IF(MYSQL_VERSION_STRING STREQUAL "")
MESSAGE(STATUS "The mysql in your system is not the mariadb, so we can't use it in drogon")
ELSE()
MESSAGE(STATUS "Ok! We find the mariadb!")
INCLUDE_DIRECTORIES(${MYSQL_INCLUDE_DIR})
LINK_LIBRARIES(${MYSQL_CLIENT_LIBS})
ENDIF()
ENDIF()
#Find sqlite3.
find_package (SQLite3)
FIND_PACKAGE (SQLite3)
if (SQLITE3_FOUND)
include_directories(${SQLITE3_INCLUDE_DIRS})
link_libraries(${SQLITE3_LIBRARIES})
endif()
INCLUDE_DIRECTORIES(${SQLITE3_INCLUDE_DIRS})
LINK_LIBRARIES(${SQLITE3_LIBRARIES})
ENDIF()
AUX_SOURCE_DIRECTORY(./ SRC_DIR)
AUX_SOURCE_DIRECTORY(controllers CTL_SRC)
@ -87,20 +87,20 @@ AUX_SOURCE_DIRECTORY(filters FILTER_SRC)
AUX_SOURCE_DIRECTORY(plugins PLUGIN_SRC)
AUX_SOURCE_DIRECTORY(models MODEL_SRC)
include_directories(/usr/local/include)
INCLUDE_DIRECTORIES(/usr/local/include)
FILE(GLOB SCP_LIST ${CMAKE_CURRENT_SOURCE_DIR}/views/*.csp)
foreach(cspFile ${SCP_LIST})
message(STATUS "cspFile:" ${cspFile})
FOREACH(cspFile ${SCP_LIST})
MESSAGE(STATUS "cspFile:" ${cspFile})
EXEC_PROGRAM(basename ARGS "${cspFile} .csp" OUTPUT_VARIABLE classname)
message(STATUS "view classname:" ${classname})
add_custom_command(OUTPUT ${classname}.h ${classname}.cc
MESSAGE(STATUS "view classname:" ${classname})
ADD_CUSTOM_COMMAND(OUTPUT ${classname}.h ${classname}.cc
COMMAND drogon_ctl
ARGS create view ${cspFile}
DEPENDS ${cspFile}
VERBATIM )
set(VIEWSRC ${VIEWSRC} ${classname}.cc)
endforeach()
SET(VIEWSRC ${VIEWSRC} ${classname}.cc)
ENDFOREACH()
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_executable([[ProjectName]] ${SRC_DIR} ${CTL_SRC} ${FILTER_SRC} ${VIEWSRC} ${PLUGIN_SRC} ${MODEL_SRC})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
ADD_EXECUTABLE([[ProjectName]] ${SRC_DIR} ${CTL_SRC} ${FILTER_SRC} ${VIEWSRC} ${PLUGIN_SRC} ${MODEL_SRC})

View File

@ -9,7 +9,6 @@ using namespace drogon_ctl;
*/
#include "[[className]].h"
#include <trantor/utils/config.h>
#include <drogon/utils/Utilities.h>
#include <string>
<%c++
@ -17,6 +16,7 @@ using namespace drogon_ctl;
auto className=@@.get<std::string>("className");
%>
using namespace drogon;
using namespace drogon_model::[[dbName]];
<%c++for(auto col:cols){

View File

@ -22,6 +22,7 @@ using namespace drogon_ctl;
#include <tuple>
#include <stdint.h>
#include <iostream>
using namespace drogon::orm;
namespace drogon_model

View File

@ -13,8 +13,8 @@
*/
#include "version.h"
#include <drogon/version.h>
#include <drogon/config.h>
#include <drogon/version.h>
#include <iostream>
using namespace drogon_ctl;
@ -32,6 +32,6 @@ void version::handleCommand(std::vector<std::string> &parameters)
std::cout << "A utility for drogon" << std::endl;
std::cout << "Version:" << VERSION << std::endl;
std::cout << "Git commit:" << VERSION_MD5 << std::endl;
std::cout << "Compile config:" << compileFlags << " " << includeDirs
std::cout << "Compile config:" << COMPILATION_FLAGS << " " << INCLUDING_DIRS
<< std::endl;
}

View File

@ -1,40 +1,62 @@
link_libraries(drogon trantor pthread dl)
LINK_LIBRARIES(drogon trantor pthread dl)
FILE(GLOB SCP_LIST ${CMAKE_CURRENT_SOURCE_DIR}/simple_example/*.csp)
foreach(cspFile ${SCP_LIST})
message(STATUS "cspFile:" ${cspFile})
FOREACH(cspFile ${SCP_LIST})
MESSAGE(STATUS "cspFile:" ${cspFile})
EXEC_PROGRAM(basename ARGS "${cspFile} .csp" OUTPUT_VARIABLE classname)
message(STATUS "view classname:" ${classname})
add_custom_command(OUTPUT ${classname}.h ${classname}.cc
MESSAGE(STATUS "view classname:" ${classname})
ADD_CUSTOM_COMMAND(OUTPUT ${classname}.h ${classname}.cc
COMMAND drogon_ctl
ARGS create view ${cspFile}
DEPENDS ${cspFile}
VERBATIM )
set(VIEWSRC ${VIEWSRC} ${classname}.cc)
endforeach()
SET(VIEWSRC ${VIEWSRC} ${classname}.cc)
ENDFOREACH()
AUX_SOURCE_DIRECTORY(simple_example DIR_STATIC)
SET(simple_example_sources simple_example/CustomCtrl.cc
simple_example/CustomHeaderFilter.cc
simple_example/DoNothingPlugin.cc
simple_example/ForwardCtrl.cc
simple_example/JsonTestController.cc
simple_example/ListParaCtl.cc
simple_example/PipeliningTest.cc
simple_example/TestController.cc
simple_example/TestPlugin.cc
simple_example/TestViewCtl.cc
simple_example/WebSocketTest.cc
simple_example/api_Attachment.cc
simple_example/api_v1_ApiTest.cc
simple_example/TimeFilter.cc
simple_example/main.cc)
add_executable(webapp ${DIR_STATIC} ${VIEWSRC})
add_dependencies(webapp drogon_ctl)
ADD_EXECUTABLE(webapp ${simple_example_sources} ${VIEWSRC})
ADD_DEPENDENCIES(webapp drogon_ctl)
AUX_SOURCE_DIRECTORY(client_example DIR_CLIENT)
AUX_SOURCE_DIRECTORY(benchmark DIR_BENCHMARK)
SET(client_example_sources client_example/main.cc)
SET(benchmark_sources benchmark/BenchmarkCtrl.cc
benchmark/JsonCtrl.cc
benchmark/main.cc)
#AUX_SOURCE_DIRECTORY(simple_example_test DIR_TEST)
add_executable(client ${DIR_CLIENT})
add_executable(benchmark ${DIR_BENCHMARK})
add_executable(webapp_test simple_example_test/main.cc)
add_executable(pipelining_test simple_example_test/HttpPipeliningTest.cc)
add_executable(websocket_test simple_example_test/WebSocketTest.cc)
ADD_EXECUTABLE(client ${client_example_sources})
ADD_EXECUTABLE(benchmark ${benchmark_sources})
ADD_EXECUTABLE(webapp_test simple_example_test/main.cc)
ADD_EXECUTABLE(pipelining_test simple_example_test/HttpPipeliningTest.cc)
ADD_EXECUTABLE(websocket_test simple_example_test/WebSocketTest.cc)
add_custom_command(TARGET webapp POST_BUILD
ADD_CUSTOM_COMMAND(TARGET webapp POST_BUILD
COMMAND gzip
ARGS -c ${CMAKE_CURRENT_SOURCE_DIR}/simple_example/index.html > ${CMAKE_CURRENT_BINARY_DIR}/index.html.gz
VERBATIM)
add_custom_command(TARGET webapp POST_BUILD
ADD_CUSTOM_COMMAND(TARGET webapp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${PROJECT_SOURCE_DIR}/config.example.json ${PROJECT_SOURCE_DIR}/drogon.jpg
${CMAKE_CURRENT_SOURCE_DIR}/simple_example/index.html
${PROJECT_SOURCE_DIR}/trantor/trantor/tests/server.pem $<TARGET_FILE_DIR:webapp>)
${PROJECT_SOURCE_DIR}/trantor/trantor/tests/server.pem $<TARGET_FILE_DIR:webapp>)
SET(example_targets webapp webapp_test client benchmark pipelining_test websocket_test)
SET_PROPERTY(TARGET ${example_targets} PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD})
SET_PROPERTY(TARGET ${example_targets} PROPERTY CXX_STANDARD_REQUIRED ON)
SET_PROPERTY(TARGET ${example_targets} PROPERTY CXX_EXTENSIONS OFF)

View File

@ -5,8 +5,10 @@ void TestController::asyncHandleHttpRequest(
std::function<void(const HttpResponsePtr &)> &&callback)
{
// write your application logic here
LOG_WARN << req->matchedPathPattern();
LOG_WARN << req->matchedPathPatternData();
auto resp = HttpResponse::newHttpResponse();
resp->setContentTypeCodeAndCustomString(CT_TEXT_PLAIN,
"Content-Type: plaintext\r\n");
resp->setBody("<p>Hello, world!</p>");
resp->setExpiredTime(0);
callback(resp);

View File

@ -38,7 +38,7 @@ void ApiTest::your_method_name(
double p1,
int p2) const
{
LOG_WARN << req->matchedPathPattern();
LOG_WARN << req->matchedPathPatternData();
HttpViewData data;
data.insert("title", std::string("ApiTest::get"));
std::map<std::string, std::string> para;

View File

@ -1,9 +1,11 @@
#include <iostream>
#include "CustomCtrl.h"
#include "CustomHeaderFilter.h"
#include <drogon/config.h>
#include <drogon/drogon.h>
#include <vector>
#include <string>
#include "CustomCtrl.h"
#include "CustomHeaderFilter.h"
#include <iostream>
using namespace drogon;
using namespace std::chrono_literals;
@ -125,7 +127,7 @@ int main()
std::cout << banner << std::endl;
// app().addListener("::1", 8848); //ipv6
app().addListener("0.0.0.0", 8848);
#ifdef USE_OPENSSL
#ifdef OpenSSL_FOUND
// https
drogon::app().setSSLFiles("server.pem", "server.pem");
drogon::app().addListener("0.0.0.0", 8849, true);
@ -206,7 +208,7 @@ int main()
drogon::AdviceCallback &&acb,
drogon::AdviceChainCallback &&accb) {
LOG_DEBUG << "postRouting1";
LOG_DEBUG << "Matched path=" << req->matchedPathPattern();
LOG_DEBUG << "Matched path=" << req->matchedPathPatternData();
for (auto &cookie : req->cookies())
{
LOG_DEBUG << "cookie: " << cookie.first << "=" << cookie.second;

View File

@ -26,7 +26,7 @@ int main()
{
LOG_ERROR << "The response was received in "
"the wrong order!";
exit(-1);
exit(1);
}
else
{
@ -36,12 +36,12 @@ int main()
if (resp->getBody().length() > 0)
{
LOG_ERROR << "The response has a body:" << resp->getBody();
exit(-1);
exit(1);
}
}
else
{
exit(-1);
exit(1);
}
});
@ -53,15 +53,15 @@ int main()
if (resp->getBody().length() != 44618)
{
LOG_ERROR << "The response is error!";
exit(-1);
exit(1);
}
}
else
{
exit(-1);
exit(1);
}
});
auto request = HttpRequest::newHttpRequest();
request->setPath("/pipe");
for (int i = 0; i < 19; i++)
@ -76,7 +76,7 @@ int main()
{
LOG_ERROR
<< "The response was received in the wrong order!";
exit(-1);
exit(1);
}
else
{
@ -91,12 +91,12 @@ int main()
if (resp->getBody().length() == 0)
{
LOG_ERROR << "The response hasn't a body!";
exit(-1);
exit(1);
}
}
else
{
exit(-1);
exit(1);
}
});
}

View File

@ -50,14 +50,14 @@ int main(int argc, char *argv[])
std::cout << "ws failed!" << std::endl;
if (!continually)
{
exit(-1);
exit(1);
}
}
});
app().getLoop()->runAfter(5.0, [continually]() {
if (!continually)
{
exit(-1);
exit(1);
}
});
app().run();

View File

@ -14,6 +14,7 @@
// Make a http client to test the example server app;
#include <drogon/config.h>
#include <drogon/drogon.h>
#include <trantor/net/EventLoopThread.h>
#include <trantor/net/TcpClient.h>
@ -1031,7 +1032,7 @@ int main(int argc, char *argv[])
client->addCookie(sessionID);
doTest(client, pro1);
#ifdef USE_OPENSSL
#ifdef OpenSSL_FOUND
std::promise<int> pro2;
auto sslClient = HttpClient::newHttpClient("127.0.0.1",
8849,

View File

@ -14,11 +14,8 @@
#pragma once
#include <drogon/config.h>
#if USE_ORM
#include <drogon/orm/DbClient.h>
#endif
#include <chrono>
#include <drogon/utils/HttpConstraint.h>
#include <drogon/CacheMap.h>
#include <drogon/DrObject.h>
#include <drogon/HttpBinder.h>
@ -34,13 +31,14 @@
#include <drogon/utils/ClassTraits.h>
#include <drogon/utils/Utilities.h>
#include <drogon/version.h>
#include <trantor/net/EventLoop.h>
#include <trantor/utils/NonCopyable.h>
#include <functional>
#include <memory>
#include <string>
#include <trantor/net/EventLoop.h>
#include <trantor/utils/NonCopyable.h>
#include <type_traits>
#include <vector>
#include <chrono>
namespace drogon
{
@ -299,7 +297,8 @@ class HttpAppFramework : public trantor::NonCopyable
virtual void registerHttpSimpleController(
const std::string &pathName,
const std::string &ctrlName,
const std::vector<any> &filtersAndMethods = std::vector<any>()) = 0;
const std::vector<internal::HttpConstraint> &filtersAndMethods =
std::vector<internal::HttpConstraint>{}) = 0;
/// Register a handler into the framework.
/**
@ -335,7 +334,8 @@ class HttpAppFramework : public trantor::NonCopyable
void registerHandler(
const std::string &pathPattern,
FUNCTION &&function,
const std::vector<any> &filtersAndMethods = std::vector<any>(),
const std::vector<internal::HttpConstraint> &filtersAndMethods =
std::vector<internal::HttpConstraint>{},
const std::string &handlerName = "")
{
LOG_TRACE << "pathPattern:" << pathPattern;
@ -348,22 +348,17 @@ class HttpAppFramework : public trantor::NonCopyable
std::vector<std::string> filters;
for (auto const &filterOrMethod : filtersAndMethods)
{
if (filterOrMethod.type() == typeid(std::string))
if (filterOrMethod.type() == internal::ConstraintType::HttpFilter)
{
filters.push_back(*any_cast<std::string>(&filterOrMethod));
filters.push_back(filterOrMethod.getFilterName());
}
else if (filterOrMethod.type() == typeid(const char *))
else if (filterOrMethod.type() ==
internal::ConstraintType::HttpMethod)
{
filters.push_back(*any_cast<const char *>(&filterOrMethod));
}
else if (filterOrMethod.type() == typeid(HttpMethod))
{
validMethods.push_back(*any_cast<HttpMethod>(&filterOrMethod));
validMethods.push_back(filterOrMethod.getHttpMethod());
}
else
{
std::cerr << "Invalid controller constraint type:"
<< filterOrMethod.type().name() << std::endl;
LOG_ERROR << "Invalid controller constraint type";
exit(1);
}
@ -790,7 +785,6 @@ class HttpAppFramework : public trantor::NonCopyable
*/
virtual void setHomePage(const std::string &homePageFile) = 0;
#if USE_ORM
/// Get a database client by @param name
/**
* NOTE:
@ -833,7 +827,6 @@ class HttpAppFramework : public trantor::NonCopyable
const std::string &filename = "",
const std::string &name = "default",
const bool isFast = false) = 0;
#endif
private:
virtual void registerHttpController(

View File

@ -15,6 +15,7 @@
#pragma once
#include <drogon/DrObject.h>
#include <drogon/utils/HttpConstraint.h>
#include <drogon/HttpAppFramework.h>
#include <iostream>
#include <string>
@ -54,7 +55,8 @@ class HttpController : public DrObject<T>, public HttpControllerBase
static void registerMethod(
FUNCTION &&function,
const std::string &pattern,
const std::vector<any> &filtersAndMethods = std::vector<any>(),
const std::vector<internal::HttpConstraint> &filtersAndMethods =
std::vector<internal::HttpConstraint>{},
bool classNameInPath = true,
const std::string &handlerName = "")
{

View File

@ -14,6 +14,7 @@
#pragma once
#include <drogon/utils/string_view.h>
#include <drogon/HttpTypes.h>
#include <drogon/Session.h>
#include <drogon/UploadFile.h>
@ -88,24 +89,26 @@ class HttpRequest
/// Get the query string of the request.
/**
* If the http method is GET, the query string is the substring after the
* '?' in the URL string. If the http method is POST, the query string is
* the content(body) string of the HTTP request.
* The query string is the substring after the '?' in the URL string.
*/
virtual string_view query() const = 0;
string_view getQuery() const
virtual const std::string &query() const = 0;
const std::string &getQuery() const
{
return query();
}
/// Get the content string of the request, which is the body part of the
/// request.
virtual string_view body() const = 0;
string_view body() const
{
return string_view(bodyData(), bodyLength());
}
string_view getBody() const
{
return body();
}
virtual const char *bodyData() const = 0;
virtual size_t bodyLength() const = 0;
/// Set the content string of the request.
virtual void setBody(const std::string &body) = 0;
virtual void setBody(std::string &&body) = 0;
@ -118,11 +121,17 @@ class HttpRequest
}
/// Get the matched path pattern after routing
virtual const string_view &matchedPathPattern() const = 0;
const string_view &getMatchedPathPattern() const
string_view getMatchedPathPattern() const
{
return matchedPathPattern();
}
string_view matchedPathPattern() const
{
return string_view(matchedPathPatternData(),
matchedPathPatternLength());
}
virtual const char *matchedPathPatternData() const = 0;
virtual size_t matchedPathPatternLength() const = 0;
/// Return the enum type version of the request.
/**

View File

@ -13,6 +13,7 @@
#pragma once
#include <drogon/utils/string_view.h>
#include <drogon/Cookie.h>
#include <drogon/HttpTypes.h>
#include <drogon/HttpViewData.h>
@ -69,9 +70,23 @@ class HttpResponse
/// Set the response content type and the content-type string, The string
/// must contain the header name and CRLF.
/// For example, "content-type: text/plain\r\n"
virtual void setContentTypeCodeAndCustomString(
ContentType type,
const string_view &typeString) = 0;
void setContentTypeCodeAndCustomString(ContentType type,
const string_view &typeString)
{
setContentTypeCodeAndCustomString(type,
typeString.data(),
typeString.length());
}
template <int N>
void setContentTypeCodeAndCustomString(ContentType type,
const char (&typeString)[N])
{
assert(N > 0);
setContentTypeCodeAndCustomString(type, typeString, N - 1);
}
virtual void setContentTypeCodeAndCustomString(ContentType type,
const char *typeString,
size_t typeStringLength) = 0;
/// Set the reponse content type and the character set.
/// virtual void setContentTypeCodeAndCharacterSet(ContentType type, const

View File

@ -15,6 +15,7 @@
#pragma once
#include <drogon/DrObject.h>
#include <drogon/utils/HttpConstraint.h>
#include <drogon/HttpAppFramework.h>
#include <iostream>
#include <string>
@ -52,8 +53,9 @@ class HttpSimpleController : public DrObject<T>, public HttpSimpleControllerBase
HttpSimpleController()
{
}
static void __registerSelf(const std::string &path,
const std::vector<any> &filtersAndMethods)
static void __registerSelf(
const std::string &path,
const std::vector<internal::HttpConstraint> &filtersAndMethods)
{
LOG_TRACE << "register simple controller("
<< HttpSimpleController<T>::classTypeName()

View File

@ -13,7 +13,6 @@
#pragma once
#include <atomic>
#include <drogon/config.h>
#include <thread>
namespace drogon

View File

@ -14,7 +14,8 @@
#pragma once
#include <drogon/config.h>
#include <drogon/utils/string_view.h>
#include <drogon/utils/any.h>
#include <trantor/utils/Logger.h>
#include <trantor/utils/MsgBuffer.h>
@ -135,8 +136,16 @@ class HttpViewData
* < --> &lt;
* > --> &gt;
*/
static std::string htmlTranslate(const std::string &str);
static std::string htmlTranslate(const string_view &str);
static std::string htmlTranslate(const char *str, size_t length);
static std::string htmlTranslate(const std::string &str)
{
return htmlTranslate(str.data(), str.length());
}
static std::string htmlTranslate(const string_view &str)
{
return htmlTranslate(str.data(), str.length());
}
static bool needTranslation(const std::string &str)
{
for (auto const &c : str)

View File

@ -110,7 +110,7 @@ class MultiPartParser
protected:
std::vector<HttpFile> _files;
std::map<std::string, std::string> _parameters;
int parse(const string_view &content, const std::string &boundary);
int parse(const HttpRequestPtr &req, const std::string &boundary);
int parseEntity(const char *begin, const char *end);
};

View File

@ -14,7 +14,7 @@
#pragma once
#include <drogon/config.h>
#include <drogon/utils/any.h>
#include <map>
#include <memory>
#include <mutex>

View File

@ -14,7 +14,6 @@
#pragma once
#include <drogon/config.h>
#include <memory>
#include <string>
#include <trantor/net/InetAddress.h>
@ -63,11 +62,33 @@ class WebSocketConnection
virtual void forceClose() = 0;
/// Set custom data on the connection
virtual void setContext(const any &context) = 0;
void setContext(const std::shared_ptr<void> &context)
{
_contextPtr = context;
}
void setContext(std::shared_ptr<void> &&context)
{
_contextPtr = std::move(context);
}
/// Get custom data from the connection
virtual const any &getContext() const = 0;
virtual any *getMutableContext() = 0;
template <typename T>
std::shared_ptr<T> getContext() const
{
return std::static_pointer_cast<T>(_contextPtr);
}
/// Return true if the context is set by user.
bool hasContext()
{
return (bool)_contextPtr;
}
/// Clear the context.
void clearContext()
{
_contextPtr.reset();
}
/// Set the heartbeat(ping) message sent to the peer.
/**
@ -78,6 +99,9 @@ class WebSocketConnection
virtual void setPingMessage(
const std::string &message,
const std::chrono::duration<long double> &interval) = 0;
private:
std::shared_ptr<void> _contextPtr;
};
typedef std::shared_ptr<WebSocketConnection> WebSocketConnectionPtr;
} // namespace drogon

View File

@ -0,0 +1,12 @@
#pragma once
#cmakedefine01 USE_POSTGRESQL
#cmakedefine01 USE_MYSQL
#cmakedefine01 USE_SQLITE3
#cmakedefine OpenSSL_FOUND
#cmakedefine COMPILATION_FLAGS "@COMPILATION_FLAGS@@DROGON_CXX_STANDARD@"
#cmakedefine COMPILER_COMMAND "@COMPILER_COMMAND@"
#cmakedefine COMPILER_ID "@COMPILER_ID@"
#cmakedefine INCLUDING_DIRS "@INCLUDING_DIRS@"

View File

@ -14,8 +14,6 @@
#pragma once
#include <drogon/config.h>
#include <trantor/net/EventLoop.h>
#include <trantor/net/InetAddress.h>
#include <trantor/utils/Date.h>

View File

@ -0,0 +1,64 @@
/**
*
* HttpConstraint.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/HttpTypes.h>
#include <string>
namespace drogon
{
namespace internal
{
enum class ConstraintType
{
None,
HttpMethod,
HttpFilter
};
class HttpConstraint
{
public:
HttpConstraint(HttpMethod method)
: _type(ConstraintType::HttpMethod), _method(method)
{
}
HttpConstraint(const std::string &filterName)
: _type(ConstraintType::HttpFilter), _filterName(filterName)
{
}
HttpConstraint(const char *filterName)
: _type(ConstraintType::HttpFilter), _filterName(filterName)
{
}
ConstraintType type() const
{
return _type;
}
HttpMethod getHttpMethod() const
{
return _method;
}
const std::string &getFilterName() const
{
return _filterName;
}
private:
ConstraintType _type = ConstraintType::None;
HttpMethod _method;
std::string _filterName;
};
} // namespace internal
} // namespace drogon

View File

@ -14,10 +14,10 @@
#pragma once
#include <drogon/config.h>
#include <trantor/utils/Date.h>
#include <drogon/utils/string_view.h>
#include <memory>
#include <string>
#include <trantor/utils/Date.h>
#include <vector>
namespace drogon
@ -58,9 +58,17 @@ std::string base64Encode(const unsigned char *bytes_to_encode,
std::string base64Decode(std::string const &encoded_string);
/// Decode from or encode to the URL format string
std::string urlDecode(const std::string &szToDecode);
std::string urlDecode(const string_view &szToDecode);
std::string urlDecode(const char *begin, const char *end);
inline std::string urlDecode(const std::string &szToDecode)
{
auto begin = szToDecode.data();
return urlDecode(begin, begin + szToDecode.length());
}
inline std::string urlDecode(const string_view &szToDecode)
{
auto begin = szToDecode.data();
return urlDecode(begin, begin + szToDecode.length());
}
std::string urlEncode(const std::string &str);
/// Commpress or decompress data using gzip lib.

View File

@ -0,0 +1,31 @@
/**
*
* any.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
#if __cplusplus >= 201703L
#include <any>
#else
#include <boost/any.hpp>
#endif
namespace drogon
{
#if __cplusplus >= 201703L
using std::any;
using std::any_cast;
#else
using boost::any;
using boost::any_cast;
#endif
} // namespace drogon

View File

@ -0,0 +1,28 @@
/**
*
* string_view.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
#if __cplusplus >= 201703L
#include <string_view>
#else
#include <boost/utility/string_view.hpp>
#endif
namespace drogon
{
#if __cplusplus >= 201703L
using std::string_view;
#else
using boost::string_view;
#endif
} // namespace drogon

View File

@ -14,7 +14,7 @@
#pragma once
#include <drogon/config.h>
#include <drogon/utils/string_view.h>
#include <trantor/utils/NonCopyable.h>
#include <string>
#include <stdio.h>

View File

@ -13,7 +13,7 @@
*/
#include "ConfigLoader.h"
#include <drogon/config.h>
#include <drogon/HttpAppFramework.h>
#include <fstream>
#include <iostream>
@ -160,7 +160,7 @@ static void loadControllers(const Json::Value &controllers)
auto ctrlName = controller.get("controller", "").asString();
if (path == "" || ctrlName == "")
continue;
std::vector<any> constraints;
std::vector<internal::HttpConstraint> constraints;
if (!controller["http_methods"].isNull())
{
for (auto const &method : controller["http_methods"])
@ -316,7 +316,7 @@ static void loadApp(const Json::Value &app)
else
{
std::cerr << "Error format of client_max_body_size" << std::endl;
exit(-1);
exit(1);
}
auto maxMemoryBodySize =
app.get("client_max_memory_body_size", "64K").asString();
@ -327,7 +327,7 @@ static void loadApp(const Json::Value &app)
else
{
std::cerr << "Error format of client_max_memory_body_size" << std::endl;
exit(-1);
exit(1);
}
auto maxWsMsgSize =
app.get("client_max_websocket_message_size", "128K").asString();
@ -339,7 +339,7 @@ static void loadApp(const Json::Value &app)
{
std::cerr << "Error format of client_max_websocket_message_size"
<< std::endl;
exit(-1);
exit(1);
}
drogon::app().setHomePage(app.get("home_page", "index.html").asString());
}
@ -347,7 +347,6 @@ static void loadDbClients(const Json::Value &dbClients)
{
if (!dbClients)
return;
#if USE_ORM
for (auto const &client : dbClients)
{
auto type = client.get("rdbms", "postgresql").asString();
@ -377,12 +376,6 @@ static void loadDbClients(const Json::Value &dbClients)
name,
isFast);
}
#else
std::cout << "No database is supported by drogon, please install the "
"database development library first."
<< std::endl;
exit(1);
#endif
}
static void loadListeners(const Json::Value &listeners)
{

View File

@ -0,0 +1,44 @@
/**
*
* DbClientManagerSkipped.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 "DbClientManager.h"
#include <drogon/config.h>
#include <drogon/utils/Utilities.h>
#include <algorithm>
#include <stdlib.h>
using namespace drogon::orm;
using namespace drogon;
void DbClientManager::createDbClients(
const std::vector<trantor::EventLoop *> &ioloops)
{
return;
}
void DbClientManager::createDbClient(const std::string &dbType,
const std::string &host,
const u_short port,
const std::string &databaseName,
const std::string &userName,
const std::string &password,
const size_t connectionNum,
const std::string &filename,
const std::string &name,
const bool isFast)
{
LOG_FATAL << "No database is supported by drogon, please install the "
"database development library first.";
abort();
}

View File

@ -16,6 +16,7 @@
#include "AOPAdvice.h"
#include "ConfigLoader.h"
#include "HttpServer.h"
#include <drogon/config.h>
#include <algorithm>
#include <drogon/CacheMap.h>
#include <drogon/DrClassMap.h>
@ -128,7 +129,7 @@ void HttpAppFrameworkImpl::registerWebSocketController(
void HttpAppFrameworkImpl::registerHttpSimpleController(
const std::string &pathName,
const std::string &ctrlName,
const std::vector<any> &filtersAndMethods)
const std::vector<internal::HttpConstraint> &filtersAndMethods)
{
assert(!_running);
_httpSimpleCtrlsRouter.registerHttpSimpleController(pathName,
@ -292,13 +293,11 @@ void HttpAppFrameworkImpl::run()
_sslCertPath,
_sslKeyPath,
_threadNum);
#if USE_ORM
// A fast database client instance should be created in the main event loop,
// so put the main loop into ioLoops.
ioLoops.push_back(getLoop());
_dbClientManager.createDbClients(ioLoops);
ioLoops.pop_back();
#endif
_httpCtrlsRouter.init(ioLoops);
_httpSimpleCtrlsRouter.init(ioLoops);
_staticFileRouter.init();
@ -366,11 +365,7 @@ void HttpAppFrameworkImpl::onConnection(const trantor::TcpConnectionPtr &conn)
}
else
{
#if CXX_STD >= 17
if (!conn->getContext().has_value())
#else
if (conn->getContext().empty())
#endif
if (!conn->hasContext())
{
// If the connection is connected to the SSL port and then
// disconnected before the SSL handshake.
@ -449,7 +444,6 @@ void HttpAppFrameworkImpl::onAsyncRequest(
callback(resp);
return;
}
// LOG_TRACE << "query: " << req->query() ;
std::string sessionId = req->getCookie("JSESSIONID");
bool needSetJsessionid = false;

View File

@ -14,6 +14,7 @@
#pragma once
#include "DbClientManager.h"
#include "HttpClientImpl.h"
#include "HttpControllersRouter.h"
#include "HttpRequestImpl.h"
@ -26,9 +27,7 @@
#include "WebsocketControllersRouter.h"
#include "StaticFileRouter.h"
#include "SessionManager.h"
#if USE_ORM
#include "../../orm_lib/src/DbClientManager.h"
#endif
#include <drogon/config.h>
#include <drogon/HttpAppFramework.h>
#include <drogon/HttpSimpleController.h>
#include <drogon/version.h>
@ -106,8 +105,8 @@ class HttpAppFrameworkImpl : public HttpAppFramework
virtual void registerHttpSimpleController(
const std::string &pathName,
const std::string &crtlName,
const std::vector<any> &filtersAndMethods =
std::vector<any>()) override;
const std::vector<internal::HttpConstraint> &filtersAndMethods =
std::vector<internal::HttpConstraint>{}) override;
virtual void setCustom404Page(const HttpResponsePtr &resp) override
{
@ -344,7 +343,6 @@ class HttpAppFrameworkImpl : public HttpAppFramework
return _serverHeader;
}
#if USE_ORM
virtual orm::DbClientPtr getDbClient(
const std::string &name = "default") override
{
@ -378,7 +376,6 @@ class HttpAppFrameworkImpl : public HttpAppFramework
name,
isFast);
}
#endif
inline static HttpAppFrameworkImpl &instance()
{
@ -461,9 +458,7 @@ class HttpAppFrameworkImpl : public HttpAppFramework
Json::Value _jsonConfig;
PluginsManager _pluginsManager;
HttpResponsePtr _custom404;
#if USE_ORM
orm::DbClientManager _dbClientManager;
#endif
static InitBeforeMainFunction _initFirst;
std::vector<std::function<bool(const trantor::InetAddress &,
const trantor::InetAddress &)>>

View File

@ -16,6 +16,7 @@
#include "HttpAppFrameworkImpl.h"
#include "HttpRequestImpl.h"
#include "HttpResponseParser.h"
#include <drogon/config.h>
#include <algorithm>
#include <stdlib.h>
@ -205,7 +206,7 @@ void HttpClientImpl::sendRequestInLoop(const drogon::HttpRequestPtr &req,
_server,
"httpClient");
#ifdef USE_OPENSSL
#ifdef OpenSSL_FOUND
if (_useSSL)
{
_tcpClient->enableSSL();
@ -227,7 +228,8 @@ void HttpClientImpl::sendRequestInLoop(const drogon::HttpRequestPtr &req,
return;
if (connPtr->connected())
{
connPtr->setContext(HttpResponseParser(connPtr));
connPtr->setContext(
std::make_shared<HttpResponseParser>());
// send request;
LOG_TRACE << "Connection established!";
while (thisPtr->_pipeliningCallbacks.size() <=
@ -316,8 +318,8 @@ void HttpClientImpl::sendReq(const trantor::TcpConnectionPtr &connPtr,
const HttpRequestPtr &req)
{
trantor::MsgBuffer buffer;
auto implPtr = std::dynamic_pointer_cast<HttpRequestImpl>(req);
assert(implPtr);
assert(req);
auto implPtr = static_cast<HttpRequestImpl *>(req.get());
implPtr->appendToBuffer(&buffer);
LOG_TRACE << "Send request:"
<< std::string(buffer.peek(), buffer.readableBytes());
@ -328,8 +330,7 @@ void HttpClientImpl::sendReq(const trantor::TcpConnectionPtr &connPtr,
void HttpClientImpl::onRecvMessage(const trantor::TcpConnectionPtr &connPtr,
trantor::MsgBuffer *msg)
{
HttpResponseParser *responseParser =
any_cast<HttpResponseParser>(connPtr->getMutableContext());
auto responseParser = connPtr->getContext<HttpResponseParser>();
// LOG_TRACE << "###:" << msg->readableBytes();
auto msgSize = msg->readableBytes();

View File

@ -389,7 +389,7 @@ void HttpControllersRouter::doControllerHandler(
{
// make a copy response;
auto newResp = std::make_shared<HttpResponseImpl>(
*std::dynamic_pointer_cast<HttpResponseImpl>(responsePtr));
*static_cast<HttpResponseImpl *>(responsePtr.get()));
newResp->setExpiredTime(-1); // make it temporary
newResp->addCookie("JSESSIONID", sessionId);
invokeCallback(callback, req, newResp);
@ -444,8 +444,7 @@ void HttpControllersRouter::doControllerHandler(
if (resp->expiredTime() >= 0)
{
// cache the response;
std::dynamic_pointer_cast<HttpResponseImpl>(resp)
->makeHeaderString();
static_cast<HttpResponseImpl *>(resp.get())->makeHeaderString();
auto loop = req->getLoop();
if (loop->isInLoopThread())
{
@ -464,7 +463,7 @@ void HttpControllersRouter::doControllerHandler(
{
// make a copy
newResp = std::make_shared<HttpResponseImpl>(
*std::dynamic_pointer_cast<HttpResponseImpl>(resp));
*static_cast<HttpResponseImpl *>(resp.get()));
newResp->setExpiredTime(-1); // make it temporary
}
newResp->addCookie("JSESSIONID", sessionId);

View File

@ -25,7 +25,7 @@ using namespace drogon;
void HttpRequestImpl::parseParameters() const
{
auto input = query();
auto input = queryView();
if (input.empty())
return;
std::string type = getHeaderBy("content-type");

View File

@ -123,7 +123,7 @@ class HttpRequestImpl : public HttpRequest
_query = query;
}
virtual string_view body() const override
string_view bodyView() const
{
if (_cacheFilePtr)
{
@ -131,6 +131,22 @@ class HttpRequestImpl : public HttpRequest
}
return _content;
}
virtual const char *bodyData() const override
{
if (_cacheFilePtr)
{
return _cacheFilePtr->getStringView().data();
}
return _content.data();
}
virtual size_t bodyLength() const override
{
if (_cacheFilePtr)
{
return _cacheFilePtr->getStringView().length();
}
return _content.length();
}
void appendToBody(const char *data, size_t length)
{
@ -146,9 +162,9 @@ class HttpRequestImpl : public HttpRequest
void reserveBodySize();
virtual string_view query() const override
string_view queryView() const
{
if (_query != "")
if (!_query.empty())
return _query;
if (_method == Post)
{
@ -159,6 +175,11 @@ class HttpRequestImpl : public HttpRequest
return _query;
}
virtual const std::string &query() const override
{
return _query;
}
virtual const trantor::InetAddress &peerAddr() const override
{
return _peer;
@ -323,9 +344,13 @@ class HttpRequestImpl : public HttpRequest
return _contentType;
}
virtual const string_view &matchedPathPattern() const override
virtual const char *matchedPathPatternData() const override
{
return _matchedPathPattern;
return _matchedPathPattern.data();
}
virtual size_t matchedPathPatternLength() const override
{
return _matchedPathPattern.length();
}
void setMatchedPathPattern(const std::string &pathPattern)

View File

@ -202,8 +202,7 @@ bool HttpRequestParser::parseRequest(MsgBuffer *buf)
{
resp->setStatusCode(k413RequestEntityTooLarge);
auto httpString =
std::dynamic_pointer_cast<HttpResponseImpl>(
resp)
static_cast<HttpResponseImpl *>(resp.get())
->renderToString();
reset();
connPtr->send(httpString);
@ -212,8 +211,7 @@ bool HttpRequestParser::parseRequest(MsgBuffer *buf)
{
resp->setStatusCode(k100Continue);
auto httpString =
std::dynamic_pointer_cast<HttpResponseImpl>(
resp)
static_cast<HttpResponseImpl *>(resp.get())
->renderToString();
connPtr->send(httpString);
}

View File

@ -16,15 +16,16 @@
#include "HttpRequestImpl.h"
#include "WebSocketConnectionImpl.h"
#include <deque>
#include <drogon/HttpResponse.h>
#include <mutex>
#include <trantor/utils/NonCopyable.h>
#include <trantor/net/TcpConnection.h>
#include <trantor/utils/MsgBuffer.h>
#include <mutex>
#include <deque>
namespace drogon
{
class HttpRequestParser
class HttpRequestParser : public trantor::NonCopyable
{
public:
enum HttpRequestParseState

View File

@ -100,10 +100,11 @@ class HttpResponseImpl : public HttpResponse
virtual void setContentTypeCodeAndCustomString(
ContentType type,
const string_view &typeString) override
const char *typeString,
size_t typeStringLength) override
{
_contentType = type;
setContentType(typeString);
setContentType(string_view{typeString, typeStringLength});
}
// virtual void setContentTypeCodeAndCharacterSet(ContentType type, const

View File

@ -18,7 +18,7 @@
#include <trantor/utils/MsgBuffer.h>
using namespace trantor;
using namespace drogon;
HttpResponseParser::HttpResponseParser(const trantor::TcpConnectionPtr &connPtr)
HttpResponseParser::HttpResponseParser()
: _state(HttpResponseParseState::kExpectResponseLine),
_response(new HttpResponseImpl)
{
@ -138,7 +138,7 @@ bool HttpResponseParser::parseResponse(MsgBuffer *buf)
}
}
}
if(_parseResponseForHeadMethod)
if (_parseResponseForHeadMethod)
{
_response->_leftBodyLength = 0;
_state = HttpResponseParseState::kGotAll;

View File

@ -16,14 +16,15 @@
#include "HttpResponseImpl.h"
#include <drogon/WebSocketConnection.h>
#include <list>
#include <mutex>
#include <trantor/utils/NonCopyable.h>
#include <trantor/net/TcpConnection.h>
#include <trantor/utils/MsgBuffer.h>
#include <list>
#include <mutex>
namespace drogon
{
class HttpResponseParser
class HttpResponseParser : public trantor::NonCopyable
{
public:
enum class HttpResponseParseState
@ -38,7 +39,7 @@ class HttpResponseParser
kGotAll,
};
explicit HttpResponseParser(const trantor::TcpConnectionPtr &connPtr);
HttpResponseParser();
// default copy-ctor, dtor and assignment are fine

View File

@ -15,7 +15,6 @@
#include "HttpServer.h"
#include "HttpAppFrameworkImpl.h"
#include "HttpRequestParser.h"
#include "HttpResponseImpl.h"
#include <drogon/HttpRequest.h>
#include <drogon/HttpResponse.h>
@ -100,34 +99,32 @@ void HttpServer::onConnection(const TcpConnectionPtr &conn)
{
if (conn->connected())
{
conn->setContext(HttpRequestParser(conn));
conn->setContext(std::make_shared<HttpRequestParser>(conn));
_connectionCallback(conn);
}
else if (conn->disconnected())
{
LOG_TRACE << "conn disconnected!";
_connectionCallback(conn);
HttpRequestParser *requestParser =
any_cast<HttpRequestParser>(conn->getMutableContext());
auto requestParser = conn->getContext<HttpRequestParser>();
if (requestParser)
{
if (requestParser->webSocketConn())
{
requestParser->webSocketConn()->onClose();
}
#if (CXX_STD > 14)
conn->getMutableContext()->reset(); // reset(): since c++17
#else
conn->getMutableContext()->clear();
#endif
conn->clearContext();
}
}
}
void HttpServer::onMessage(const TcpConnectionPtr &conn, MsgBuffer *buf)
{
HttpRequestParser *requestParser =
any_cast<HttpRequestParser>(conn->getMutableContext());
if (!conn->hasContext())
return;
auto requestParser = conn->getContext<HttpRequestParser>();
if (!requestParser)
return;
// With the pipelining feature or web socket, it is possible to receice
// multiple messages at once, so
// the while loop is necessary
@ -165,16 +162,20 @@ void HttpServer::onMessage(const TcpConnectionPtr &conn, MsgBuffer *buf)
std::make_shared<WebSocketConnectionImpl>(conn);
_newWebsocketCallback(
requestParser->requestImpl(),
[=](const HttpResponsePtr &resp) mutable {
if (resp->statusCode() == k101SwitchingProtocols)
[conn, wsConn, requestParser](
const HttpResponsePtr &resp) mutable {
if (conn->connected())
{
requestParser->setWebsockConnection(wsConn);
if (resp->statusCode() ==
k101SwitchingProtocols)
{
requestParser->setWebsockConnection(wsConn);
}
auto httpString =
((HttpResponseImpl *)resp.get())
->renderToString();
conn->send(httpString);
}
auto httpString =
std::dynamic_pointer_cast<HttpResponseImpl>(
resp)
->renderToString();
conn->send(httpString);
},
wsConn);
}
@ -187,23 +188,20 @@ void HttpServer::onMessage(const TcpConnectionPtr &conn, MsgBuffer *buf)
break;
}
}
onRequests(conn, requests);
onRequests(conn, requests, requestParser);
}
}
void HttpServer::onRequests(const TcpConnectionPtr &conn,
const std::vector<HttpRequestImplPtr> &requests)
void HttpServer::onRequests(
const TcpConnectionPtr &conn,
const std::vector<HttpRequestImplPtr> &requests,
const std::shared_ptr<HttpRequestParser> &requestParser)
{
if (requests.empty())
return;
auto responsePtrs =
std::make_shared<std::vector<std::pair<HttpResponsePtr, bool>>>();
auto loopFlagPtr = std::make_shared<bool>(true);
HttpRequestParser *requestParser =
any_cast<HttpRequestParser>(conn->getMutableContext());
if (!requestParser)
return;
for (auto &req : requests)
{
if (!conn->connected())
@ -239,122 +237,83 @@ void HttpServer::onRequests(const TcpConnectionPtr &conn,
requestParser->stop();
}
_httpAsyncCallback(req, [=](const HttpResponsePtr &response) {
if (!response)
return;
response->setCloseConnection(_close);
auto newResp = response;
auto &sendfileName =
std::dynamic_pointer_cast<HttpResponseImpl>(newResp)
->sendfileName();
if (app().isGzipEnabled() && sendfileName.empty() &&
req->getHeaderBy("accept-encoding").find("gzip") !=
std::string::npos &&
std::dynamic_pointer_cast<HttpResponseImpl>(response)
->getHeaderBy("content-encoding")
.empty() &&
response->getContentType() < CT_APPLICATION_OCTET_STREAM &&
response->getBody().length() > 1024)
{
// use gzip
LOG_TRACE << "Use gzip to compress the body";
size_t zlen = response->getBody().length();
auto strCompress =
utils::gzipCompress(response->getBody().data(),
response->getBody().length());
if (strCompress)
{
if (zlen > 0)
{
LOG_TRACE << "length after compressing:" << zlen;
if (response->expiredTime() >= 0)
{
// cached response,we need to make a clone
newResp = std::make_shared<HttpResponseImpl>(
*std::dynamic_pointer_cast<HttpResponseImpl>(
response));
newResp->setExpiredTime(-1);
}
newResp->setBody(std::move(*strCompress));
newResp->addHeader("Content-Encoding", "gzip");
}
else
{
LOG_ERROR << "gzip got 0 length result";
}
}
}
if (conn->getLoop()->isInLoopThread())
{
/*
* A client that supports persistent connections MAY
* pipeline its requests (i.e., send multiple requests
* without waiting for each response). A server MUST send
* its responses to those requests in the same order that
* the requests were received. rfc2616-8.1.1.2
*/
_httpAsyncCallback(
req,
[conn,
_close,
req,
loopFlagPtr,
responsePtrs,
isHeadMethod,
this,
requestParser](const HttpResponsePtr &response) {
if (!response)
return;
if (!conn->connected())
return;
if (requestParser->getFirstRequest() == req)
response->setCloseConnection(_close);
auto newResp = response;
auto &sendfileName =
static_cast<HttpResponseImpl *>(newResp.get())
->sendfileName();
if (app().isGzipEnabled() && sendfileName.empty() &&
req->getHeaderBy("accept-encoding").find("gzip") !=
std::string::npos &&
static_cast<HttpResponseImpl *>(response.get())
->getHeaderBy("content-encoding")
.empty() &&
response->getContentType() < CT_APPLICATION_OCTET_STREAM &&
response->getBody().length() > 1024)
{
requestParser->popFirstRequest();
if (*loopFlagPtr)
// use gzip
LOG_TRACE << "Use gzip to compress the body";
size_t zlen = response->getBody().length();
auto strCompress =
utils::gzipCompress(response->getBody().data(),
response->getBody().length());
if (strCompress)
{
(*responsePtrs).emplace_back(newResp, isHeadMethod);
}
else
{
std::vector<std::pair<HttpResponsePtr, bool>> resps;
resps.emplace_back(newResp, isHeadMethod);
while (requestParser->numberOfRequestsInPipelining() >
0)
if (zlen > 0)
{
auto resp = requestParser->getFirstResponse();
if (resp.first)
LOG_TRACE << "length after compressing:" << zlen;
if (response->expiredTime() >= 0)
{
requestParser->popFirstRequest();
resps.push_back(std::move(resp));
// cached response,we need to make a clone
newResp = std::make_shared<HttpResponseImpl>(
*static_cast<HttpResponseImpl *>(
response.get()));
newResp->setExpiredTime(-1);
}
else
break;
newResp->setBody(std::move(*strCompress));
newResp->addHeader("Content-Encoding", "gzip");
}
else
{
LOG_ERROR << "gzip got 0 length result";
}
sendResponses(conn, resps);
}
if (requestParser->isStop() &&
requestParser->numberOfRequestsInPipelining() == 0)
}
if (conn->getLoop()->isInLoopThread())
{
/*
* A client that supports persistent connections MAY
* pipeline its requests (i.e., send multiple requests
* without waiting for each response). A server MUST send
* its responses to those requests in the same order that
* the requests were received. rfc2616-8.1.1.2
*/
if (!conn->connected())
return;
if (requestParser->getFirstRequest() == req)
{
requestParser->popFirstRequest();
if (*loopFlagPtr)
{
sendResponses(conn, *responsePtrs);
responsePtrs->clear();
(*responsePtrs).emplace_back(newResp, isHeadMethod);
}
conn->shutdown();
}
}
else
{
// some earlier requests are waiting for responses;
requestParser->pushResponseToPipelining(req,
newResp,
isHeadMethod);
}
}
else
{
conn->getLoop()->queueInLoop([conn,
req,
newResp,
this,
isHeadMethod]() {
HttpRequestParser *requestParser =
any_cast<HttpRequestParser>(conn->getMutableContext());
if (requestParser)
{
if (requestParser->getFirstRequest() == req)
else
{
requestParser->popFirstRequest();
std::vector<std::pair<HttpResponsePtr, bool>> resps;
resps.emplace_back(newResp, isHeadMethod);
while (
@ -371,24 +330,75 @@ void HttpServer::onRequests(const TcpConnectionPtr &conn,
break;
}
sendResponses(conn, resps);
if (requestParser->isStop() &&
requestParser->numberOfRequestsInPipelining() ==
0)
{
conn->shutdown();
}
}
else
if (requestParser->isStop() &&
requestParser->numberOfRequestsInPipelining() == 0)
{
// some earlier requests are waiting for
// responses;
requestParser->pushResponseToPipelining(
req, newResp, isHeadMethod);
if (*loopFlagPtr)
{
sendResponses(conn, *responsePtrs);
responsePtrs->clear();
}
conn->shutdown();
}
}
});
}
});
else
{
// some earlier requests are waiting for responses;
requestParser->pushResponseToPipelining(req,
newResp,
isHeadMethod);
}
}
else
{
conn->getLoop()->queueInLoop([conn,
req,
newResp,
this,
isHeadMethod,
requestParser]() {
if (conn->connected())
{
if (requestParser->getFirstRequest() == req)
{
requestParser->popFirstRequest();
std::vector<std::pair<HttpResponsePtr, bool>>
resps;
resps.emplace_back(newResp, isHeadMethod);
while (requestParser
->numberOfRequestsInPipelining() > 0)
{
auto resp =
requestParser->getFirstResponse();
if (resp.first)
{
requestParser->popFirstRequest();
resps.push_back(std::move(resp));
}
else
break;
}
sendResponses(conn, resps);
if (requestParser->isStop() &&
requestParser
->numberOfRequestsInPipelining() ==
0)
{
conn->shutdown();
}
}
else
{
// some earlier requests are waiting for
// responses;
requestParser->pushResponseToPipelining(
req, newResp, isHeadMethod);
}
}
});
}
});
}
*loopFlagPtr = false;
if (conn->connected() && !responsePtrs->empty())
@ -400,7 +410,7 @@ void HttpServer::sendResponse(const TcpConnectionPtr &conn,
bool isHeadMethod)
{
conn->getLoop()->assertInLoopThread();
auto respImplPtr = std::dynamic_pointer_cast<HttpResponseImpl>(response);
auto respImplPtr = static_cast<HttpResponseImpl *>(response.get());
if (!isHeadMethod)
{
auto httpString = respImplPtr->renderToString();
@ -438,8 +448,7 @@ void HttpServer::sendResponses(
trantor::MsgBuffer buffer(256 * responses.size());
for (auto const &resp : responses)
{
auto respImplPtr =
std::dynamic_pointer_cast<HttpResponseImpl>(resp.first);
auto respImplPtr = static_cast<HttpResponseImpl *>(resp.first.get());
if (!resp.second)
{
// Not HEAD method

View File

@ -16,8 +16,8 @@
#include "HttpRequestImpl.h"
#include "WebSocketConnectionImpl.h"
#include "HttpRequestParser.h"
#include <drogon/WebSocketController.h>
#include <drogon/config.h>
#include <trantor/net/TcpServer.h>
#include <trantor/net/callbacks.h>
#include <trantor/utils/NonCopyable.h>
@ -87,18 +87,17 @@ class HttpServer : trantor::NonCopyable
}
void start();
#ifdef USE_OPENSSL
void enableSSL(const std::string &certPath, const std::string &keyPath)
{
_server.enableSSL(certPath, keyPath);
}
#endif
private:
void onConnection(const trantor::TcpConnectionPtr &conn);
void onMessage(const trantor::TcpConnectionPtr &, trantor::MsgBuffer *);
void onRequests(const trantor::TcpConnectionPtr &,
const std::vector<HttpRequestImplPtr> &);
const std::vector<HttpRequestImplPtr> &,
const std::shared_ptr<HttpRequestParser> &);
void sendResponse(const trantor::TcpConnectionPtr &,
const HttpResponsePtr &,
bool isHeadMethod);

View File

@ -16,13 +16,14 @@
#include "AOPAdvice.h"
#include "FiltersFunction.h"
#include "HttpAppFrameworkImpl.h"
#include <drogon/utils/HttpConstraint.h>
using namespace drogon;
void HttpSimpleControllersRouter::registerHttpSimpleController(
const std::string &pathName,
const std::string &ctrlName,
const std::vector<any> &filtersAndMethods)
const std::vector<internal::HttpConstraint> &filtersAndMethods)
{
assert(!pathName.empty());
assert(!ctrlName.empty());
@ -34,22 +35,16 @@ void HttpSimpleControllersRouter::registerHttpSimpleController(
std::vector<std::string> filters;
for (auto const &filterOrMethod : filtersAndMethods)
{
if (filterOrMethod.type() == typeid(std::string))
if (filterOrMethod.type() == internal::ConstraintType::HttpFilter)
{
filters.push_back(*any_cast<std::string>(&filterOrMethod));
filters.push_back(filterOrMethod.getFilterName());
}
else if (filterOrMethod.type() == typeid(const char *))
else if (filterOrMethod.type() == internal::ConstraintType::HttpMethod)
{
filters.push_back(*any_cast<const char *>(&filterOrMethod));
}
else if (filterOrMethod.type() == typeid(HttpMethod))
{
validMethods.push_back(*any_cast<HttpMethod>(&filterOrMethod));
validMethods.push_back(filterOrMethod.getHttpMethod());
}
else
{
std::cerr << "Invalid controller constraint type:"
<< filterOrMethod.type().name() << std::endl;
LOG_ERROR << "Invalid controller constraint type";
exit(1);
}
@ -242,7 +237,7 @@ void HttpSimpleControllersRouter::doControllerHandler(
{
// make a copy response;
auto newResp = std::make_shared<HttpResponseImpl>(
*std::dynamic_pointer_cast<HttpResponseImpl>(responsePtr));
*static_cast<HttpResponseImpl *>(responsePtr.get()));
newResp->setExpiredTime(-1); // make it temporary
newResp->addCookie("JSESSIONID", sessionId);
invokeCallback(callback, req, newResp);
@ -262,7 +257,7 @@ void HttpSimpleControllersRouter::doControllerHandler(
if (resp->expiredTime() >= 0)
{
// cache the response;
std::dynamic_pointer_cast<HttpResponseImpl>(resp)
static_cast<HttpResponseImpl *>(resp.get())
->makeHeaderString();
auto loop = req->getLoop();
if (loop->isInLoopThread())
@ -282,8 +277,7 @@ void HttpSimpleControllersRouter::doControllerHandler(
{
// make a copy
newResp = std::make_shared<HttpResponseImpl>(
*std::dynamic_pointer_cast<HttpResponseImpl>(
resp));
*static_cast<HttpResponseImpl *>(resp.get()));
newResp->setExpiredTime(-1); // make it temporary
}
newResp->addCookie("JSESSIONID", sessionId);

View File

@ -16,6 +16,7 @@
#include "HttpControllersRouter.h"
#include "HttpRequestImpl.h"
#include "HttpResponseImpl.h"
#include <drogon/utils/HttpConstraint.h>
#include <atomic>
#include <drogon/HttpBinder.h>
#include <drogon/HttpFilter.h>
@ -62,7 +63,7 @@ class HttpSimpleControllersRouter : public trantor::NonCopyable
void registerHttpSimpleController(
const std::string &pathName,
const std::string &ctrlName,
const std::vector<any> &filtersAndMethods);
const std::vector<internal::HttpConstraint> &filtersAndMethods);
void route(const HttpRequestImplPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback,
bool needSetJsessionid,

View File

@ -13,9 +13,10 @@
*/
#pragma once
#include <drogon/utils/string_view.h>
#include <drogon/HttpTypes.h>
#include <drogon/WebSocketConnection.h>
#include <drogon/config.h>
#include <string>
#include <trantor/utils/MsgBuffer.h>

View File

@ -16,18 +16,14 @@
using namespace drogon;
std::string HttpViewData::htmlTranslate(const std::string &str)
{
return htmlTranslate(string_view(str));
}
std::string HttpViewData::htmlTranslate(const string_view &str)
std::string HttpViewData::htmlTranslate(const char *str, size_t length)
{
std::string ret;
ret.reserve(str.length() + 64);
for (auto &ch : str)
ret.reserve(length + 64);
auto end = str + length;
while (str != end)
{
switch (ch)
switch (*str)
{
case '"':
ret.append("&quot;", 6);
@ -42,9 +38,10 @@ std::string HttpViewData::htmlTranslate(const string_view &str)
ret.append("&gt;", 4);
break;
default:
ret.push_back(ch);
ret.push_back(*str);
break;
}
++str;
}
return ret;
}

View File

@ -13,9 +13,8 @@
*/
#include "ListenerManager.h"
#include <trantor/utils/config.h>
#include <drogon/config.h>
#include <trantor/utils/Logger.h>
#include <fcntl.h>
#include <sys/file.h>
#include <sys/stat.h>
@ -53,7 +52,7 @@ void ListenerManager::addListener(const std::string &ip,
const std::string &certFile,
const std::string &keyFile)
{
#ifndef USE_OPENSSL
#ifndef OpenSSL_FOUND
if (useSSL)
{
LOG_ERROR << "Can't use SSL without OpenSSL found in your system";
@ -108,7 +107,7 @@ std::vector<trantor::EventLoop *> ListenerManager::createListeners(
if (listener._useSSL)
{
#ifdef USE_OPENSSL
#ifdef OpenSSL_FOUND
auto cert = listener._certFile;
auto key = listener._keyFile;
if (cert == "")
@ -149,7 +148,7 @@ std::vector<trantor::EventLoop *> ListenerManager::createListeners(
"drogon");
if (listener._useSSL)
{
#ifdef USE_OPENSSL
#ifdef OpenSSL_FOUND
auto cert = listener._certFile;
auto key = listener._keyFile;
if (cert == "")

View File

@ -17,7 +17,8 @@
#include <drogon/HttpAppFramework.h>
#include <drogon/MultiPart.h>
#include <drogon/utils/Utilities.h>
#ifdef USE_OPENSSL
#include <drogon/config.h>
#ifdef OpenSSL_FOUND
#include <openssl/md5.h>
#else
#include "ssl_funcs/Md5.h"
@ -46,7 +47,7 @@ int MultiPartParser::parse(const HttpRequestPtr &req)
if (req->method() != Post)
return -1;
const std::string &contentType =
std::dynamic_pointer_cast<HttpRequestImpl>(req)->getHeaderBy(
static_cast<HttpRequestImpl *>(req.get())->getHeaderBy(
"content-type");
if (contentType.empty())
{
@ -64,7 +65,8 @@ int MultiPartParser::parse(const HttpRequestPtr &req)
if (pos == std::string::npos)
return -1;
std::string boundary = contentType.substr(pos + 9);
return parse(req->query(), boundary);
return parse(req, boundary);
}
int MultiPartParser::parseEntity(const char *begin, const char *end)
@ -108,11 +110,12 @@ int MultiPartParser::parseEntity(const char *begin, const char *end)
}
}
int MultiPartParser::parse(const string_view &content,
int MultiPartParser::parse(const HttpRequestPtr &req,
const std::string &boundary)
{
string_view::size_type pos1, pos2;
pos1 = 0;
auto content = static_cast<HttpRequestImpl *>(req.get())->bodyView();
pos2 = content.find(boundary);
while (1)
{
@ -222,7 +225,7 @@ int HttpFile::saveTo(const std::string &pathAndFilename) const
}
const std::string HttpFile::getMd5() const
{
#ifdef USE_OPENSSL
#ifdef OpenSSL_FOUND
MD5_CTX c;
unsigned char md5[16] = {0};
MD5_Init(&c);

View File

@ -13,9 +13,9 @@
*/
#include "SharedLibManager.h"
#include <drogon/config.h>
#include <dirent.h>
#include <dlfcn.h>
#include <drogon/config.h>
#include <fstream>
#include <sys/stat.h>
#include <sys/types.h>
@ -154,7 +154,7 @@ void SharedLibManager::managerLibs()
void *SharedLibManager::loadLibs(const std::string &sourceFile, void *oldHld)
{
LOG_TRACE << "src:" << sourceFile;
std::string cmd = compilerCommand;
std::string cmd = COMPILER_COMMAND;
auto pos = cmd.rfind("/");
if (pos != std::string::npos)
{
@ -163,10 +163,10 @@ void *SharedLibManager::loadLibs(const std::string &sourceFile, void *oldHld)
cmd.append(" ")
.append(sourceFile)
.append(" ")
.append(compileFlags)
.append(COMPILATION_FLAGS)
.append(" ")
.append(includeDirs);
if (std::string(compilerId).find("Clang") != std::string::npos)
.append(INCLUDING_DIRS);
if (std::string(COMPILER_ID).find("Clang") != std::string::npos)
cmd.append(" -shared -fPIC -undefined dynamic_lookup -o ");
else
cmd.append(" -shared -fPIC --no-gnu-unique -o ");

View File

@ -69,7 +69,7 @@ void StaticFileRouter::route(
{
if (cachedResp)
{
if (std::dynamic_pointer_cast<HttpResponseImpl>(cachedResp)
if (static_cast<HttpResponseImpl *>(cachedResp.get())
->getHeaderBy("last-modified") ==
req->getHeaderBy("if-modified-since"))
{
@ -124,8 +124,8 @@ void StaticFileRouter::route(
{
// make a copy
auto newCachedResp = std::make_shared<HttpResponseImpl>(
*std::dynamic_pointer_cast<HttpResponseImpl>(
cachedResp));
*static_cast<HttpResponseImpl *>(
cachedResp.get()));
newCachedResp->addCookie("JSESSIONID", sessionId);
newCachedResp->setExpiredTime(-1);
callback(newCachedResp);
@ -182,7 +182,7 @@ void StaticFileRouter::route(
{
// make a copy
newCachedResp = std::make_shared<HttpResponseImpl>(
*std::dynamic_pointer_cast<HttpResponseImpl>(resp));
*static_cast<HttpResponseImpl *>(resp.get()));
newCachedResp->setExpiredTime(-1);
}
newCachedResp->addCookie("JSESSIONID", sessionId);

View File

@ -14,7 +14,6 @@
#include <cctype>
#include <cstdlib>
#include <drogon/config.h>
#include <drogon/utils/Utilities.h>
#include <fcntl.h>
#include <iomanip>
@ -456,18 +455,6 @@ std::string urlEncode(const std::string &src)
return result;
}
std::string urlDecode(const std::string &szToDecode)
{
return urlDecode(szToDecode.c_str(),
szToDecode.c_str() + szToDecode.length());
}
std::string urlDecode(const string_view &szToDecode)
{
return urlDecode(szToDecode.data(),
szToDecode.data() + szToDecode.length());
}
std::string urlDecode(const char *begin, const char *end)
{
std::string result;

View File

@ -18,8 +18,9 @@
#include "HttpUtils.h"
#include <drogon/HttpAppFramework.h>
#include <drogon/utils/Utilities.h>
#include <drogon/config.h>
#include <trantor/net/InetAddress.h>
#ifdef USE_OPENSSL
#ifdef OpenSSL_FOUND
#include <openssl/sha.h>
#else
#include "ssl_funcs/Sha1.h"
@ -89,13 +90,10 @@ void WebSocketClientImpl::connectToServerInLoop()
LOG_TRACE << "New TcpClient," << _server.toIpPort();
_tcpClient =
std::make_shared<trantor::TcpClient>(_loop, _server, "httpClient");
#ifdef USE_OPENSSL
if (_useSSL)
{
_tcpClient->enableSSL();
}
#endif
auto thisPtr = shared_from_this();
std::weak_ptr<WebSocketClientImpl> weakPtr = thisPtr;
@ -106,7 +104,7 @@ void WebSocketClientImpl::connectToServerInLoop()
return;
if (connPtr->connected())
{
connPtr->setContext(HttpResponseParser(connPtr));
connPtr->setContext(std::make_shared<HttpResponseParser>());
// send request;
LOG_TRACE << "Connection established!";
thisPtr->sendReq(connPtr);
@ -169,8 +167,7 @@ void WebSocketClientImpl::onRecvMessage(
onRecvWsMessage(connPtr, msgBuffer);
return;
}
HttpResponseParser *responseParser =
any_cast<HttpResponseParser>(connPtr->getMutableContext());
auto responseParser = connPtr->getContext<HttpResponseParser>();
// LOG_TRACE << "###:" << msg->readableBytes();
@ -311,8 +308,8 @@ WebSocketClientImpl::WebSocketClientImpl(trantor::EventLoop *loop,
void WebSocketClientImpl::sendReq(const trantor::TcpConnectionPtr &connPtr)
{
trantor::MsgBuffer buffer;
auto implPtr = std::dynamic_pointer_cast<HttpRequestImpl>(_upgradeRequest);
assert(implPtr);
assert(_upgradeRequest);
auto implPtr = static_cast<HttpRequestImpl *>(_upgradeRequest.get());
implPtr->appendToBuffer(&buffer);
LOG_TRACE << "Send request:"
<< std::string(buffer.peek(), buffer.readableBytes());

View File

@ -156,19 +156,6 @@ void WebSocketConnectionImpl::WebSocketConnectionImpl::forceClose()
_tcpConn->forceClose();
}
void WebSocketConnectionImpl::setContext(const any &context)
{
_context = context;
}
const any &WebSocketConnectionImpl::WebSocketConnectionImpl::getContext() const
{
return _context;
}
any *WebSocketConnectionImpl::WebSocketConnectionImpl::getMutableContext()
{
return &_context;
}
void WebSocketConnectionImpl::setPingMessage(
const std::string &message,
const std::chrono::duration<long double> &interval)

View File

@ -69,10 +69,6 @@ class WebSocketConnectionImpl
virtual void shutdown() override; // close write
virtual void forceClose() override; // close
virtual void setContext(const any &context) override;
virtual const any &getContext() const override;
virtual any *getMutableContext() override;
virtual void setPingMessage(
const std::string &message,
const std::chrono::duration<long double> &interval) override;
@ -105,7 +101,6 @@ class WebSocketConnectionImpl
trantor::TcpConnectionPtr _tcpConn;
trantor::InetAddress _localAddr;
trantor::InetAddress _peerAddr;
any _context;
bool _isServer = true;
WebSocketMessageParser _parser;
trantor::TimerId _pingTimerId = trantor::InvalidTimerId;

View File

@ -15,7 +15,8 @@
#include "WebsocketControllersRouter.h"
#include "FiltersFunction.h"
#include "HttpAppFrameworkImpl.h"
#ifdef USE_OPENSSL
#include <drogon/config.h>
#ifdef OpenSSL_FOUND
#include <openssl/sha.h>
#else
#include "ssl_funcs/Sha1.h"

View File

@ -1,13 +1,29 @@
link_libraries(drogon trantor pthread dl)
LINK_LIBRARIES(drogon trantor pthread dl)
add_executable(cache_map_test CacheMapTest.cc)
add_executable(cache_map_test2 CacheMapTest2.cc)
add_executable(cookies_test CookiesTest.cc)
add_executable(class_name_test ClassNameTest.cc)
add_executable(sha1_test Sha1Test.cc)
add_executable(view_data_test HttpViewDataTest.cc)
add_executable(md5_test Md5Test.cc ../src/ssl_funcs/Md5.cc)
add_executable(http_full_date_test HttpFullDateTest.cc)
add_executable(gzip_test GzipTest.cc)
add_executable(url_codec_test UrlCodecTest.cc)
add_executable(main_loop_test MainLoopTest.cc)
ADD_EXECUTABLE(cache_map_test CacheMapTest.cc)
ADD_EXECUTABLE(cache_map_test2 CacheMapTest2.cc)
ADD_EXECUTABLE(cookies_test CookiesTest.cc)
ADD_EXECUTABLE(class_name_test ClassNameTest.cc)
ADD_EXECUTABLE(sha1_test Sha1Test.cc)
ADD_EXECUTABLE(view_data_test HttpViewDataTest.cc)
ADD_EXECUTABLE(md5_test Md5Test.cc ../src/ssl_funcs/Md5.cc)
ADD_EXECUTABLE(http_full_date_test HttpFullDateTest.cc)
ADD_EXECUTABLE(gzip_test GzipTest.cc)
ADD_EXECUTABLE(url_codec_test UrlCodecTest.cc)
ADD_EXECUTABLE(main_loop_test MainLoopTest.cc)
SET(test_targets cache_map_test
cache_map_test2
cookies_test
class_name_test
sha1_test
view_data_test
md5_test
http_full_date_test
gzip_test
url_codec_test
main_loop_test)
SET_PROPERTY(TARGET ${test_targets} PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD})
SET_PROPERTY(TARGET ${test_targets} PROPERTY CXX_STANDARD_REQUIRED ON)
SET_PROPERTY(TARGET ${test_targets} PROPERTY CXX_EXTENSIONS OFF)

View File

@ -1,5 +1,5 @@
#include <drogon/config.h>
#ifdef USE_OPENSSL
#ifdef OpenSSL_FOUND
#include <openssl/sha.h>
#else
#include "../lib/src/ssl_funcs/Sha1.h"

View File

@ -1,3 +1,4 @@
#include <drogon/utils/string_view.h>
#include <drogon/utils/Utilities.h>
#include <iostream>
@ -9,7 +10,8 @@ int main()
auto output2 = drogon::utils::urlDecode(output);
std::cout << output2 << std::endl;
std::cout << drogon::utils::urlEncode("k2=安&k1=1") << std::endl;
std::cout << drogon::utils::urlDecode(string_view("k2%3D%E5%AE%89&k1%3D1"))
std::cout << drogon::utils::urlDecode(
drogon::string_view("k2%3D%E5%AE%89&k1%3D1"))
<< std::endl;
return 0;
}

View File

@ -14,7 +14,6 @@
#pragma once
#include <drogon/config.h>
#include <drogon/orm/SqlBinder.h>
#include <assert.h>

View File

@ -13,7 +13,6 @@
*/
#pragma once
#include <drogon/config.h>
#include <drogon/orm/Exception.h>
#include <drogon/orm/Field.h>
#include <drogon/orm/Result.h>
@ -42,45 +41,38 @@ class DbClient : public trantor::NonCopyable
{
public:
virtual ~DbClient(){};
/// Create a new database client with multiple connections;
/**
* @param connInfo: Connection string with some parameters,
* each parameter setting is in the form keyword = value. Spaces around the
* equal sign are optional.
* To write an empty value, or a value containing spaces, surround it with
* single quotes, e.g.,
* keyword = 'a value'. Single quotes and backslashes within the value must be
* escaped with a backslash, i.e., \' and \\.
* Example:
* host=localhost port=5432 dbname=mydb connect_timeout=10 password=''
* The currently recognized parameter key words are:
* - host: can be either a host name or an IP address.
* - port: Port number to connect to at the server host.
* - dbname: The database name. Defaults to be the same as the user name.
* - user: user name to connect as. With PostgreSQL defaults to be the same as
* the operating system name of the user running the application.
* - password: Password to be used if the server demands password
* authentication.
*
* For other key words on PostgreSQL, see the PostgreSQL documentation.
* Only a pair of key values is valid for Sqlite3, and its keyword is
* 'filename'.
*
* @param connNum: The number of connections to database server;
*/
#if USE_POSTGRESQL
/// Create a new database client with multiple connections;
/**
* @param connInfo: Connection string with some parameters,
* each parameter setting is in the form keyword = value. Spaces around the
* equal sign are optional.
* To write an empty value, or a value containing spaces, surround it with
* single quotes, e.g.,
* keyword = 'a value'. Single quotes and backslashes within the value must
* be escaped with a backslash, i.e., \' and \\. Example: host=localhost
* port=5432 dbname=mydb connect_timeout=10 password='' The currently
* recognized parameter key words are:
* - host: can be either a host name or an IP address.
* - port: Port number to connect to at the server host.
* - dbname: The database name. Defaults to be the same as the user name.
* - user: user name to connect as. With PostgreSQL defaults to be the same
* as the operating system name of the user running the application.
* - password: Password to be used if the server demands password
* authentication.
*
* For other key words on PostgreSQL, see the PostgreSQL documentation.
* Only a pair of key values is valid for Sqlite3, and its keyword is
* 'filename'.
*
* @param connNum: The number of connections to database server;
*/
static std::shared_ptr<DbClient> newPgClient(const std::string &connInfo,
const size_t connNum);
#endif
#if USE_MYSQL
static std::shared_ptr<DbClient> newMysqlClient(const std::string &connInfo,
const size_t connNum);
#endif
#if USE_SQLITE3
static std::shared_ptr<DbClient> newSqlite3Client(
const std::string &connInfo,
const size_t connNum);
#endif
/// Async and nonblocking method
/**

View File

@ -17,13 +17,13 @@
#pragma once
#include <drogon/utils/string_view.h>
#include <drogon/orm/ArrayParser.h>
#include <drogon/orm/Result.h>
#include <drogon/orm/Row.h>
#include <memory>
#include <sstream>
#include <string>
#include <trantor/utils/config.h>
#include <vector>
#ifdef __linux__
@ -195,7 +195,12 @@ char *Field::as<char *>() const;
template <>
std::vector<char> Field::as<std::vector<char>>() const;
template <>
string_view Field::as<string_view>() const;
inline drogon::string_view Field::as<drogon::string_view>() const
{
auto first = _result.getValue(_row, _column);
auto length = _result.getLength(_row, _column);
return drogon::string_view(first, length);
}
template <>
int Field::as<int>() const;
template <>

View File

@ -13,7 +13,6 @@
*/
#pragma once
#include <drogon/config.h>
#include <drogon/orm/Exception.h>
#include <drogon/orm/Field.h>
#include <drogon/orm/FunctionTraits.h>
@ -21,9 +20,6 @@
#include <drogon/orm/Row.h>
#include <drogon/orm/RowIterator.h>
#include <trantor/utils/Logger.h>
#if USE_MYSQL
#include <mysql.h>
#endif
#include <functional>
#include <iostream>
#include <map>
@ -315,27 +311,10 @@ class SqlBinder
}
else if (_type == ClientType::Mysql)
{
#if USE_MYSQL
_objs.push_back(obj);
_parameters.push_back((char *)obj.get());
_length.push_back(0);
switch (sizeof(T))
{
case 1:
_format.push_back(MYSQL_TYPE_TINY);
break;
case 2:
_format.push_back(MYSQL_TYPE_SHORT);
break;
case 4:
_format.push_back(MYSQL_TYPE_LONG);
break;
case 8:
_format.push_back(MYSQL_TYPE_LONGLONG);
default:
break;
}
#endif
_format.push_back(getMysqlTypeBySize(sizeof(T)));
}
else if (_type == ClientType::Sqlite3)
{
@ -411,6 +390,7 @@ class SqlBinder
void exec() noexcept(false);
private:
int getMysqlTypeBySize(size_t size);
std::string _sql;
DbClient &_client;
size_t _paraNum = 0;

View File

@ -13,6 +13,7 @@
*/
#include "DbClientImpl.h"
#include <drogon/config.h>
#include <drogon/orm/DbClient.h>
using namespace drogon::orm;
using namespace drogon;
@ -27,31 +28,40 @@ internal::SqlBinder DbClient::operator<<(std::string &&sql)
return internal::SqlBinder(std::move(sql), *this, _type);
}
#if USE_POSTGRESQL
std::shared_ptr<DbClient> DbClient::newPgClient(const std::string &connInfo,
const size_t connNum)
{
#if USE_POSTGRESQL
return std::make_shared<DbClientImpl>(connInfo,
connNum,
ClientType::PostgreSQL);
}
#else
LOG_FATAL << "PostgreSQL is not supported!";
exit(1);
#endif
}
#if USE_MYSQL
std::shared_ptr<DbClient> DbClient::newMysqlClient(const std::string &connInfo,
const size_t connNum)
{
#if USE_MYSQL
return std::make_shared<DbClientImpl>(connInfo, connNum, ClientType::Mysql);
}
#else
LOG_FATAL << "Mysql is not supported!";
exit(1);
#endif
}
#if USE_SQLITE3
std::shared_ptr<DbClient> DbClient::newSqlite3Client(
const std::string &connInfo,
const size_t connNum)
{
#if USE_SQLITE3
return std::make_shared<DbClientImpl>(connInfo,
connNum,
ClientType::Sqlite3);
}
#else
LOG_FATAL << "Sqlite3 is not supported!";
exit(1);
#endif
}

View File

@ -14,6 +14,7 @@
#include "DbClientImpl.h"
#include "DbConnection.h"
#include <drogon/config.h>
#if USE_POSTGRESQL
#include "postgresql_impl/PgConnection.h"
#endif

View File

@ -15,6 +15,7 @@
#include "DbClientLockFree.h"
#include "DbConnection.h"
#include "TransactionImpl.h"
#include <drogon/config.h>
#if USE_POSTGRESQL
#include "postgresql_impl/PgConnection.h"
#endif

View File

@ -12,8 +12,9 @@
*
*/
#include "DbClientManager.h"
#include "../../lib/src/DbClientManager.h"
#include "DbClientLockFree.h"
#include <drogon/config.h>
#include <drogon/utils/Utilities.h>
#include <algorithm>

View File

@ -84,13 +84,6 @@ std::vector<char> Field::as<std::vector<char>>() const
return utils::hexToBinaryVector(sv.data() + 2, sv.length() - 2);
}
}
template <>
string_view Field::as<string_view>() const
{
auto first = _result.getValue(_row, _column);
auto length = _result.getLength(_row, _column);
return string_view(first, length);
}
template <>
int Field::as<int>() const

View File

@ -18,6 +18,9 @@
#include <future>
#include <iostream>
#include <stdio.h>
#if USE_MYSQL
#include <mysql.h>
#endif
using namespace drogon::orm;
using namespace drogon::orm::internal;
void SqlBinder::exec()
@ -258,4 +261,31 @@ SqlBinder &SqlBinder::operator<<(std::nullptr_t nullp)
_format.push_back(Sqlite3TypeNull);
}
return *this;
}
int SqlBinder::getMysqlTypeBySize(size_t size)
{
#if USE_MYSQL
switch (size)
{
case 1:
return MYSQL_TYPE_TINY;
break;
case 2:
return MYSQL_TYPE_SHORT;
break;
case 4:
return MYSQL_TYPE_LONG;
break;
case 8:
return MYSQL_TYPE_LONGLONG;
break;
default:
return 0;
}
#else
LOG_FATAL << "Mysql is not supported!";
exit(1);
return 0;
#endif
}

View File

@ -105,7 +105,7 @@ MysqlConnection::MysqlConnection(trantor::EventLoop *loop,
LOG_FATAL << "Socket fd < 0, Usually this is because the number of "
"files opened by the program exceeds the system "
"limit. Please use the ulimit command to check.";
exit(-1);
exit(1);
}
_channelPtr =
std::unique_ptr<trantor::Channel>(new trantor::Channel(loop, fd));

View File

@ -1,4 +1,7 @@
link_libraries(drogon trantor pthread dl)
LINK_LIBRARIES(drogon trantor pthread dl)
add_executable(mysql_test1 test1.cc)
#add_executable(test2 test2.cc)
ADD_EXECUTABLE(mysql_test1 test1.cc)
SET_PROPERTY(TARGET mysql_test1 PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD})
SET_PROPERTY(TARGET mysql_test1 PROPERTY CXX_STANDARD_REQUIRED ON)
SET_PROPERTY(TARGET mysql_test1 PROPERTY CXX_EXTENSIONS OFF)

View File

@ -50,7 +50,7 @@ PgConnection::PgConnection(trantor::EventLoop *loop,
LOG_FATAL << "Socket fd < 0, Usually this is because the number of "
"files opened by the program exceeds the system "
"limit. Please use the ulimit command to check.";
exit(-1);
exit(1);
}
_channel.setReadCallback([=]() {
if (_status != ConnectStatus_Ok)

View File

@ -1,4 +1,8 @@
link_libraries(drogon trantor pthread dl)
LINK_LIBRARIES(drogon trantor pthread dl)
add_executable(pg_test1 test1.cc)
add_executable(pg_test2 test2.cc)
ADD_EXECUTABLE(pg_test1 test1.cc)
ADD_EXECUTABLE(pg_test2 test2.cc)
SET_PROPERTY(TARGET pg_test1 pg_test2 PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD})
SET_PROPERTY(TARGET pg_test1 pg_test2 PROPERTY CXX_STANDARD_REQUIRED ON)
SET_PROPERTY(TARGET pg_test1 pg_test2 PROPERTY CXX_EXTENSIONS OFF)

View File

@ -48,7 +48,7 @@ Sqlite3Connection::Sqlite3Connection(
auto ret = sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
if (ret != SQLITE_OK)
{
LOG_FATAL << sqlite3_errstr(ret);
LOG_FATAL << "SQLITE_CONFIG_MULTITHREAD is not supported!";
}
});
// Get the key and value
@ -82,7 +82,7 @@ Sqlite3Connection::Sqlite3Connection(
auto thisPtr = shared_from_this();
if (ret != SQLITE_OK)
{
LOG_FATAL << sqlite3_errstr(ret);
LOG_FATAL << sqlite3_errmsg(_conn.get());
_closeCb(thisPtr);
}
else

View File

@ -1,3 +1,7 @@
link_libraries(drogon trantor pthread dl)
LINK_LIBRARIES(drogon trantor pthread dl)
add_executable(sqlite3_test1 test1.cc Groups.cc)
ADD_EXECUTABLE(sqlite3_test1 test1.cc Groups.cc)
SET_PROPERTY(TARGET sqlite3_test1 PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD})
SET_PROPERTY(TARGET sqlite3_test1 PROPERTY CXX_STANDARD_REQUIRED ON)
SET_PROPERTY(TARGET sqlite3_test1 PROPERTY CXX_EXTENSIONS OFF)

View File

@ -1,3 +1,7 @@
link_libraries(drogon trantor pthread dl)
LINK_LIBRARIES(drogon trantor pthread dl)
add_executable(db_test db_test.cc Users.cc)
ADD_EXECUTABLE(db_test db_test.cc Users.cc)
SET_PROPERTY(TARGET db_test PROPERTY CXX_STANDARD ${DROGON_CXX_STANDARD})
SET_PROPERTY(TARGET db_test PROPERTY CXX_STANDARD_REQUIRED ON)
SET_PROPERTY(TARGET db_test PROPERTY CXX_EXTENSIONS OFF)

View File

@ -8,7 +8,6 @@
#include "Users.h"
#include <drogon/utils/Utilities.h>
#include <string>
#include <trantor/utils/config.h>
using namespace drogon_model::postgres;

View File

@ -13,6 +13,7 @@
*
*/
#include "Users.h"
#include <drogon/config.h>
#include <drogon/orm/DbClient.h>
#include <iostream>
#include <trantor/utils/Logger.h>
@ -33,7 +34,7 @@ void testOutput(bool isGood, const std::string &testMessage)
{
std::cout << RED << testMessage << "\t\tBAD\n";
std::cout << RESET;
exit(-1);
exit(1);
}
}
@ -43,12 +44,6 @@ int main()
#if USE_POSTGRESQL
auto clientPtr = DbClient::newPgClient(
"host=127.0.0.1 port=5432 dbname=postgres user=antao", 1);
#elif USE_MYSQL
auto clientPtr = DbClient::newMysqlClient(
"host=127.0.0.1 port=3306 dbname=test user=root", 1);
#else
DbClientPtr clientPtr;
return -1;
#endif
LOG_DEBUG << "start!";
sleep(1);

@ -1 +1 @@
Subproject commit ad24f2c6733681f69c0c5bd9f218ef35c4f346d2
Subproject commit 93078923084bab9f4bd9e534e080f806df66fe5e

View File

@ -1,11 +0,0 @@
#!/bin/sh
echo "update config.h"
if [ ! -f $2 ];then
mv -f $1 $2
else
diff $1 $2
if [ $? -eq 1 ];then
mv -f $1 $2
fi
fi
rm -f $1