Modify drogon_ctl
This commit is contained in:
parent
17e15d282b
commit
aa8170ff18
|
@ -27,7 +27,9 @@ std::string create::detail()
|
|||
"drogon_ctl create controller [-s] [-n <namespace>] <class_name> //"
|
||||
"create HttpSimpleController source files\n"
|
||||
"drogon_ctl create controller -a <[namespace::]class_name> //"
|
||||
"create HttpApiController source files\n";
|
||||
"create HttpApiController source files\n"
|
||||
"drogon_ctl create controller -w [-n <namespace>] <class_name> //"
|
||||
"create WebSocketController source files\n";
|
||||
}
|
||||
|
||||
void create::handleCommand(std::vector<std::string> ¶meters)
|
||||
|
|
|
@ -39,6 +39,12 @@ void create_controller::handleCommand(std::vector<std::string> ¶meters)
|
|||
parameters.erase(iter);
|
||||
break;
|
||||
}
|
||||
else if(*iter=="-w"||*iter=="--websocket")
|
||||
{
|
||||
type=WebSocket;
|
||||
parameters.erase(iter);
|
||||
break;
|
||||
}
|
||||
else if(*iter=="-n"||*iter=="--namespace")
|
||||
{
|
||||
if(type==Simple)
|
||||
|
@ -87,6 +93,37 @@ void create_controller::handleCommand(std::vector<std::string> ¶meters)
|
|||
}
|
||||
createSimpleController(parameters,namespaceName);
|
||||
}
|
||||
else if(type==WebSocket)
|
||||
{
|
||||
std::string namespaceName;
|
||||
for(auto iter=parameters.begin();iter!=parameters.end();iter++)
|
||||
{
|
||||
if((*iter)[0]=='-')
|
||||
{
|
||||
if(*iter=="-n"||*iter=="--namespace")
|
||||
{
|
||||
iter=parameters.erase(iter);
|
||||
if(iter!=parameters.end())
|
||||
{
|
||||
namespaceName=*iter;
|
||||
iter=parameters.erase(iter);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout<<"please enter namespace"<<std::endl;
|
||||
return;
|
||||
}
|
||||
}else
|
||||
{
|
||||
std::cout<<ARGS_ERROR_STR<<std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
createSimpleController(parameters,namespaceName);
|
||||
}
|
||||
else
|
||||
createApiController(parameters);
|
||||
}
|
||||
|
@ -118,15 +155,59 @@ void create_controller::createSimpleController(const std::string &ctlName,const
|
|||
newSimpleControllerHeaderFile(oHeadFile,ctlName,namespaceName);
|
||||
newSimpleControllerSourceFile(oSourceFile,ctlName,namespaceName);
|
||||
}
|
||||
|
||||
void create_controller::createWebsockController(std::vector<std::string> &ctlNames,const std::string &namespaceName)
|
||||
{
|
||||
for(auto iter=ctlNames.begin();iter!=ctlNames.end();iter++)
|
||||
{
|
||||
if ((*iter)[0] == '-')
|
||||
{
|
||||
std::cout<<ARGS_ERROR_STR<<std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
for(auto ctlName:ctlNames)
|
||||
{
|
||||
createWebsockController(ctlName,namespaceName);
|
||||
}
|
||||
}
|
||||
void create_controller::createWebsockController(const std::string &ctlName,const std::string &namespaceName)
|
||||
{
|
||||
std::cout<<"create websocket controller:"<<namespaceName<<(namespaceName==""?"":"::")<<ctlName<<std::endl;
|
||||
std::string headFileName=ctlName+".h";
|
||||
std::string sourceFilename=ctlName+".cc";
|
||||
std::ofstream oHeadFile(headFileName.c_str(),std::ofstream::out);
|
||||
std::ofstream oSourceFile(sourceFilename.c_str(),std::ofstream::out);
|
||||
if(!oHeadFile||!oSourceFile)
|
||||
return;
|
||||
newWebsockControllerHeaderFile(oHeadFile,ctlName,namespaceName);
|
||||
newWebsockControllerSourceFile(oSourceFile,ctlName,namespaceName);
|
||||
}
|
||||
|
||||
void create_controller::newSimpleControllerHeaderFile(std::ofstream &file,const std::string &ctlName,const std::string &namespaceName)
|
||||
{
|
||||
file<<"#pragma once\n";
|
||||
file<<"#include <drogon/HttpSimpleController.h>\n";
|
||||
file<<"using namespace drogon;\n";
|
||||
std::string indent="";
|
||||
if(namespaceName!="") {
|
||||
file << "namespace " << namespaceName << "{\n";
|
||||
indent=" ";
|
||||
auto namespace_name=namespaceName;
|
||||
if(namespace_name!="") {
|
||||
auto pos=namespace_name.find("::");
|
||||
while(pos!=std::string::npos)
|
||||
{
|
||||
auto namespaceI=namespace_name.substr(0,pos);
|
||||
namespace_name=namespace_name.substr(pos+2);
|
||||
file<<indent<<"namespace "<<namespaceI<<"\n";
|
||||
file<<indent<<"{\n";
|
||||
indent.append(" ");
|
||||
pos=namespace_name.find("::");
|
||||
}
|
||||
if(!namespace_name.empty())
|
||||
{
|
||||
file<<indent<<"namespace "<<namespace_name<<"\n";
|
||||
file<<indent<<"{\n";
|
||||
indent.append(" ");
|
||||
}
|
||||
}
|
||||
file<<indent<<"class "<<ctlName<<":public drogon::HttpSimpleController<"<<ctlName<<">\n";
|
||||
file<<indent<<"{\n";
|
||||
|
@ -139,8 +220,12 @@ void create_controller::newSimpleControllerHeaderFile(std::ofstream &file,const
|
|||
file<<indent<<" //PATH_ADD(\"/path\",\"filter1\",\"filter2\",...);\n";
|
||||
file<<indent<<" PATH_LIST_END\n";
|
||||
file<<indent<<"};\n";
|
||||
if(namespaceName!="")
|
||||
file<<"}\n";
|
||||
if(indent=="")
|
||||
return;
|
||||
do {
|
||||
indent.resize(indent.length()-4);
|
||||
file<<indent<<"}\n";
|
||||
} while(indent!="");
|
||||
}
|
||||
void create_controller::newSimpleControllerSourceFile(std::ofstream &file,const std::string &ctlName,const std::string &namespaceName)
|
||||
{
|
||||
|
@ -152,6 +237,70 @@ void create_controller::newSimpleControllerSourceFile(std::ofstream &file,const
|
|||
file<<" //write your application logic here\n";
|
||||
file<<"}";
|
||||
}
|
||||
|
||||
void create_controller::newWebsockControllerHeaderFile(std::ofstream &file,const std::string &ctlName,const std::string &namespaceName)
|
||||
{
|
||||
file<<"#pragma once\n";
|
||||
file<<"#include <drogon/HttpWebsocketController.h>\n";
|
||||
file<<"using namespace drogon;\n";
|
||||
std::string indent="";
|
||||
auto namespace_name=namespaceName;
|
||||
if(namespace_name!="") {
|
||||
auto pos=namespace_name.find("::");
|
||||
while(pos!=std::string::npos)
|
||||
{
|
||||
auto namespaceI=namespace_name.substr(0,pos);
|
||||
namespace_name=namespace_name.substr(pos+2);
|
||||
file<<indent<<"namespace "<<namespaceI<<"\n";
|
||||
file<<indent<<"{\n";
|
||||
indent.append(" ");
|
||||
pos=namespace_name.find("::");
|
||||
}
|
||||
if(!namespace_name.empty())
|
||||
{
|
||||
file<<indent<<"namespace "<<namespace_name<<"\n";
|
||||
file<<indent<<"{\n";
|
||||
indent.append(" ");
|
||||
}
|
||||
}
|
||||
file<<indent<<"class "<<ctlName<<":public drogon::HttpWebsocketController<"<<ctlName<<">\n";
|
||||
file<<indent<<"{\n";
|
||||
file<<indent<<"public:\n";
|
||||
//TestController(){}
|
||||
// virtual void handleNewMessage(const WebSocketConnectionPtr&,
|
||||
// trantor::MsgBuffer*)=0;
|
||||
// //on new connection or after disconnect
|
||||
// virtual void handleConnection(const WebSocketConnectionPtr&)=0;
|
||||
file<<indent<<" virtual void handleNewMessage(const WebSocketConnectionPtr&,\n";
|
||||
file<<indent<<" trantor::MsgBuffer*)override;\n";
|
||||
file<<indent<<" virtual void handleConnection(const WebSocketConnectionPtr&)override;\n";
|
||||
file<<indent<<" WS_PATH_LIST_BEGIN\n";
|
||||
file<<indent<<" //list path definations here;\n";
|
||||
file<<indent<<" //WS_PATH_ADD(\"/path\");\n";
|
||||
file<<indent<<" WS_PATH_LIST_END\n";
|
||||
file<<indent<<"};\n";
|
||||
if(indent=="")
|
||||
return;
|
||||
do {
|
||||
indent.resize(indent.length()-4);
|
||||
file<<indent<<"}\n";
|
||||
} while(indent!="");
|
||||
}
|
||||
void create_controller::newWebsockControllerSourceFile(std::ofstream &file,const std::string &ctlName,const std::string &namespaceName)
|
||||
{
|
||||
file<<"#include \""<<ctlName<<".h\"\n";
|
||||
if(namespaceName!="")
|
||||
file<<"using namespace "<<namespaceName<<";\n";
|
||||
file<<"void "<<ctlName<<"::handleNewMessage(const WebSocketConnectionPtr& wsConnPtr,trantor::MsgBuffer* buffer)\n";
|
||||
file<<"{\n";
|
||||
file<<" //write your application logic here\n";
|
||||
file<<"}";
|
||||
file<<"void "<<ctlName<<"::handleConnection(const WebSocketConnectionPtr& wsConnPtr)\n";
|
||||
file<<"{\n";
|
||||
file<<" //write your application logic here\n";
|
||||
file<<"}";
|
||||
}
|
||||
|
||||
void create_controller::createApiController(std::vector<std::string> &apiClasses)
|
||||
{
|
||||
for(auto iter=apiClasses.begin();iter!=apiClasses.end();iter++)
|
||||
|
|
|
@ -27,14 +27,21 @@ namespace drogon_ctl
|
|||
protected:
|
||||
enum ControllerType{
|
||||
Simple=0,
|
||||
API
|
||||
API,
|
||||
WebSocket
|
||||
};
|
||||
void createSimpleController(std::vector<std::string> &ctlNames,const std::string &namespaceName="");
|
||||
void createSimpleController(const std::string &ctlName,const std::string &namespaceName="");
|
||||
void createWebsockController(std::vector<std::string> &ctlNames,const std::string &namespaceName="");
|
||||
void createWebsockController(const std::string &ctlName,const std::string &namespaceName="");
|
||||
|
||||
void createApiController(std::vector<std::string> &apiClasses);
|
||||
void createApiController(const std::string &className);
|
||||
void newSimpleControllerHeaderFile(std::ofstream &file,const std::string &ctlName,const std::string &namespaceName="");
|
||||
void newSimpleControllerSourceFile(std::ofstream &file,const std::string &ctlName,const std::string &namespaceName="");
|
||||
void newWebsockControllerHeaderFile(std::ofstream &file,const std::string &ctlName,const std::string &namespaceName="");
|
||||
void newWebsockControllerSourceFile(std::ofstream &file,const std::string &ctlName,const std::string &namespaceName="");
|
||||
|
||||
void newApiControllerHeaderFile(std::ofstream &file,const std::string &className);
|
||||
void newApiControllerSourceFile(std::ofstream &file,const std::string &className,const std::string &filename);
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <string>
|
||||
#include <memory>
|
||||
namespace drogon{
|
||||
class WebSocketConnection:public trantor::NonCopyable
|
||||
class WebSocketConnection
|
||||
{
|
||||
public:
|
||||
WebSocketConnection()= default;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <drogon/DrObject.h>
|
||||
#include <drogon/HttpAppFramework.h>
|
||||
#include <drogon/WebSocketConnection.h>
|
||||
#include <trantor/utils/Logger.h>
|
||||
#include <trantor/net/TcpConnection.h>
|
||||
#include <string>
|
||||
|
@ -38,8 +39,11 @@ namespace drogon
|
|||
class WebSocketControllerBase:public virtual DrObjectBase
|
||||
{
|
||||
public:
|
||||
virtual void handleNewMessage(const TcpConnectionPtr&,
|
||||
MsgBuffer*)=0;
|
||||
//on new data received
|
||||
virtual void handleNewMessage(const WebSocketConnectionPtr&,
|
||||
trantor::MsgBuffer*)=0;
|
||||
//on new connection or after disconnect
|
||||
virtual void handleConnection(const WebSocketConnectionPtr&)=0;
|
||||
virtual ~WebSocketControllerBase(){}
|
||||
};
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
#include "HttpRequestImpl.h"
|
||||
#include "HttpResponseImpl.h"
|
||||
#include "HttpClientImpl.h"
|
||||
#include "WebSockectConnectionImpl.h"
|
||||
#include <drogon/utils/Utilities.h>
|
||||
#include <drogon/WebSocketController.h>
|
||||
#include <drogon/DrClassMap.h>
|
||||
#include <drogon/HttpAppFramework.h>
|
||||
#include <drogon/HttpRequest.h>
|
||||
|
@ -69,7 +69,11 @@ namespace drogon
|
|||
private:
|
||||
std::vector<std::tuple<std::string,uint16_t,bool>> _listeners;
|
||||
void onAsyncRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)> & callback);
|
||||
void onNewWebsockRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)> & callback);
|
||||
void onNewWebsockRequest(const HttpRequestPtr& req,
|
||||
const std::function<void (HttpResponse &)> & callback,
|
||||
const WebSocketConnectionPtr &wsConnPtr);
|
||||
void onWebsockMessage(const WebSocketConnectionPtr &wsConnPtr,trantor::MsgBuffer *buffer);
|
||||
void onWebsockDisconnect(const WebSocketConnectionPtr &wsConnPtr);
|
||||
void readSendFile(const std::string& filePath,const HttpRequestPtr& req, HttpResponse* resp);
|
||||
void addApiPath(const std::string &path,
|
||||
const HttpApiBinderBasePtr &binder,
|
||||
|
@ -349,8 +353,9 @@ void HttpAppFrameworkImpl::run()
|
|||
}
|
||||
serverPtr->setIoLoopNum(_threadNum);
|
||||
serverPtr->setHttpAsyncCallback(std::bind(&HttpAppFrameworkImpl::onAsyncRequest,this,_1,_2));
|
||||
serverPtr->setNewWebsocketCallback(std::bind(&HttpAppFrameworkImpl::onNewWebsockRequest,this,_1,_2));
|
||||
|
||||
serverPtr->setNewWebsocketCallback(std::bind(&HttpAppFrameworkImpl::onNewWebsockRequest,this,_1,_2,_3));
|
||||
serverPtr->setWebsocketMessageCallback(std::bind(&HttpAppFrameworkImpl::onWebsockMessage,this,_1,_2));
|
||||
serverPtr->setDisconnectWebsocketCallback(std::bind(&HttpAppFrameworkImpl::onWebsockDisconnect,this,_1));
|
||||
serverPtr->start();
|
||||
servers.push_back(serverPtr);
|
||||
#endif
|
||||
|
@ -416,32 +421,69 @@ void HttpAppFrameworkImpl::doFilters(const std::vector<std::string> &filters,
|
|||
}
|
||||
doFilterChain(filterPtrs,req,callback,needSetJsessionid,session_id,missCallback);
|
||||
}
|
||||
void HttpAppFrameworkImpl::onNewWebsockRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)> & callback)
|
||||
void HttpAppFrameworkImpl::onWebsockDisconnect(const WebSocketConnectionPtr &wsConnPtr)
|
||||
{
|
||||
auto wsConnImplPtr=std::dynamic_pointer_cast<WebSocketConnectionImpl>(wsConnPtr);
|
||||
assert(wsConnImplPtr);
|
||||
auto ctrl=wsConnImplPtr->controller();
|
||||
if(ctrl)
|
||||
{
|
||||
ctrl->handleConnection(wsConnPtr);
|
||||
wsConnImplPtr->setController(WebSocketControllerBasePtr());
|
||||
}
|
||||
|
||||
}
|
||||
void HttpAppFrameworkImpl::onWebsockMessage(const WebSocketConnectionPtr &wsConnPtr,
|
||||
trantor::MsgBuffer *buffer)
|
||||
{
|
||||
auto wsConnImplPtr=std::dynamic_pointer_cast<WebSocketConnectionImpl>(wsConnPtr);
|
||||
assert(wsConnImplPtr);
|
||||
auto ctrl=wsConnImplPtr->controller();
|
||||
if(ctrl)
|
||||
ctrl->handleNewMessage(wsConnPtr,buffer);
|
||||
}
|
||||
void HttpAppFrameworkImpl::onNewWebsockRequest(const HttpRequestPtr& req,
|
||||
const std::function<void (HttpResponse &)> & callback,
|
||||
const WebSocketConnectionPtr &wsConnPtr)
|
||||
{
|
||||
// magic = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
|
||||
// sha1 = hashlib.sha1()
|
||||
// sha1.update(ws_key + magic)
|
||||
// return base64.b64encode(sha1.digest())
|
||||
std::string wsKey=req->getHeader("Sec-WebSocket-Key");
|
||||
if(!wsKey.empty())
|
||||
{
|
||||
// magic="258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
wsKey.append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
||||
unsigned char accKey[SHA_DIGEST_LENGTH];
|
||||
SHA1(reinterpret_cast<const unsigned char *>(wsKey.c_str()), wsKey.length(), accKey);
|
||||
auto base64Key=base64_encode(accKey,SHA_DIGEST_LENGTH);
|
||||
auto resp=HttpResponse::newHttpResponse();
|
||||
resp->setStatusCode(HttpResponse::k101,"Switching Protocols");
|
||||
resp->addHeader("Upgrade","websocket");
|
||||
resp->addHeader("Connection","Upgrade");
|
||||
resp->addHeader("Sec-WebSocket-Accept",base64Key);
|
||||
callback(*resp);
|
||||
} else{
|
||||
HttpResponseImpl resp;
|
||||
resp.setStatusCode(HttpResponse::k404NotFound);
|
||||
resp.setCloseConnection(true);
|
||||
callback(resp);
|
||||
WebSocketControllerBasePtr ctrlPtr;
|
||||
{
|
||||
std::string pathLower(req->path());
|
||||
std::transform(pathLower.begin(),pathLower.end(),pathLower.begin(),tolower);
|
||||
std::lock_guard<std::mutex> guard(_websockCtrlMutex);
|
||||
if(_websockCtrlMap.find(pathLower)!=_websockCtrlMap.end())
|
||||
{
|
||||
ctrlPtr=_websockCtrlMap[pathLower];
|
||||
}
|
||||
}
|
||||
if(ctrlPtr)
|
||||
{
|
||||
wsKey.append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
||||
unsigned char accKey[SHA_DIGEST_LENGTH];
|
||||
SHA1(reinterpret_cast<const unsigned char *>(wsKey.c_str()), wsKey.length(), accKey);
|
||||
auto base64Key=base64_encode(accKey,SHA_DIGEST_LENGTH);
|
||||
auto resp=HttpResponse::newHttpResponse();
|
||||
resp->setStatusCode(HttpResponse::k101,"Switching Protocols");
|
||||
resp->addHeader("Upgrade","websocket");
|
||||
resp->addHeader("Connection","Upgrade");
|
||||
resp->addHeader("Sec-WebSocket-Accept",base64Key);
|
||||
callback(*resp);
|
||||
auto wsConnImplPtr=std::dynamic_pointer_cast<WebSocketConnectionImpl>(wsConnPtr);
|
||||
assert(wsConnImplPtr);
|
||||
wsConnImplPtr->setController(ctrlPtr);
|
||||
ctrlPtr->handleConnection(wsConnPtr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
HttpResponseImpl resp;
|
||||
resp.setStatusCode(HttpResponse::k404NotFound);
|
||||
resp.setCloseConnection(true);
|
||||
callback(resp);
|
||||
|
||||
}
|
||||
void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)> & callback)
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "HttpRequestImpl.h"
|
||||
#include "HttpResponseImpl.h"
|
||||
#include <trantor/utils/MsgBuffer.h>
|
||||
#include <drogon/WebSocketConnection.h>
|
||||
|
||||
using namespace trantor;
|
||||
namespace drogon
|
||||
|
@ -132,13 +133,13 @@ namespace drogon
|
|||
}
|
||||
return false;
|
||||
}
|
||||
bool isWebsock()
|
||||
WebSocketConnectionPtr webSocketConn()
|
||||
{
|
||||
return _isWebsock;
|
||||
return _websockConnPtr;
|
||||
}
|
||||
void setIsWebsock(bool val)
|
||||
void setWebsockConnection(const WebSocketConnectionPtr &conn)
|
||||
{
|
||||
_isWebsock=val;
|
||||
_websockConnPtr=conn;
|
||||
}
|
||||
private:
|
||||
bool processRequestLine(const char *begin, const char *end);
|
||||
|
@ -150,7 +151,7 @@ namespace drogon
|
|||
HttpResponseParseState res_state_;
|
||||
HttpResponseImpl response_;
|
||||
bool _firstRequest=true;
|
||||
bool _isWebsock=false;
|
||||
WebSocketConnectionPtr _websockConnPtr;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -193,13 +193,17 @@ void HttpResponseImpl::appendToBuffer(MsgBuffer* output) const
|
|||
output->append("\r\n");
|
||||
snprintf(buf, sizeof buf, "Content-Length: %lu\r\n", _body.size());
|
||||
output->append(buf);
|
||||
if (_closeConnection) {
|
||||
output->append("Connection: close\r\n");
|
||||
} else {
|
||||
if(_headers.find("Connection")==_headers.end())
|
||||
{
|
||||
if (_closeConnection) {
|
||||
output->append("Connection: close\r\n");
|
||||
} else {
|
||||
|
||||
output->append("Connection: Keep-Alive\r\n");
|
||||
output->append("Connection: Keep-Alive\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (auto it = _headers.begin();
|
||||
it != _headers.end();
|
||||
++it) {
|
||||
|
|
|
@ -43,6 +43,16 @@ static void defaultHttpAsyncCallback(const HttpRequestPtr&,const std::function<v
|
|||
callback(resp);
|
||||
}
|
||||
|
||||
static void defaultWebSockAsyncCallback(const HttpRequestPtr&,
|
||||
const std::function<void( HttpResponse& resp)> & callback,
|
||||
const WebSocketConnectionPtr& wsConnPtr)
|
||||
{
|
||||
HttpResponseImpl resp;
|
||||
resp.setStatusCode(HttpResponse::k404NotFound);
|
||||
resp.setCloseConnection(true);
|
||||
callback(resp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -51,7 +61,7 @@ HttpServer::HttpServer(EventLoop* loop,
|
|||
const std::string& name)
|
||||
: server_(loop, listenAddr, name.c_str()),
|
||||
httpAsyncCallback_(defaultHttpAsyncCallback),
|
||||
newWebsocketCallback_(defaultHttpAsyncCallback)
|
||||
newWebsocketCallback_(defaultWebSockAsyncCallback)
|
||||
{
|
||||
server_.setConnectionCallback(
|
||||
std::bind(&HttpServer::onConnection, this, _1));
|
||||
|
@ -81,9 +91,9 @@ void HttpServer::onConnection(const TcpConnectionPtr& conn)
|
|||
HttpContext* context = any_cast<HttpContext>(conn->getMutableContext());
|
||||
|
||||
// LOG_INFO << "###:" << string(buf->peek(), buf->readableBytes());
|
||||
if(context->isWebsock())
|
||||
if(context->webSocketConn())
|
||||
{
|
||||
//TODO websock disconnect !
|
||||
disconnectWebsocketCallback_(context->webSocketConn());
|
||||
}
|
||||
conn->setContext(std::string("None"));
|
||||
}
|
||||
|
@ -95,10 +105,10 @@ void HttpServer::onMessage(const TcpConnectionPtr& conn,
|
|||
HttpContext* context = any_cast<HttpContext>(conn->getMutableContext());
|
||||
|
||||
// LOG_INFO << "###:" << string(buf->peek(), buf->readableBytes());
|
||||
if(context->isWebsock())
|
||||
if(context->webSocketConn())
|
||||
{
|
||||
//websocket payload,we shouldn't parse it
|
||||
//TODO websock message callback;
|
||||
webSocketMessageCallback_(context->webSocketConn(),buf);
|
||||
return;
|
||||
}
|
||||
if (!context->parseRequest(buf)) {
|
||||
|
@ -113,16 +123,17 @@ void HttpServer::onMessage(const TcpConnectionPtr& conn,
|
|||
context->requestImpl()->setReceiveDate(trantor::Date::date());
|
||||
if(context->firstReq()&&isWebSocket(conn,context->request()))
|
||||
{
|
||||
auto wsConn=std::make_shared<WebSocketConnectionImpl>(conn);
|
||||
newWebsocketCallback_(context->request(),[=](HttpResponse &resp) mutable
|
||||
{
|
||||
if(resp.statusCode()==HttpResponse::k101)
|
||||
{
|
||||
context->setIsWebsock(true);
|
||||
context->setWebsockConnection(wsConn);
|
||||
}
|
||||
MsgBuffer buffer;
|
||||
((HttpResponseImpl &)resp).appendToBuffer(&buffer);
|
||||
conn->send(buffer.peek(),buffer.readableBytes());
|
||||
});
|
||||
},wsConn);
|
||||
}
|
||||
else
|
||||
onRequest(conn, context->request());
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "WebSockectConnectionImpl.h"
|
||||
#include <drogon/config.h>
|
||||
#include <trantor/net/TcpServer.h>
|
||||
#include <trantor/utils/NonCopyable.h>
|
||||
|
@ -34,6 +35,15 @@ namespace drogon
|
|||
public:
|
||||
|
||||
typedef std::function< void (const HttpRequestPtr&,const std::function<void (HttpResponse &)>&)> HttpAsyncCallback;
|
||||
typedef std::function< void (const HttpRequestPtr&,
|
||||
const std::function<void (HttpResponse &)>&,
|
||||
const WebSocketConnectionPtr &)>
|
||||
WebSocketNewAsyncCallback;
|
||||
typedef std::function< void (const WebSocketConnectionPtr &)>
|
||||
WebSocketDisconnetCallback;
|
||||
typedef std::function< void (const WebSocketConnectionPtr &,trantor::MsgBuffer *)>
|
||||
WebSocketMessageCallback;
|
||||
|
||||
HttpServer(EventLoop* loop,
|
||||
const InetAddress& listenAddr,
|
||||
const std::string& name);
|
||||
|
@ -46,10 +56,18 @@ namespace drogon
|
|||
{
|
||||
httpAsyncCallback_= cb;
|
||||
}
|
||||
void setNewWebsocketCallback(const HttpAsyncCallback& cb)
|
||||
void setNewWebsocketCallback(const WebSocketNewAsyncCallback& cb)
|
||||
{
|
||||
newWebsocketCallback_=cb;
|
||||
}
|
||||
void setDisconnectWebsocketCallback(const WebSocketDisconnetCallback& cb)
|
||||
{
|
||||
disconnectWebsocketCallback_=cb;
|
||||
}
|
||||
void setWebsocketMessageCallback(const WebSocketMessageCallback& cb)
|
||||
{
|
||||
webSocketMessageCallback_=cb;
|
||||
}
|
||||
void setIoLoopNum(int numThreads)
|
||||
{
|
||||
server_.setIoLoopNum(numThreads);
|
||||
|
@ -71,8 +89,9 @@ namespace drogon
|
|||
bool isWebSocket(const TcpConnectionPtr& conn, const HttpRequestPtr& req);
|
||||
trantor::TcpServer server_;
|
||||
HttpAsyncCallback httpAsyncCallback_;
|
||||
HttpAsyncCallback newWebsocketCallback_;
|
||||
|
||||
WebSocketNewAsyncCallback newWebsocketCallback_;
|
||||
WebSocketDisconnetCallback disconnectWebsocketCallback_;
|
||||
WebSocketMessageCallback webSocketMessageCallback_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,34 +1,6 @@
|
|||
#include <drogon/WebSocketConnection.h>
|
||||
#include "WebSockectConnectionImpl.h"
|
||||
#include <trantor/net/TcpConnection.h>
|
||||
namespace drogon{
|
||||
class WebSocketConnectionImpl:public WebSocketConnection
|
||||
{
|
||||
public:
|
||||
WebSocketConnectionImpl(const trantor::TcpConnectionPtr &conn);
|
||||
|
||||
virtual void send(const char *msg,uint64_t len) override;
|
||||
virtual void send(const std::string &msg) override;
|
||||
|
||||
virtual const trantor::InetAddress& localAddr() const override;
|
||||
virtual const trantor::InetAddress& peerAddr() const override;
|
||||
|
||||
virtual bool connected() const override;
|
||||
virtual bool disconnected() const override;
|
||||
|
||||
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;
|
||||
|
||||
private:
|
||||
std::weak_ptr<trantor::TcpConnection> _tcpConn;
|
||||
trantor::InetAddress _localAddr;
|
||||
trantor::InetAddress _peerAddr;
|
||||
any _context;
|
||||
};
|
||||
}
|
||||
using namespace drogon;
|
||||
WebSocketConnectionImpl::WebSocketConnectionImpl(const trantor::TcpConnectionPtr &conn):
|
||||
_tcpConn(conn),
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
#include <drogon/WebSocketConnection.h>
|
||||
#include <drogon/WebSocketController.h>
|
||||
namespace drogon{
|
||||
class WebSocketConnectionImpl:public WebSocketConnection
|
||||
{
|
||||
public:
|
||||
WebSocketConnectionImpl(const trantor::TcpConnectionPtr &conn);
|
||||
|
||||
virtual void send(const char *msg,uint64_t len) override;
|
||||
virtual void send(const std::string &msg) override;
|
||||
|
||||
virtual const trantor::InetAddress& localAddr() const override;
|
||||
virtual const trantor::InetAddress& peerAddr() const override;
|
||||
|
||||
virtual bool connected() const override;
|
||||
virtual bool disconnected() const override;
|
||||
|
||||
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;
|
||||
|
||||
void setController(const WebSocketControllerBasePtr &ctrl)
|
||||
{
|
||||
_ctrlPtr=ctrl;
|
||||
}
|
||||
WebSocketControllerBasePtr controller()
|
||||
{
|
||||
return _ctrlPtr;
|
||||
}
|
||||
private:
|
||||
std::weak_ptr<trantor::TcpConnection> _tcpConn;
|
||||
trantor::InetAddress _localAddr;
|
||||
trantor::InetAddress _peerAddr;
|
||||
WebSocketControllerBasePtr _ctrlPtr;
|
||||
any _context;
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue