add HttpAppFramework class,not complete

This commit is contained in:
an-tao 2018-05-02 17:45:10 +08:00
parent 977160b7fc
commit ecfea6f713
15 changed files with 446 additions and 59 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required (VERSION 2.6)
project (DROGON C CXX)
project (DROGON CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fpermissive -g -ggdb")
@ -14,27 +14,33 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fpermissive -g -ggdb")
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fpermissive -g -ggdb")
# MESSAGE(STATUS "new gcc")
#endif()
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake_modules/)
find_package (jsoncpp REQUIRED)
include_directories(${JSONCPP_INCLUDE_DIRS})
link_directories(${JSONCPP_LIBRARY_DIRS})
find_package (UUID)
if(UUID_FOUND)
add_definitions(-DUSE_UUID)
endif()
add_subdirectory(trantor)
SET(CMAKE_INSTALL_PREFIX /usr/local/drogon)
#INSTALL(FILES trantor.cfg DESTINATION conf)
include_directories(${PROJECT_SOURCE_DIR}/trantor ${PROJECT_SOURCE_DIR}/lib/inc)
include_directories(${PROJECT_SOURCE_DIR}/trantor ${PROJECT_SOURCE_DIR}/drogon/inc)
add_subdirectory(examples)
aux_source_directory(${PROJECT_SOURCE_DIR}/drogon/src DIR_SRCS)
aux_source_directory(${PROJECT_SOURCE_DIR}/lib/src DIR_SRCS)
ADD_LIBRARY(drogon ${DIR_SRCS})
SET(CMAKE_INSTALL_PREFIX /usr/local)
install(TARGETS drogon DESTINATION lib)
file(GLOB trantor_net_headers "${CMAKE_CURRENT_SOURCE_DIR}/lib/inc/*.h")
install(FILES ${trantor_net_headers} DESTINATION include/drogon)
#add_library(db ${DIR_DB_SRCS})
add_executable(drogon ${DIR_SRCS})
add_dependencies(drogon trantor)
#if (version LESS 6.0.0)
# MESSAGE(STATUS "old gcc...")
# set (LIBCONFIG config++)
#else()
# MESSAGE(STATUS "new gcc...")
# set (LIBCONFIG libconfig++)
#endif()
target_link_libraries(drogon trantor pthread)
#crypt dl m pqxx pq hiredis mongocxx bsoncxx jsoncpp ${LIBCONFIG})
INSTALL(TARGETS drogon DESTINATION bin)
#target_link_libraries(drogon trantor pthread)

View File

@ -0,0 +1,119 @@
# - Try to find UUID
# Once done this will define
#
# UUID_FOUND - system has UUID
# UUID_INCLUDE_DIRS - the UUID include directory
# UUID_LIBRARIES - Link these to use UUID
# UUID_DEFINITIONS - Compiler switches required for using UUID
#
# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
# in cache already
set(UUID_FOUND TRUE)
else (UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
find_path(UUID_INCLUDE_DIR
NAMES
uuid.h
PATH_SUFFIXES
uuid
HINTS
${UUID_DIR}/include
$ENV{UUID_DIR}/include
$ENV{UUID_DIR}
${DELTA3D_EXT_DIR}/inc
$ENV{DELTA_ROOT}/ext/inc
$ENV{DELTA_ROOT}
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local/include
/usr/include
/usr/include/gdal
/sw/include # Fink
/opt/local/include # DarwinPorts
/opt/csw/include # Blastwave
/opt/include
[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/include
/usr/freeware/include
)
find_library(UUID_LIBRARY
NAMES
uuid ossp-uuid
HINTS
${UUID_DIR}/lib
$ENV{UUID_DIR}/lib
$ENV{UUID_DIR}
${DELTA3D_EXT_DIR}/lib
$ENV{DELTA_ROOT}/ext/lib
$ENV{DELTA_ROOT}
$ENV{OSG_ROOT}/lib
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local/lib
/usr/lib
/sw/lib
/opt/local/lib
/opt/csw/lib
/opt/lib
/usr/freeware/lib64
)
find_library(UUID_LIBRARY_DEBUG
NAMES
uuidd
HINTS
${UUID_DIR}/lib
$ENV{UUID_DIR}/lib
$ENV{UUID_DIR}
${DELTA3D_EXT_DIR}/lib
$ENV{DELTA_ROOT}/ext/lib
$ENV{DELTA_ROOT}
$ENV{OSG_ROOT}/lib
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local/lib
/usr/lib
/sw/lib
/opt/local/lib
/opt/csw/lib
/opt/lib
/usr/freeware/lib64
)
if (NOT UUID_LIBRARY AND BSD)
set(UUID_LIBRARY "")
endif(NOT UUID_LIBRARY AND BSD)
set(UUID_INCLUDE_DIRS ${UUID_INCLUDE_DIR})
set(UUID_LIBRARIES ${UUID_LIBRARY})
if (UUID_INCLUDE_DIRS)
if (BSD OR UUID_LIBRARIES)
set(UUID_FOUND TRUE)
endif (BSD OR UUID_LIBRARIES)
endif (UUID_INCLUDE_DIRS)
if (UUID_FOUND)
if (NOT UUID_FIND_QUIETLY)
message(STATUS "Found UUID: ${UUID_LIBRARIES}")
endif (NOT UUID_FIND_QUIETLY)
else (UUID_FOUND)
if (UUID_FIND_REQUIRED)
message(FATAL_ERROR "Could not find UUID")
endif (UUID_FIND_REQUIRED)
endif (UUID_FOUND)
# show the UUID_INCLUDE_DIRS and UUID_LIBRARIES variables only in the advanced view
mark_as_advanced(UUID_INCLUDE_DIRS UUID_LIBRARIES)
endif (UUID_LIBRARIES AND UUID_INCLUDE_DIRS)

View File

@ -1,41 +0,0 @@
#include <trantor/net/TcpServer.h>
#include <trantor/utils/Logger.h>
#include <trantor/net/EventLoopThread.h>
#include <string>
#include <iostream>
using namespace trantor;
#define USE_IPV6 0
int main()
{
LOG_DEBUG<<"test start";
Logger::setLogLevel(Logger::TRACE);
//EventLoopThread loopThread;
EventLoop loop;
//loopThread.run();
#if USE_IPV6
InetAddress addr(7676,true,true);
#else
InetAddress addr(7676);
#endif
TcpServer server(&loop,addr,"test");
server.setRecvMessageCallback([](const TcpConnectionPtr &connectionPtr,MsgBuffer *buffer){
//LOG_DEBUG<<"recv callback!";
std::cout<<std::string(buffer->peek(),buffer->readableBytes());
connectionPtr->send(buffer->peek(),buffer->readableBytes());
buffer->retrieveAll();
connectionPtr->forceClose();
});
server.setConnectionCallback([](const TcpConnectionPtr& connPtr){
if(connPtr->connected())
{
LOG_DEBUG<<"New connection";
}
else if(connPtr->disconnected())
{
LOG_DEBUG<<"connection disconnected";
}
});
server.setIoLoopNum(3);
server.start();
loop.loop();
}

3
examples/CMakeLists.txt Executable file
View File

@ -0,0 +1,3 @@
link_libraries(drogon trantor uuid pthread)
AUX_SOURCE_DIRECTORY(static_link_example DIR_STATIC)
add_executable(webapp ${DIR_STATIC})

View File

@ -0,0 +1,6 @@
#include <HttpAppFramework.h>
int main()
{
drogon::HttpAppFramework framework("0.0.0.0",12345);
framework.run();
}

39
lib/inc/HttpAppFramework.h Executable file
View File

@ -0,0 +1,39 @@
#pragma once
#include <HttpRequest.h>
#include <HttpResponse.h>
#include <trantor/utils/NonCopyable.h>
#include <string>
#include <set>
namespace drogon
{
class HttpAppFramework:public trantor::NonCopyable
{
public:
HttpAppFramework()= delete;
HttpAppFramework(const std::string &ip,uint16_t port);
void run();
private:
std::string _ip;
uint16_t _port;
void onAsyncRequest(const HttpRequest& req,std::function<void (HttpResponse &)>callback);
void readSendFile(const std::string& filePath,const HttpRequest& req, HttpResponse* resp);
#ifdef USE_UUID
//if uuid package found,we can use a uuid string as session id;
uint _sessionTimeout=0;
#endif
bool _enableLastModify=true;
std::set<std::string> _fileTypeSet={"html","jpg"};
std::string _rootPath;
//tool funs
#ifdef USE_UUID
std::string getUuid();
std::string stringToHex(unsigned char* ptr, long long length);
#endif
};
}

255
lib/src/HttpAppFramework.cc Executable file
View File

@ -0,0 +1,255 @@
#include "HttpAppFramework.h"
#include "HttpServer.h"
#include <sys/stat.h>
#include <iostream>
#include <fstream>
#ifdef USE_UUID
#include <uuid/uuid.h>
#endif
using namespace drogon;
using namespace std::placeholders;
HttpAppFramework::HttpAppFramework(const std::string &ip,uint16_t port):
_ip(ip),
_port(port)
{
}
void HttpAppFramework::run()
{
trantor::EventLoop loop;
HttpServer httpServer(&loop,InetAddress(_ip,_port),"");
httpServer.setHttpAsyncCallback(std::bind(&HttpAppFramework::onAsyncRequest,this,_1,_2));
httpServer.start();
loop.loop();
}
void HttpAppFramework::onAsyncRequest(const HttpRequest& req,std::function<void (HttpResponse &)>callback)
{
std::cout << "Headers " << req.methodString() << " " << req.path() << std::endl;
#if 1
const std::map<std::string, std::string>& headers = req.headers();
for (std::map<std::string, std::string>::const_iterator it = headers.begin();
it != headers.end();
++it) {
std::cout << it->first << ": " << it->second << std::endl;
}
std::cout<<"cookies:"<<std::endl;
auto cookies = req.cookies();
for(auto it=cookies.begin();it!=cookies.end();++it)
{
std::cout<<it->first<<"="<<it->second<<std::endl;
}
#endif
LOG_INFO << "http path=" << req.path();
LOG_INFO << "query: " << req.query() ;
#ifdef USE_UUID
std::string session_id=req.getCookie("JSESSIONID");
bool needSetJsessionid=false;
if(_sessionTimeout>0)
{
if(session_id=="")
{
session_id=getUuid().c_str();
needSetJsessionid=true;
//_sessionMap.insert(session_id,std::make_shared< Session >(),_sessionTimeout);
}
else
{
// if(_sessionMap.find(session_id)==false)
// {
// _sessionMap.insert(session_id,std::make_shared< Session >(),_sessionTimeout);
// }
}
}
#endif
std::string path = req.path().c_str();
auto pos = path.rfind(".");
if(pos != std::string::npos) {
std::string filetype = path.substr(pos + 1, path.length());
transform(filetype.begin(), filetype.end(), filetype.begin(), tolower);
if(_fileTypeSet.find(filetype) != _fileTypeSet.end()) {
LOG_INFO << "file query!";
std::string filePath = _rootPath + path;
HttpResponse resp(true);
#ifdef USE_UUID
if(needSetJsessionid)
resp.addCookie("JSESSIONID",session_id);
#endif
// pick a Content-Type for the file
if(filetype=="html") resp.setContentTypeCode(CT_TEXT_HTML);
else if(filetype=="js") resp.setContentTypeCode(CT_APPLICATION_X_JAVASCRIPT);
else if(filetype=="css") resp.setContentTypeCode(CT_TEXT_CSS);
else if(filetype=="xml") resp.setContentTypeCode(CT_TEXT_XML);
else if(filetype=="xsl") resp.setContentTypeCode(CT_TEXT_XSL);
else if(filetype=="txt") resp.setContentTypeCode(CT_TEXT_PLAIN);
else if(filetype=="svg") resp.setContentTypeCode(CT_IMAGE_SVG_XML);
else if(filetype=="ttf") resp.setContentTypeCode(CT_APPLICATION_X_FONT_TRUETYPE);
else if(filetype=="otf") resp.setContentTypeCode(CT_APPLICATION_X_FONT_OPENTYPE);
else if(filetype=="woff2")resp.setContentTypeCode(CT_APPLICATION_FONT_WOFF2);
else if(filetype=="woff") resp.setContentTypeCode(CT_APPLICATION_FONT_WOFF);
else if(filetype=="eot") resp.setContentTypeCode(CT_APPLICATION_VND_MS_FONTOBJ);
else if(filetype=="png") resp.setContentTypeCode(CT_IMAGE_PNG);
else if(filetype=="jpg") resp.setContentTypeCode(CT_IMAGE_JPG);
else if(filetype=="jpeg") resp.setContentTypeCode(CT_IMAGE_JPG);
else if(filetype=="gif") resp.setContentTypeCode(CT_IMAGE_GIF);
else if(filetype=="bmp") resp.setContentTypeCode(CT_IMAGE_BMP);
else if(filetype=="ico") resp.setContentTypeCode(CT_IMAGE_XICON);
else if(filetype=="icns") resp.setContentTypeCode(CT_IMAGE_ICNS);
else resp.setContentTypeCode(CT_APPLICATION_OCTET_STREAM);
readSendFile(filePath,req, &resp);
callback(resp);
return;
}
}
/*filters
std::vector<std::string> filters=(*_filterMap)[req.path().c_str()];
for(std::string filterClassName:filters)
{
TRObject *_obj=TRClassMap::newObject(filterClassName);
HttpFilter *filter= dynamic_cast<HttpFilter*>(_obj);
int filter_flag=0;
if(filter)
{
LOG_INFO<<filterClassName<<".doFilter()";
filter->setSession(_sessionMap[session_id]);
filter->doFilter(req,[=,&filter_flag]( HttpResponse &resp){
callback(resp);
filter_flag=1;
});
if(filter_flag)
return;
}
else
LOG_INFO<<"can't find filter "<<filterClassName;
}
*/
/*find controller
std::string ctrlName = (*_controllerMap)[req.path().c_str()];
TRObject *_object = TRClassMap::newObject(ctrlName);
HttpController *controller = dynamic_cast<HttpController*>(_object);
if(controller) {
controller->setSession(_sessionMap[session_id]);
controller->setEnvironment(this);
controller->handleHttpAsyncRequest(req, [=](HttpResponse& resp){
if(needSetJsessionid)
resp.addCookie("JSESSIONID",session_id);
callback(resp);
});
delete controller;
} else {
LOG_ERROR<<"can't find controller "<<ctrlName;
*/
HttpResponse resp(true);
resp.setStatusCode(HttpResponse::k404NotFound);
//resp.setCloseConnection(true);
#ifdef USE_UUID
if(needSetJsessionid)
resp.addCookie("JSESSIONID",session_id);
#endif
callback(resp);
// }
}
void HttpAppFramework::readSendFile(const std::string& filePath,const HttpRequest& req, HttpResponse* resp)
{
//If-Modified-Since: Wed Jun 15 08:57:30 2016 GMT
std::ifstream infile(filePath, std::ifstream::binary);
LOG_INFO << "send http file:" << filePath;
if(!infile) {
resp->setStatusCode(HttpResponse::k404NotFound);
resp->setCloseConnection(true);
return;
}
if(_enableLastModify)
{
struct stat fileStat;
LOG_DEBUG<<"enabled LastModify";
if(stat(filePath.c_str(),&fileStat)>=0)
{
std::cout<<"last modify time:"<<fileStat.st_mtime<<std::endl;
struct tm tm1;
gmtime_r(&fileStat.st_mtime,&tm1);
char timeBuf[64];
asctime_r(&tm1,timeBuf);
std::string timeStr(timeBuf);
std::string::size_type len=timeStr.length();
std::string lastModified =timeStr.substr(0,len-1)+" GMT";
std::string modiStr=req.getHeader("If-Modified-Since");
if(modiStr!=""&&modiStr==lastModified)
{
LOG_DEBUG<<"not Modified!";
resp->setStatusCode(HttpResponse::k304NotModified);
return;
}
resp->addHeader("Last-Modified",lastModified);
resp->addHeader("Expires","Thu, 01 Jan 1970 00:00:00 GMT");
}
}
std::streambuf * pbuf = infile.rdbuf();
std::streamsize size = pbuf->pubseekoff(0,infile.end);
pbuf->pubseekoff(0,infile.beg); // rewind
char *contents = new char [size];
pbuf->sgetn (contents,size);
infile.close();
std::string str(contents,size);
resp->setStatusCode(HttpResponse::k200Ok);
LOG_INFO << "file len:" << str.length();
resp->setBody(str);
delete contents;
}
#ifdef USE_UUID
std::string HttpAppFramework::getUuid()
{
uuid_t uu;
uuid_generate(uu);
return stringToHex(uu, 16);
}
std::string HttpAppFramework::stringToHex(unsigned char* ptr, long long length)
{
std::string idString;
for (long long i = 0; i < length; i++)
{
int value = (ptr[i] & 0xf0)>>4;
if (value < 10)
{
idString.append(1, char(value + 48));
} else
{
idString.append(1, char(value + 55));
}
value = (ptr[i] & 0x0f);
if (value < 10)
{
idString.append(1, char(value + 48));
} else
{
idString.append(1, char(value + 55));
}
}
return idString;
}
#endif