Commit 69dd2867 by Amir Aharon

Merge branch 'Feature-MongooseFree' into 'develop'

Feature mongoose free

Bye bye mongoose 😢 

See merge request !2
parents bb9ac7a2 7541b6f9
......@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.12)
project(Microservice)
# version stuff
set (Microservice_VERSION_MAJOR 1)
set (Microservice_VERSION_MINOR 1)
set (Microservice_VERSION_MINOR 2)
set (Microservice_VERSION_PATCH 0)
set(Microservice_VERSION_STRING ${Microservice_VERSION_MAJOR}.${Microservice_VERSION_MINOR}.${Microservice_VERSION_PATCH})
......@@ -28,17 +28,18 @@ include_directories(SYSTEM ../3party/cereal-1.2.1/include)
include_directories(SYSTEM ../3party/rapidjson-cereal-1.2.1)
#include_directories(SYSTEM ../3party/rapidjson-0.11/include/rapidjson)
include_directories(SYSTEM ../3party/cppmetrics-0.1.1-Linux/include)
include_directories(SYSTEM ../3party/mongoose)
include_directories(SYSTEM ../3party/civetweb/include)
include_directories(SYSTEM ../3party/cpprest/Release/include)
include_directories(SYSTEM ../3party/rabbitmq)
include_directories(SYSTEM ../internals/include/Rabbitmq)
include_directories(SYSTEM /usr/include/hiredis)
# recursive search files cpp files
file(GLOB_RECURSE SOURCES "src/*.cpp")
set (3PARTY_SOURCES ../3party/mongoose/mongoose.c )
file(GLOB_RECURSE SOURCES "src/*.cpp" src/Microservice_BaseRestResponse.h src/common/Microservice_RestResponse.h src/common/Microservice_MsgQContext.h src/handlers/Microservice_Reactor.cpp src/handlers/Microservice_Reactor.h src/common/Microservice_PubSubContext.h src/handlers/Microservice_MsgQHandler.h src/handlers/Microservice_PubSubHandler.h src/impl/servers/Microservice_IMsgQueueServerZmqImpl.cpp src/impl/servers/Microservice_IMsgQueueServerZmqImpl.h src/impl/Microservice_IMsgArchiverCerealImpls.h src/utils/ServerFactory.cpp src/utils/ServerFactory.h src/utils/ClientFactory.cpp src/utils/ClientFactory.h src/impl/clients/MSZMQClientImpl.cpp src/impl/clients/MSZMQClientImpl.h src/impl/clients/MSIPubSubClientImpl.cpp src/impl/clients/MSIPubSubClientImpl.h)
set (3PARTY_SOURCES ../3party/civetweb/src/civetweb.c ../3party/civetweb/src/CivetServer.cpp ../3party/civetweb/src/md5.inl ../3party/civetweb/src/handle_form.inl)
#Generate the shared library from the sources
add_library(Microservice SHARED ${SOURCES} ${3PARTY_SOURCES} src/common/Microservice_RestResponse.h src/common/Microservice_MsgQContext.h src/handlers/Microservice_Reactor.cpp src/handlers/Microservice_Reactor.h src/common/Microservice_PubSubContext.h src/handlers/Microservice_MsgQHandler.h src/handlers/Microservice_PubSubHandler.h src/impl/servers/Microservice_IMsgQueueServerZmqImpl.cpp src/impl/servers/Microservice_IMsgQueueServerZmqImpl.h src/impl/Microservice_IMsgArchiverCerealImpls.h src/utils/ServerFactory.cpp src/utils/ServerFactory.h src/utils/ClientFactory.cpp src/utils/ClientFactory.h src/impl/clients/MSZMQClientImpl.cpp src/impl/clients/MSZMQClientImpl.h src/impl/clients/MSIPubSubClientImpl.cpp src/impl/clients/MSIPubSubClientImpl.h)
add_library(Microservice SHARED ${SOURCES} ${3PARTY_SOURCES} )
target_link_libraries(Microservice ${PROJECT_LINK_LIBS} )
set_target_properties(Microservice PROPERTIES VERSION ${Microservice_VERSION_STRING}
SOVERSION ${Microservice_VERSION_MAJOR})
......
## C++ Microservice Framework
## VERSIONS:
# 1.2.0
- replace mongoose with civet
# 1.1.0
- Add bin serializer
......
......@@ -4,3 +4,5 @@
the server receives the msg with the source(client pull channel) address to reply to,
checks in the hash for already connected and uses this channel to send a reply.
we can use zmqpp::socket::send_more to send source address and then the actual msg
- Test FlatBuffer as serializer for rest over zmq
\ No newline at end of file
......@@ -9,7 +9,6 @@
#include <Microservice_App.h>
#include <params/Microservice_Params.h>
#include <handlers/Microservice_BaseHandler.h>
#include <handlers/Microservice_RestHandler.h>
#include <handlers/Microservice_MonitorHandler.h>
#include <algorithm>
#include <Microservice_Client.h>
......
......@@ -273,8 +273,6 @@ namespace nsMicroservice_Iface
ILogger* pc_Logger,
IPubSub* pc_PubSub,
IMetricsFactory* p_metrics_factory) = 0;
// virtual void run() = 0;
// virtual void stop() = 0;
virtual void registerService(IServiceDiscovery* pc_ServiceDiscovery, std::string& id) = 0;
virtual const char* getType() final { return TYPE; }
};
......
......@@ -10,7 +10,8 @@
#include <stringbuffer.h>
#include <map>
#include <deque>
#include <mongoose.h>
//#include <mongoose.h>
#include <civetweb.h>
#include <stdlib.h>
#include <stringbuffer.h> //rapidjson string
......
/*
* cMicroservice_RestHandler.cpp
*
* Created on: Mar 23, 2015
* Author: amir
*/
#include <handlers/Microservice_RestHandler.h>
#include <stringbuffer.h>
#include <map>
#include <deque>
#include <mongoose.h>
#include <impl/Microservice_IRequestRestImpl.h>
#include <impl/Microservice_IResponseRestImpl.h>
#include <stringbuffer.h> //rapidjson string
#include <writer.h> //rapidjson writer
#include <document.h> //rapidjson
#include <sstream>
#include <Microservice_App.h>
#include "impl/MSIMetricsFactoryDropwisardImpl.h"
cMicroservice_RestHandler::cMicroservice_RestHandler(std::string apiContextPath,cMicroservice_BaseHandler* pc_Handler):
mpc_Handler(pc_Handler),mpc_Logger(nullptr),mpc_PubSub(nullptr),p_metrics_factory_(nullptr)
{
mpc_Buffer = new rapidjson::StringBuffer(0,nsMicroservice_Constants::MAX_JSON_BUFFER);
mpc_Writer = new JsonStringWriter(*mpc_Buffer);
mpc_RequestContext = new cMicroservice_RequestContext(this,
// mpc_Writer,
new cMicroservice_IResponseRestImpl(),
new cMicroservice_IRequestRestImpl());
this->apiContextPath = apiContextPath;
mpc_Logger = Microservice_App::GetInstance()->GetLogger();
//////// init map
crudMethodMap_[gbaa_Microservice_MethodNames[cMicroservice_Enums::eGet]] = cMicroservice_Enums::eCrudMethod::eRead;
crudMethodMap_[gbaa_Microservice_MethodNames[cMicroservice_Enums::ePost]] = cMicroservice_Enums::eCrudMethod::eCreate;
crudMethodMap_[gbaa_Microservice_MethodNames[cMicroservice_Enums::ePut]] = cMicroservice_Enums::eCrudMethod::eUpdate;
crudMethodMap_[gbaa_Microservice_MethodNames[cMicroservice_Enums::eDelete]] = cMicroservice_Enums::eCrudMethod::eDelete;
}
/**
* handling the request
* setting the request context
* getting the method and activating the adequate function
* @param conn
* @param msg the http msg object
*/
void cMicroservice_RestHandler::HandleRequest(mg_connection *conn,http_message *msg)
{
cppmetrics::core::TimerContextPtr timer;
/*
* get request context
*/
SetRequestContext(conn,msg);
/*
* Log request
*/
LogRequest(msg);
/*
* now check the method
*/
mpc_RequestContext->crudMethod = GetCrudMethod(msg);
cMicroservice_Enums::eMethod e_Method = GetMethod(msg);
if(p_metrics_factory_)
PreHandleMetrics(e_Method);
switch (e_Method)
{
case cMicroservice_Enums::eGet:
mpc_RequestContext->crudMethod = cMicroservice_Enums::eCrudMethod::eRead;
DoGet(mpc_RequestContext);
break;
case cMicroservice_Enums::ePost:
mpc_RequestContext->crudMethod = cMicroservice_Enums::eCrudMethod::eCreate;
DoPost(mpc_RequestContext);
break;
case cMicroservice_Enums::ePut:
mpc_RequestContext->crudMethod = cMicroservice_Enums::eCrudMethod::eUpdate;
DoPut(mpc_RequestContext);
break;
case cMicroservice_Enums::eDelete:
mpc_RequestContext->crudMethod = cMicroservice_Enums::eCrudMethod::eDelete;
DoDelete(mpc_RequestContext);
break;
default:
SendErrorResp(mpc_RequestContext->mpti_Response,nsMicroservice_Constants::METHOD_NOT_IMPLEMENTED);
break;
}
if(p_metrics_factory_)
PostHandleMetrics(e_Method);
}
/**
* getting the query params
* @param conn
*/
void cMicroservice_RestHandler::GetQueryParams(http_message *msg)
{
/*
* getting query parameters
*/
if (!msg->query_string.p)
return;
DequeStringMap* pc_queryParams = &mpc_RequestContext->mc_QueryParameters;
memcpy(mba_Buff,msg->query_string.p,msg->query_string.len);
mba_Buff[msg->query_string.len] = CNULL;
//strlcpy(mba_Buff, msg->query_string.p,msg->query_string.len + 1);//nsMicroservice_Constants::MAX_URI_LENGTH);
char* pba_token = strtok(mba_Buff, nsMicroservice_Constants::AND_SEPERATOR);
while (pba_token)
{
// x=y or just x
char* pba_Equal = strchr(pba_token, '=');
if (pba_Equal)
{
*pba_Equal = CNULL;
DequeStringMap::iterator t_QueryParamIter = pc_queryParams->find(pba_token);
if (t_QueryParamIter != pc_queryParams->end())
{
// existing query key >> adding to deque
t_QueryParamIter->second.push_back(pba_Equal + 1);
}
else
{
// new one
std::deque<std::string> t_QueryDeque;
t_QueryDeque.push_back(pba_Equal + 1);
(*pc_queryParams)[pba_token] = t_QueryDeque;
}
}
else
{
// insert empty deque - cannot insert null value
std::deque<std::string> t_QueryDeque;
(*pc_queryParams)[pba_token] = t_QueryDeque;
}
pba_token = strtok(NULL, nsMicroservice_Constants::AND_SEPERATOR);
}
}
/**
* - getting/setting request/response ifaces
* - getting params
* - getting query parameters
* @param mg_connection
*/
void cMicroservice_RestHandler::SetRequestContext(mg_connection *conn,http_message *msg)
{
mpc_RequestContext->Reset();
/*
* getting/setting request/response ifaces
*/
//((cMicroservice_IRequestRestImpl*)mpc_RequestContext->mpti_Request)->setConn(conn);
((cMicroservice_IRequestRestImpl*)mpc_RequestContext->mpti_Request)->SetMsg(msg);
((cMicroservice_IResponseRestImpl*)mpc_RequestContext->mpti_Response)->setConn(conn);
/*
* getting params
*/
memcpy(mba_Buff,msg->uri.p,msg->uri.len);
mba_Buff[msg->uri.len] = CNULL;
char* pba_ParamsStr = &mba_Buff[apiContextPath.length()];
char* pba_token = strtok(pba_ParamsStr,nsMicroservice_Constants::SLASH_SEPERATOR);
while(pba_token)
{
mpc_RequestContext->mc_Params.push_back(pba_token);
pba_token = strtok(NULL,nsMicroservice_Constants::SLASH_SEPERATOR);
}
/*
* getting query parameters
*/
GetQueryParams(msg);
}
void cMicroservice_RestHandler::SendErrorResp(nsMicroservice_Iface::IResponse* pti_Response,std::string error)
{
/*
* create error rest response
*/
std::ostringstream c_OutputStream;
c_OutputStream << nsMicroservice_Constants::ERROR_REST_RESPONSE_TEMPLATE_PREFIX
<< error.c_str()
<< nsMicroservice_Constants::ERROR_REST_RESPONSE_TEMPLATE_SUFFIX
<< '}';
/*
* send it
*/
//pti_Response->Send(mba_ErrorBuff);
pti_Response->Send(c_OutputStream.str().c_str());
}
void cMicroservice_RestHandler::WriteObjectToResponse(nsMicroservice_Iface::IResponse* pti_Response,rapidjson::Document& t_ObjectDoc)
{
std::ostringstream c_OutputStream;
if(!t_ObjectDoc.IsNull()) {
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
t_ObjectDoc.Accept(writer);
c_OutputStream << nsMicroservice_Constants::SUCCESS_REST_RESPONSE_TEMPLATE << buffer.GetString() << '}';
} else {
c_OutputStream << nsMicroservice_Constants::SUCCESS_NULL_REST_RESPONSE_TEMPLATE << '}';
}
pti_Response->Send(c_OutputStream.str().c_str());
// clear
//mpc_Buffer->Clear();
}
void cMicroservice_RestHandler::WriteObjectToResponse(nsMicroservice_Iface::IResponse* pti_Response,cMicroservice_BaseRestResponse& t_BaseRestResponse)
{
if(t_BaseRestResponse.IsSuccess()){
WriteObjectToResponse(pti_Response,t_BaseRestResponse.GetObjectNode());
}
else{
SendErrorResp(pti_Response,t_BaseRestResponse.GetError());
}
}
void cMicroservice_RestHandler::WriteStringToResponse(nsMicroservice_Iface::IResponse* pti_Response,const char* pba_Doc)
{
std::ostringstream c_OutputStream;
c_OutputStream << nsMicroservice_Constants::SUCCESS_REST_RESPONSE_TEMPLATE << pba_Doc << '}';
pti_Response->Send(c_OutputStream.str().c_str());
}
bool cMicroservice_RestHandler::ReadObjectFromRequest(nsMicroservice_Iface::IRequest* pti_Request,rapidjson::Document& t_ObjectDoc)
{
const char* pba_Content = pti_Request->GetContent();
if (pba_Content)
{
if (!t_ObjectDoc.Parse<0>(pba_Content).HasParseError())
return true;
}
return false;
}
/**
* resolving the http method
* @param conn
* @return
*/
cMicroservice_Enums::eMethod cMicroservice_RestHandler::GetMethod(http_message *msg)
{
/*
* now check the method
*/
cMicroservice_Enums::eMethod e_Method = cMicroservice_Enums::eMaxMethods;
for (int i = 0; i < cMicroservice_Enums::eMaxMethods; i++)
{
if (!strncmp(msg->method.p, gbaa_Microservice_MethodNames[i],msg->method.len))
{
e_Method = (cMicroservice_Enums::eMethod) (i);
break;
}
}
return e_Method;
}
void cMicroservice_RestHandler::LogRequest(http_message* msg) {
std::string str("Received request: ");
str.append(msg->method.p,msg->method.len);
str.append(", uri: ").append(msg->uri.p,msg->uri.len);
if(msg->query_string.p)
str.append(", query string: ").append(msg->query_string.p,msg->query_string.len);
mpc_Logger->debug(str);
}
void cMicroservice_RestHandler::CreateMetrics() {
std::string str;
p_get_meter_ = p_metrics_factory_->createMeter(apiContextPath.substr(1).append(".get.requests.count"));
p_post_meter_ = p_metrics_factory_->createMeter(apiContextPath.substr(1).append(".post.requests.count"));
p_put_meter_ = p_metrics_factory_->createMeter(apiContextPath.substr(1).append(".put.requests.count"));
p_delete_meter_ = p_metrics_factory_->createMeter(apiContextPath.substr(1).append(".delete.requests.count"));
p_get_timer_ = p_metrics_factory_->createTimer(apiContextPath.substr(1).append(".get.requests.timer"));
p_post_timer_ = p_metrics_factory_->createTimer(apiContextPath.substr(1).append(".post.requests.timer"));
}
void cMicroservice_RestHandler::PreHandleMetrics(cMicroservice_Enums::eMethod e_Method) {
switch(e_Method)
{
case cMicroservice_Enums::eGet:
p_get_meter_->mark();
p_get_timer_->start();
break;
case cMicroservice_Enums::ePost:
p_post_meter_->mark();
p_post_timer_->start();
break;
case cMicroservice_Enums::ePut:
p_put_meter_->mark();
break;
case cMicroservice_Enums::eDelete:
p_delete_meter_->mark();
break;
default:
break;
}
}
void cMicroservice_RestHandler::PostHandleMetrics(cMicroservice_Enums::eMethod e_Method)
{
switch(e_Method)
{
case cMicroservice_Enums::eGet:
p_get_timer_->stop();
break;
case cMicroservice_Enums::ePost:
p_post_timer_->stop();
break;
case cMicroservice_Enums::ePut:
break;
case cMicroservice_Enums::eDelete:
break;
default:
break;
}
}
eCrudMethod cMicroservice_RestHandler::GetCrudMethod(http_message *pMessage) {
return eCrudMethod::eMaxMethods;
}
/*
* Microservice_RestHandler.h
*
* Created on: Mar 23, 2015
* Author: amir
*/
#ifndef MICROSERVICE_RESTHANDLER_H_
#define MICROSERVICE_RESTHANDLER_H_
#include <common/Microservice_Defines.h>
#include <common/Microservice_Iface.h>
#include <stddef.h>
#include <writer.h>
#include <stringbuffer.h>
#include <handlers/Microservice_BaseHandler.h>
#include <Microservice_BaseRestResponse.h>
struct mg_connection;
struct http_message;
class cMicroservice_RequestContext;
class cMicroservice_RestHandler : public nsMicroservice_Iface::IContainer
{
private:
JsonStringWriter *mpc_Writer;
rapidjson::StringBuffer* mpc_Buffer;
std::string apiContextPath;
cMicroservice_BaseHandler* mpc_Handler;
nsMicroservice_Iface::ILogger* mpc_Logger;
nsMicroservice_Iface::IPubSub* mpc_PubSub;
std::map<std::string,cMicroservice_Enums::eCrudMethod> crudMethodMap_;
cMicroservice_RequestContext* mpc_RequestContext;
char mba_Buff[nsMicroservice_Constants::MAX_URI_LENGTH];
char mba_ErrorBuff[nsMicroservice_Constants::MAX_ERROR_BUFF_URI_LENGTH];
nsMicroservice_Iface::IMetricsFactory* p_metrics_factory_;
// metrics
nsMicroservice_Iface::IMetricsFactory::IMeter* p_get_meter_;
nsMicroservice_Iface::IMetricsFactory::IMeter* p_post_meter_;
nsMicroservice_Iface::IMetricsFactory::IMeter* p_put_meter_;
nsMicroservice_Iface::IMetricsFactory::IMeter* p_delete_meter_;
nsMicroservice_Iface::IMetricsFactory::ITimer* p_get_timer_;
nsMicroservice_Iface::IMetricsFactory::ITimer* p_post_timer_;
cMicroservice_Enums::eMethod GetMethod(http_message *msg);
// inlines
void DoGet(cMicroservice_RequestContext* pc_ReqCtx) { mpc_Handler->DoRead(pc_ReqCtx); }
void DoPost(cMicroservice_RequestContext* pc_ReqCtx){ mpc_Handler->DoCreate(pc_ReqCtx); }
void DoPut(cMicroservice_RequestContext* pc_ReqCtx) { mpc_Handler->DoUpdate(pc_ReqCtx); }
void DoDelete(cMicroservice_RequestContext* pc_ReqCtx){ mpc_Handler->DoDelete(pc_ReqCtx); }
/**
* prepare the request context
* @param mg_connection
* @return
*/
void SetRequestContext(mg_connection *conn,http_message *msg);
void GetQueryParams(http_message *msg);
void LogRequest(http_message *msg);
void CreateMetrics();
void PreHandleMetrics(cMicroservice_Enums::eMethod e_Method);
void PostHandleMetrics(cMicroservice_Enums::eMethod e_Method);
public:
cMicroservice_RestHandler(std::string apiContextPath,cMicroservice_BaseHandler* pc_Handler);
void withMetrics(nsMicroservice_Iface::IMetricsFactory* p_metrics_factory) {
this->p_metrics_factory_ = p_metrics_factory;
CreateMetrics();
}
void withLogger(nsMicroservice_Iface::ILogger* pc_Logger) { this->mpc_Logger = pc_Logger; }
void withPubSub(nsMicroservice_Iface::IPubSub* pc_PubSub) { this->mpc_PubSub = pc_PubSub; }
void HandleRequest(mg_connection* conn,http_message *msg);
void SendErrorResp(nsMicroservice_Iface::IResponse* pti_Response,std::string error);
void WriteObjectToResponse(nsMicroservice_Iface::IResponse* pti_Response,rapidjson::Document& t_ObjectDoc);
void WriteObjectToResponse(nsMicroservice_Iface::IResponse* pti_Response,cMicroservice_BaseRestResponse& t_BaseRestResponse);
void WriteStringToResponse(nsMicroservice_Iface::IResponse* pti_Response,const char* pba_Doc);
bool ReadObjectFromRequest(nsMicroservice_Iface::IRequest* pti_Request,rapidjson::Document& t_ObjectDoc);
// void Publish(std::string& t_Topic, std::string& t_Message) {}
// void Subscribe(std::string& t_Topic, nsMicroservice_Iface::INotifyCallback& t_NotifyHandler) {}
// void Unsubscribe(std::string& t_Topic) {}
eCrudMethod GetCrudMethod(http_message *pMessage);
};
#endif /* MICROSERVICE_RESTHANDLER_H_ */
......@@ -6,12 +6,13 @@
*/
#include <impl/Microservice_IRequestRestImpl.h>
#include <mongoose.h>
//#include <mongoose.h>
#include <civetweb.h>
#include <stdlib.h>
cMicroservice_IRequestRestImpl::cMicroservice_IRequestRestImpl():
mpt_MgMsg(nullptr),mba_BodyBuffer(nullptr)
p_reqInfo_(nullptr),mba_BodyBuffer(nullptr)
{
// TODO Auto-generated constructor stub
......@@ -24,39 +25,36 @@ cMicroservice_IRequestRestImpl::~cMicroservice_IRequestRestImpl() {
}
void cMicroservice_IRequestRestImpl::Reset() {
mpt_MgMsg = nullptr;
p_reqInfo_ = nullptr;
}
const char* cMicroservice_IRequestRestImpl::GetQueryString()
{
if (mpt_MgMsg)
return mpt_MgMsg->query_string.p;
return NULL;
if (p_reqInfo_)
return p_reqInfo_->query_string;
return nullptr;
}
const char* cMicroservice_IRequestRestImpl::GetRelativePath()
{
if (mpt_MgMsg)
return mpt_MgMsg->uri.p;
return NULL;
if (p_reqInfo_)
return p_reqInfo_->local_uri;
return nullptr;
}
const char* cMicroservice_IRequestRestImpl::GetContent()
{
if (mpt_MgMsg)
if (p_reqInfo_)
{
register auto len = mpt_MgMsg->body.len;
register auto len = p_reqInfo_->content_length;
if(len > 0)
{
mba_BodyBuffer = (char*)realloc(mba_BodyBuffer,len + 1);
memcpy(mba_BodyBuffer,mpt_MgMsg->body.p,len);
len = mg_read((mg_connection *) p_conn_, mba_BodyBuffer, len);
*(mba_BodyBuffer + len) = CNULL;
return (const char*)mba_BodyBuffer;
}
// mpt_MgMsg->body.p[mpt_MgMsg->body.len] = CNULL;
//return mpt_MgMsg->body.p;
}
return NULL;
}
......@@ -8,6 +8,7 @@
#ifndef MICROSERVICE_IREQUESTRESTIMPL_H_
#define MICROSERVICE_IREQUESTRESTIMPL_H_
#include <common/Microservice_Iface.h>
#include <civetweb.h>
struct mg_connection;
struct http_message;
......@@ -15,7 +16,8 @@ struct http_message;
class cMicroservice_IRequestRestImpl: public nsMicroservice_Iface::IRequest
{
//mg_connection *mpt_MgConn;
http_message *mpt_MgMsg;
const mg_request_info *p_reqInfo_;
const mg_connection* p_conn_;
char *mba_BodyBuffer;
public:
cMicroservice_IRequestRestImpl();
......@@ -28,7 +30,10 @@ public:
void Reset();
//void setConn(mg_connection* pt_conn) { this->mpt_MgConn = pt_conn;}
void SetMsg(http_message* mpt_MgMsg) { this->mpt_MgMsg = mpt_MgMsg; }
void SetParams(const mg_connection* p_conn,const mg_request_info *mpt_MgMsg) {
p_conn_ = p_conn;
p_reqInfo_ = mpt_MgMsg;
}
};
......
......@@ -5,8 +5,8 @@
* Author: amir
*/
#include <impl/Microservice_IResponseRestImpl.h>
#include <mongoose.h>
//#include <mongoose.h>
#include <civetweb.h>
cMicroservice_IResponseRestImpl::cMicroservice_IResponseRestImpl():
mpt_MgConn(NULL)
......
......@@ -11,23 +11,20 @@
* Created on May 3, 2016, 7:23 PM
*/
#include "Microservice_IRestServerMongooseImpl.h"
#include "../../handlers/Microservice_BaseHandler.h"
#include <mongoose.h>
#include <stdlib.h>
#include <params/Microservice_Params.h>
#include <sstream>
#include "Microservice_IRestServerCivetWebImpl.h"
#include <Microservice_BaseRestResponse.h>
#include <civetweb.h>
#include <signal.h>
#include <handlers/Microservice_RestHandler.h>
#include <handlers/Microservice_Reactor.h>
#include <impl/Microservice_IResponseRestImpl.h>
#include <impl/Microservice_IRequestRestImpl.h>
#include <utils/CommonUtils.h>
static const int POLLING_INTERVAL = 100; // IN MILLI
static const int SLEEP_INTERVAL = 1; // IN SECONDS
static int s_sig_num = 0;
void run_thread(cMicroservice_IRestServerMongooseImpl* pc_Obj)
void run_thread(cMicroservice_IRestServerCivetWebImpl* pc_Obj)
{
pc_Obj->start();
}
......@@ -37,110 +34,102 @@ static void signal_handler(int sig_num) {
s_sig_num = sig_num;
}
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
struct http_message *hm = (struct http_message *) ev_data;
struct mg_str key;
switch (ev) {
case MG_EV_HTTP_REQUEST:
((cMicroservice_IRestServerMongooseImpl*)nc->mgr->user_data)->HandleRequest(nc,hm);
break;
default:
break;
}
static int ev_handler(struct mg_connection *p_conn, void *cbdata) {
const struct mg_request_info *p_ri = mg_get_request_info(p_conn);
//((cMicroservice_IRestServerCivetWebImpl*)p_conn->ctx->user_data)->HandleRequest(p_conn,p_ri);
((cMicroservice_IRestServerCivetWebImpl*)cbdata)->HandleRequest(p_conn,p_ri);
return 1;
}
cMicroservice_IRestServerMongooseImpl::cMicroservice_IRestServerMongooseImpl(cMicroservice_RestServerParams* pc_Param)
:mpt_ServerManager(nullptr),mpc_RunThread(nullptr)
cMicroservice_IRestServerCivetWebImpl::cMicroservice_IRestServerCivetWebImpl(cMicroservice_RestServerParams* pc_Param)
:p_ctx_(nullptr),mpc_RunThread(nullptr)
{
serverType_.assign(getType());
mpc_Param = pc_Param;
// mc_HandlersMap.clear();
p_requestRestImpl_ = new cMicroservice_IRequestRestImpl();
p_restResponseImpl_ = new cMicroservice_IResponseRestImpl();
}
cMicroservice_IRestServerMongooseImpl::cMicroservice_IRestServerMongooseImpl(const cMicroservice_IRestServerMongooseImpl& orig) {
cMicroservice_IRestServerCivetWebImpl::cMicroservice_IRestServerCivetWebImpl(const cMicroservice_IRestServerCivetWebImpl& orig) {
}
cMicroservice_IRestServerMongooseImpl::~cMicroservice_IRestServerMongooseImpl() {
cMicroservice_IRestServerCivetWebImpl::~cMicroservice_IRestServerCivetWebImpl() {
}
bool cMicroservice_IRestServerMongooseImpl::build(std::string& appName,
bool cMicroservice_IRestServerCivetWebImpl::build(std::string& appName,
const std::map<std::string, nsMicroservice_Iface::IHandler*>& msHandlersMap,
nsMicroservice_Iface::ILogger* pc_Logger,
nsMicroservice_Iface::IPubSub* pc_PubSub,
nsMicroservice_Iface::IMetricsFactory* p_metrics_factory) {
bool result = false;
if (this->mpc_Param)
{
mc_AppName.assign(appName);
mpc_Logger = pc_Logger;
// create host:port
std::string str_hostport;
std::stringstream portStr;
portStr << mpc_Param->getPort();
if(mpc_Param->getHost().compare(nsMicroservice_Constants::LOCALHOST) != 0)
{
str_hostport.assign(mpc_Param->getHost());
}
str_hostport.append(":");
str_hostport.append(portStr.str());
/*
* creating the server manager object
*/
mpt_ServerManager = new mg_mgr();
mg_mgr_init(mpt_ServerManager, this); // Initialize event manager object
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
struct mg_bind_opts opts;
memset(&opts, 0, sizeof(opts));
auto conn = mg_bind(mpt_ServerManager, str_hostport.c_str(), ev_handler); // Create listening connection and add it to the event manager
if(conn)
{
mg_set_protocol_http_websocket(conn);
/*
* creating a map of rest handlers
*/
// for (auto prfxHandler : msHandlersMap)
// {
// cMicroservice_RestHandler* pc_RestHandler = new cMicroservice_RestHandler(prfxHandler.first,dynamic_cast<cMicroservice_BaseHandler*>(prfxHandler.second));
// pc_RestHandler->withLogger(pc_Logger);
// pc_RestHandler->withPubSub(pc_PubSub);
// pc_RestHandler->withMetrics(p_metrics_factory);
// //this->mc_HandlersMap[prfxHandler.first] = pc_RestHandler;
// }
result = true;
}
}
return result;
}
void cMicroservice_IRestServerMongooseImpl::registerService(nsMicroservice_Iface::IServiceDiscovery* pc_ServiceDiscovery, std::string& id) {
void cMicroservice_IRestServerCivetWebImpl::registerService(nsMicroservice_Iface::IServiceDiscovery* pc_ServiceDiscovery, std::string& id) {
if (pc_ServiceDiscovery != nullptr)
pc_ServiceDiscovery->registerService(this->mc_AppName, id, mpc_Param->getHost(), mpc_Param->getPort());
}
void cMicroservice_IRestServerMongooseImpl::run() {
void cMicroservice_IRestServerCivetWebImpl::run() {
mpc_RunThread = new std::thread(run_thread,this);
}
void cMicroservice_IRestServerMongooseImpl::start() {
void cMicroservice_IRestServerCivetWebImpl::start() {
struct mg_callbacks callbacks;
mpc_Logger->info("staring http server on: %s, port: %u",mpc_Param->getHost().c_str(),mpc_Param->getPort());
// create host:port
std::string str_hostport;
std::stringstream portStr;
portStr << mpc_Param->getPort();
if(mpc_Param->getHost().compare(nsMicroservice_Constants::LOCALHOST) != 0)
{
str_hostport.assign(mpc_Param->getHost());
str_hostport.append(":");
}
str_hostport.append(portStr.str());
/*
* init params and server context
*/
if (mpc_Param->getWorkerThreadsNum() == 0)
mpc_Param->setWorkerThreadsNum(CommonUtils::numofcpu());
memset(&callbacks, 0, sizeof(callbacks));
const char *options[] = {
"listening_ports",str_hostport.c_str(),
"enable_keep_alive","yes",
"num_threads",std::to_string(mpc_Param->getWorkerThreadsNum()).c_str()};
mg_init_library(0);
p_ctx_ = mg_start(&callbacks,this,options);
if (p_ctx_) {
mg_set_request_handler(p_ctx_, "/", ev_handler, this);
while (s_sig_num == 0) {
mg_mgr_poll(mpt_ServerManager,POLLING_INTERVAL);
// just sleep and check for exit every now and then
std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL));
}
// Cleanup, and free server instance
mg_mgr_free(mpt_ServerManager);
mg_stop(p_ctx_);
} else
std::cerr << __PRETTY_FUNCTION__ << " >> Failed to start server" << std::endl;
mg_exit_library();
}
void cMicroservice_IRestServerMongooseImpl::stop() {
void cMicroservice_IRestServerCivetWebImpl::stop() {
if(mpc_RunThread)
{
s_sig_num = 1;
......@@ -148,8 +137,8 @@ void cMicroservice_IRestServerMongooseImpl::stop() {
}
}
void cMicroservice_IRestServerMongooseImpl::HandleRequest(mg_connection* conn, http_message* msg) {
const char* pba_Uri = msg->uri.p;
void cMicroservice_IRestServerCivetWebImpl::HandleRequest(mg_connection* conn, const mg_request_info *p_reqInfo) {
const char* pba_Uri = p_reqInfo->local_uri;
if (pba_Uri[0] == '/')
{
const char* pba_NextSlash = strchr(pba_Uri + 1, '/');
......@@ -159,18 +148,10 @@ void cMicroservice_IRestServerMongooseImpl::HandleRequest(mg_connection* conn, h
std::string key(nsMicroservice_Iface::IRestServer::TYPE);
key.append(nsMicroservice_Constants::TYPE_PREFIX_SEPERATOR).append(apiContextPath);
if(p_reactor_)
HandleNewRequest(conn, key, msg, apiContextPath);
HandleNewRequest(conn, key, p_reqInfo, apiContextPath);
else
SendGeneralError(conn,500,"Missing Reactor body!");
// auto iter = mc_HandlersMap.find(key);
// if (iter != mc_HandlersMap.end())
// {
// cMicroservice_RestHandler* pc_Handler = iter->second;//mc_HandlerIterator->second;
// pc_Handler->HandleRequest(conn,msg);
// }
// else
// SendNotImplemented(conn);
}
else
SendNotImplemented(conn);
......@@ -179,33 +160,33 @@ void cMicroservice_IRestServerMongooseImpl::HandleRequest(mg_connection* conn, h
SendNotImplemented(conn);
/* Close connection for non-keep-alive requests */
mg_str* hdr;
if (mg_vcmp(&msg->proto, "HTTP/1.1") != 0 ||
((hdr = mg_get_http_header(msg, "Connection")) != NULL &&
mg_vcmp(hdr, "keep-alive") != 0)) {
conn->flags |= MG_F_SEND_AND_CLOSE;
}
// const char* hdr;
// if (CommonUtils::strcmp(p_reqInfo->http_version, HTTP_1_1) != 0 ||
// ((hdr = mg_get_header(conn, "Connection")) != nullptr &&
// CommonUtils::strcmp(hdr, "keep-alive") != 0)) {
// mg_close_connection(conn);
// //conn->flags |= MG_F_SEND_AND_CLOSE;
// }
}
void cMicroservice_IRestServerMongooseImpl::SendNotImplemented(mg_connection* conn) {
void cMicroservice_IRestServerCivetWebImpl::SendNotImplemented(mg_connection* conn) {
mg_printf(conn, "%s",
"HTTP/1.0 501 Not Implemented\r\n"
"Content-Length: 0\r\n\r\n");
}
bool cMicroservice_IRestServerMongooseImpl::init() {
bool cMicroservice_IRestServerCivetWebImpl::init() {
return true;
}
void cMicroservice_IRestServerMongooseImpl::HandleNewRequest(mg_connection *p_connection, std::string key,
http_message *p_message, std::string& apiContextPath) {
void cMicroservice_IRestServerCivetWebImpl::HandleNewRequest(mg_connection *p_connection, std::string key,
const mg_request_info *p_reqInfo, std::string& apiContextPath) {
MSRetStat retStat;
cMicroservice_RequestContext ctx(this,
p_restResponseImpl_,
p_requestRestImpl_);
retStat = ParseRequest(p_connection, p_message, ctx,apiContextPath);
retStat = ParseRequest(p_connection, p_reqInfo, ctx,apiContextPath);
if (retStat.IsSuccess())
p_reactor_->Delegate(key, &ctx);
else
......@@ -214,12 +195,12 @@ void cMicroservice_IRestServerMongooseImpl::HandleNewRequest(mg_connection *p_co
}
void
cMicroservice_IRestServerMongooseImpl::SendGeneralError(mg_connection *p_connection, int respCode, const char *error) {
cMicroservice_IRestServerCivetWebImpl::SendGeneralError(mg_connection *p_connection, int respCode, const char *error) {
mg_printf(p_connection, "HTTP/1.0 %u %s\r\nContent-Length: 0\r\n\r\n",respCode,error);
}
void
cMicroservice_IRestServerMongooseImpl::SendErrorResp(nsMicroservice_Iface::IResponse *pti_Response, std::string error) {
cMicroservice_IRestServerCivetWebImpl::SendErrorResp(nsMicroservice_Iface::IResponse *pti_Response, std::string error) {
/*
* create error rest response
*/
......@@ -235,7 +216,7 @@ cMicroservice_IRestServerMongooseImpl::SendErrorResp(nsMicroservice_Iface::IResp
pti_Response->Send(c_OutputStream.str().c_str());
}
void cMicroservice_IRestServerMongooseImpl::WriteObjectToResponse(nsMicroservice_Iface::IResponse *pti_Response,
void cMicroservice_IRestServerCivetWebImpl::WriteObjectToResponse(nsMicroservice_Iface::IResponse *pti_Response,
rapidjson::Document &t_ObjectDoc) {
std::ostringstream c_OutputStream;
......@@ -251,7 +232,7 @@ void cMicroservice_IRestServerMongooseImpl::WriteObjectToResponse(nsMicroservice
pti_Response->Send(c_OutputStream.str().c_str());
}
void cMicroservice_IRestServerMongooseImpl::WriteObjectToResponse(nsMicroservice_Iface::IResponse *pti_Response,
void cMicroservice_IRestServerCivetWebImpl::WriteObjectToResponse(nsMicroservice_Iface::IResponse *pti_Response,
cMicroservice_BaseRestResponse &t_BaseRestResponse) {
if(t_BaseRestResponse.IsSuccess()){
......@@ -262,14 +243,14 @@ void cMicroservice_IRestServerMongooseImpl::WriteObjectToResponse(nsMicroservice
}
}
void cMicroservice_IRestServerMongooseImpl::WriteStringToResponse(nsMicroservice_Iface::IResponse *pti_Response,
void cMicroservice_IRestServerCivetWebImpl::WriteStringToResponse(nsMicroservice_Iface::IResponse *pti_Response,
const char *pba_Doc) {
std::ostringstream c_OutputStream;
c_OutputStream << nsMicroservice_Constants::SUCCESS_REST_RESPONSE_TEMPLATE << pba_Doc << '}';
pti_Response->Send(c_OutputStream.str().c_str());
}
bool cMicroservice_IRestServerMongooseImpl::ReadObjectFromRequest(nsMicroservice_Iface::IRequest *pti_Request,
bool cMicroservice_IRestServerCivetWebImpl::ReadObjectFromRequest(nsMicroservice_Iface::IRequest *pti_Request,
rapidjson::Document &t_ObjectDoc) {
const char* pba_Content = pti_Request->GetContent();
if (pba_Content)
......@@ -281,8 +262,8 @@ bool cMicroservice_IRestServerMongooseImpl::ReadObjectFromRequest(nsMicroservice
}
MSRetStat
cMicroservice_IRestServerMongooseImpl::ParseRequest(mg_connection *p_conn,
http_message *p_message,
cMicroservice_IRestServerCivetWebImpl::ParseRequest(mg_connection *p_conn,
const mg_request_info *p_reqInfo,
cMicroservice_RequestContext& ctx,
std::string& apiContextPath) {
/*
......@@ -291,14 +272,16 @@ cMicroservice_IRestServerMongooseImpl::ParseRequest(mg_connection *p_conn,
/*
* getting/setting request/response ifaces
*/
((cMicroservice_IRequestRestImpl*)ctx.mpti_Request)->SetMsg(p_message);
((cMicroservice_IRequestRestImpl *) ctx.mpti_Request)->SetParams(p_conn,p_reqInfo);
((cMicroservice_IResponseRestImpl*)ctx.mpti_Response)->setConn(p_conn);
/*
* getting params
*/
memcpy(mba_Buff,p_message->uri.p,p_message->uri.len);
mba_Buff[p_message->uri.len] = CNULL;
const auto uriLen = strlen(p_reqInfo->local_uri);
memcpy(mba_Buff, p_reqInfo->local_uri,
(uriLen < nsMicroservice_Constants::MAX_URI_LENGTH) ? uriLen : nsMicroservice_Constants::MAX_URI_LENGTH - 1);
mba_Buff[uriLen] = CNULL;
char* pba_ParamsStr = &mba_Buff[apiContextPath.length()];
char* pba_token = strtok(pba_ParamsStr,nsMicroservice_Constants::SLASH_SEPERATOR);
while(pba_token)
......@@ -310,44 +293,45 @@ cMicroservice_IRestServerMongooseImpl::ParseRequest(mg_connection *p_conn,
* getting query parameters
*/
GetQueryParams(ctx, p_message);
GetQueryParams(ctx, p_reqInfo);
/*
* Log request
*/
LogRequest(p_message);
LogRequest(p_reqInfo);
/**
* get crud method
*/
ctx.crudMethod = GetCrudMethod(p_message);
ctx.crudMethod = GetCrudMethod(p_reqInfo);
return MSRetStat();
}
void cMicroservice_IRestServerMongooseImpl::LogRequest(http_message *p_msg) {
void cMicroservice_IRestServerCivetWebImpl::LogRequest(const mg_request_info *p_reqInfo) {
if (mpc_Logger->getLevel() == cMicroservice_Enums::eLogLevel::eDebug) {
std::string str("Received request: ");
str.append(p_msg->method.p, p_msg->method.len);
str.append(", uri: ").append(p_msg->uri.p, p_msg->uri.len);
if (p_msg->query_string.p)
str.append(", query string: ").append(p_msg->query_string.p, p_msg->query_string.len);
str.append(p_reqInfo->request_method);
str.append(", uri: ").append(p_reqInfo->local_uri);
if (p_reqInfo->query_string)
str.append(", query string: ").append(p_reqInfo->query_string);
mpc_Logger->debug(str);
}
}
void
cMicroservice_IRestServerMongooseImpl::GetQueryParams(cMicroservice_RequestContext &ctx, http_message *p_msg) {
cMicroservice_IRestServerCivetWebImpl::GetQueryParams(cMicroservice_RequestContext &ctx, const mg_request_info *p_reqInfo) {
/*
* getting query parameters
*/
if (!p_msg->query_string.p)
if (!p_reqInfo->query_string)
return;
DequeStringMap* pc_queryParams = &ctx.mc_QueryParameters;
memcpy(mba_Buff,p_msg->query_string.p,p_msg->query_string.len);
mba_Buff[p_msg->query_string.len] = CNULL;
//strlcpy(mba_Buff, p_msg->query_string.p,p_msg->query_string.len + 1);//nsMicroservice_Constants::MAX_URI_LENGTH);
const auto queryLen = strlen(p_reqInfo->query_string);
memcpy(mba_Buff, p_reqInfo->query_string,
(queryLen < nsMicroservice_Constants::MAX_URI_LENGTH) ? queryLen : nsMicroservice_Constants::MAX_URI_LENGTH - 1);
mba_Buff[queryLen] = CNULL;
char* pba_token = strtok(mba_Buff, nsMicroservice_Constants::AND_SEPERATOR);
while (pba_token)
......@@ -381,8 +365,8 @@ cMicroservice_IRestServerMongooseImpl::GetQueryParams(cMicroservice_RequestConte
}
}
eCrudMethod cMicroservice_IRestServerMongooseImpl::GetCrudMethod(http_message *p_msg) {
auto iter = _microservice_RestCrudMap.find(std::string(p_msg->method.p,p_msg->method.len));
eCrudMethod cMicroservice_IRestServerCivetWebImpl::GetCrudMethod(const mg_request_info *p_reqInfo) {
auto iter = _microservice_RestCrudMap.find(std::string(p_reqInfo->request_method));
if (iter != _microservice_RestCrudMap.end())
return iter->second;
return eCrudMethod::eMaxMethods;
......
......@@ -13,24 +13,28 @@
#ifndef MICROSERVICE_IRESTSERVERMONGOOSEIMPL_H
#define MICROSERVICE_IRESTSERVERMONGOOSEIMPL_H
static const char *const HTTP_1_1 = "1.1";
#include "common/Microservice_Iface.h"
#include <thread>
#include <common/Microservice_RequestContext.h>
#include "../../params/Microservice_Params.h"
struct mg_connection;
struct mg_mgr;
struct http_message;
//struct mg_mgr;
//struct http_message;
struct mg_context;
struct mg_request_info;
class cMicroservice_RestHandler;
//class cMicroservice_RestHandler;
class cMicroservice_IResponseRestImpl;
class cMicroservice_IRequestRestImpl;
class cMicroservice_IRestServerMongooseImpl : public nsMicroservice_Iface::IRestServer , public nsMicroservice_Iface::IContainer {
class cMicroservice_IRestServerCivetWebImpl : public nsMicroservice_Iface::IRestServer , public nsMicroservice_Iface::IContainer {
public:
cMicroservice_IRestServerMongooseImpl(cMicroservice_RestServerParams* pc_Param);
cMicroservice_IRestServerMongooseImpl(const cMicroservice_IRestServerMongooseImpl& orig);
virtual ~cMicroservice_IRestServerMongooseImpl();
cMicroservice_IRestServerCivetWebImpl(cMicroservice_RestServerParams* pc_Param);
cMicroservice_IRestServerCivetWebImpl(const cMicroservice_IRestServerCivetWebImpl& orig);
virtual ~cMicroservice_IRestServerCivetWebImpl();
bool build(std::string& appName, const std::map<std::string,nsMicroservice_Iface::IHandler*>& msHandlersMap,
nsMicroservice_Iface::ILogger* pc_Logger,
......@@ -45,7 +49,7 @@ public:
virtual bool init() override;
void HandleRequest(mg_connection *conn,http_message *msg);
void HandleRequest(mg_connection *conn,const mg_request_info *req_info);
void SendNotImplemented(mg_connection* conn);
virtual void SendErrorResp(nsMicroservice_Iface::IResponse *pti_Response, std::string error) override;
......@@ -63,9 +67,9 @@ public:
private:
cMicroservice_RestServerParams* mpc_Param;
//std::map<std::string,cMicroservice_RestHandler*> mc_HandlersMap;
struct mg_context *p_ctx_;
std::string mc_AppName;
mg_mgr *mpt_ServerManager;
// mg_mgr *mpt_ServerManager;
char mba_UriBuff[nsMicroservice_Constants::MAX_URI_LENGTH];
std::thread* mpc_RunThread;
nsMicroservice_Iface::ILogger* mpc_Logger;
......@@ -75,18 +79,18 @@ private:
cMicroservice_IRequestRestImpl* p_requestRestImpl_;
void HandleNewRequest(mg_connection *p_connection, std::string key,
http_message *p_message, std::string& apiContextPath);
const mg_request_info *req_info, std::string& apiContextPath);
void SendGeneralError(mg_connection *p_connection, int respCode, const char *error);
MSRetStat ParseRequest(mg_connection *p_conn,
http_message *p_message,
const mg_request_info *p_reqInfo,
cMicroservice_RequestContext& ctx,
std::string& apiContextPath);
void LogRequest(http_message* p_msg);
void LogRequest(const mg_request_info *p_reqInfo);
void GetQueryParams(cMicroservice_RequestContext &ctx, http_message *p_msg);
void GetQueryParams(cMicroservice_RequestContext &ctx, const mg_request_info *p_reqInfo);
eCrudMethod GetCrudMethod(http_message *p_msg);
eCrudMethod GetCrudMethod(const mg_request_info *p_reqInfo);
};
#endif /* MICROSERVICE_IRESTSERVERMONGOOSEIMPL_H */
......
//
// Created by amir on 28/03/17.
//
#include "CommonUtils.h"
//
// Created by amir on 28/03/17.
//
#ifndef MICROSERVICE_COMMONUTILS_H
#define MICROSERVICE_COMMONUTILS_H
#include <chrono>
#include <utility>
#include <string.h>
#include <unistd.h>
/**
* common utils
*/
class CommonUtils {
public:
/**
* measuring execution of a function
* @tparam TimeT time unit (default milliseconds)
* @param func function
* @param args function args
* @return
*/
template<typename TimeT = std::chrono::milliseconds,typename F, typename ...Args>
static typename TimeT::rep measureFunc(F&& func, Args&&... args)
{
auto start = std::chrono::steady_clock::now();
std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
auto duration = std::chrono::duration_cast< TimeT>
(std::chrono::steady_clock::now() - start);
return duration.count();
}
static int strcmp(const char *str1, const char *str2) {
size_t n2 = strlen(str2), n1 = strlen(str1);
int r = memcmp(str1, str2, (n1 < n2) ? n1 : n2);
if (r == 0) {
return n1 - n2;
}
return r;
}
static int numofcpu(){
size_t cpunum = sysconf(_SC_NPROCESSORS_ONLN);
if (cpunum == 0)
cpunum = 1;
return (int)cpunum;
}
};
#endif //MICROSERVICE_COMMONUTILS_H
......@@ -3,13 +3,13 @@
//
#include "ServerFactory.h"
#include <impl/servers/Microservice_IRestServerMongooseImpl.h>
#include <impl/servers/Microservice_IRestServerCivetWebImpl.h>
#include <impl/servers/Microservice_IMsgQueueServerZmqImpl.h>
#include <impl/servers/Microservice_IRestServerRMQImpl.h>
cMicroservice_IRestServerMongooseImpl *
ServerFactory::createIRestServerMongooseImpl(std::string host, int port, int workerThreadsNum) {
return new cMicroservice_IRestServerMongooseImpl(new cMicroservice_RestServerParams(port,host,workerThreadsNum));
cMicroservice_IRestServerCivetWebImpl *
ServerFactory::createIRestServerCivetWebImpl(std::string host, int port, int workerThreadsNum) {
return new cMicroservice_IRestServerCivetWebImpl(new cMicroservice_RestServerParams(port,host,workerThreadsNum));
}
Microservice_IMsgQueueServerZmqImpl *
......
......@@ -8,7 +8,7 @@
#include <string>
#include <params/Microservice_Params.h>
class cMicroservice_IRestServerMongooseImpl;
class cMicroservice_IRestServerCivetWebImpl;
class Microservice_IMsgQueueServerZmqImpl;
class cMicroservice_IRestServerRMQImpl;
......@@ -18,7 +18,7 @@ class cMicroservice_IRestServerRMQImpl;
class ServerFactory {
public:
static cMicroservice_IRestServerMongooseImpl* createIRestServerMongooseImpl(std::string host,
static cMicroservice_IRestServerCivetWebImpl* createIRestServerCivetWebImpl(std::string host,
int port,
int workerThreadsNum);
static Microservice_IMsgQueueServerZmqImpl* createIMsgQueueServerZmqImpl(std::string host,
......
......@@ -11,7 +11,7 @@
#include <Microservice_Client.h>
#include <params/Microservice_Params.h>
#include <document.h> //rapidjson
#include <impl/servers/Microservice_IRestServerMongooseImpl.h>
#include <impl/servers/Microservice_IRestServerCivetWebImpl.h>
#include <impl/servers/Microservice_IRestServerRMQImpl.h>
#include <impl/Microservice_ICacheClientRedisImpl.h>
#include <impl/clients/MSICommandClientHttpImpl.h>
......@@ -24,6 +24,7 @@
#include "impl/Microservices_ILoggerLog4cppImpl.h"
#include <utils/ClientFactory.h>
#include <utils/CommonUtils.h>
static const char *const PUBSUBHOST = "zmqpubsub";
......@@ -197,21 +198,67 @@ using json = nlohmann::json;
static const int ITERATIONS = 1000000;
static const char *const JSON_CONTENT = "{\n"
" \"success\": true,\n"
" \"error\": null,\n"
" \"objectNode\": {\n"
" \"success\": true,\n"
" \"error\": null,\n"
" \"objectNode\": {\n"
" \"num_results\": 6,\n"
" \"query\": \"base\",\n"
" \"results\": [\n"
" {\n"
" \"description\": null,\n"
" \"name\": \"amir/base-server-no-db\"\n"
" },\n"
" {\n"
" \"description\": null,\n"
" \"name\": \"amir/base-server-ui\"\n"
" },\n"
" {\n"
" \"description\": null,\n"
" \"name\": \"amir/base-server-db\"\n"
" },\n"
" {\n"
" \"description\": \"\",\n"
" \"name\": \"ipgallery/base-ims\"\n"
" },\n"
" {\n"
" \"description\": \"\",\n"
" \"name\": \"ipgallery/base-resin\"\n"
" },\n"
" {\n"
" \"description\": \"\",\n"
" \"name\": \"ipgallery/base-microservice-java\"\n"
" }\n"
" ]\n"
" }\n"
" }\n"
"}";
static const char *const SOURCE_CHANNEL = "ipc:///tmp/some-file.ipc";
static const char *const URI = "/xxx/resource/subResource";
static const char *const QUERY_STRING = "a=b&c=d&abba=sabba";
void testRapidJson() {
for (int i = 0; i < ITERATIONS; i++) {
std::string json;
rapidjson::Document rpj_Doc; // Null
rapidjson::Document::AllocatorType &rpj_Alloc = rpj_Doc.GetAllocator();
rpj_Doc.SetObject();
rpj_Doc.AddMember(rapidjson::StringRef("hello"), rapidjson::StringRef("world"), rpj_Alloc);
rpj_Doc.AddMember(rapidjson::StringRef("number"), rapidjson::Value(i), rpj_Alloc);
rpj_Doc.AddMember(rapidjson::StringRef("status"), true, rpj_Alloc);
rpj_Doc.AddMember(rapidjson::StringRef("hello1"), rapidjson::StringRef("world"), rpj_Alloc);
rpj_Doc.AddMember(rapidjson::StringRef("number1"), rapidjson::Value(i), rpj_Alloc);
rpj_Doc.AddMember(rapidjson::StringRef("status1"), true, rpj_Alloc);
rpj_Doc.AddMember(rapidjson::StringRef("hello2"), rapidjson::StringRef("world"), rpj_Alloc);
rpj_Doc.AddMember(rapidjson::StringRef("number2"), rapidjson::Value(i), rpj_Alloc);
rpj_Doc.AddMember(rapidjson::StringRef("status2"), true, rpj_Alloc);
rpj_Doc.AddMember(rapidjson::StringRef("source"), rapidjson::StringRef(SOURCE_CHANNEL), rpj_Alloc);
//rpj_Doc.AddMember(rapidjson::StringRef("uri"), rapidjson::Value(i), rpj_Alloc);
//rpj_Doc.AddMember(rapidjson::StringRef("status"), true, rpj_Alloc);
rpj_Doc.AddMember(rapidjson::StringRef("uri"), rapidjson::StringRef(URI), rpj_Alloc);
//rpj_Doc.AddMember(rapidjson::StringRef("number1"), rapidjson::Value(i), rpj_Alloc);
//rpj_Doc.AddMember(rapidjson::StringRef("status1"), true, rpj_Alloc);
rpj_Doc.AddMember(rapidjson::StringRef("queryString"), rapidjson::StringRef(QUERY_STRING), rpj_Alloc);
rpj_Doc.AddMember(rapidjson::StringRef("content"), rapidjson::StringRef(JSON_CONTENT), rpj_Alloc);
// rpj_Doc.AddMember(rapidjson::StringRef("number2"), rapidjson::Value(i), rpj_Alloc);
// rpj_Doc.AddMember(rapidjson::StringRef("status2"), true, rpj_Alloc);
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
rpj_Doc.Accept(writer);
......@@ -223,31 +270,53 @@ void testNlohmanJson() {
for (int i = 0; i < ITERATIONS; i++) {
std::string jsonStr;
json j;
j.emplace("hello","world");
j.emplace("number", i);
j.emplace("status",true);
j["hello1"] = "world";
j["number1"] = i;
j["status1"] = true;
j.emplace("hello2","world");
j.emplace("number2", i);
j.emplace("status2",true);
j.emplace("source",SOURCE_CHANNEL);
j.emplace("uri", URI);
j.emplace("queryString",QUERY_STRING);
j["content"] = JSON_CONTENT;
jsonStr = j.dump();
}
}
#define MAKE_STRING_PAIR(s1,s2) std::make_pair<std::string,std::string>(s1,s2)
void testSerializations() {
using ParamsMap = std::map<std::string, std::string>;
ParamsMap paramsMap;
const char* strBuff;
for (int i = 0; i < ITERATIONS; i++) {
paramsMap.emplace(MAKE_STRING_PAIR("source",SOURCE_CHANNEL));
paramsMap.emplace(MAKE_STRING_PAIR("uri",URI));
paramsMap.emplace(MAKE_STRING_PAIR("queryString",QUERY_STRING));
paramsMap.emplace(MAKE_STRING_PAIR("content",JSON_CONTENT));
rapidjson::Document doc; // Null
rapidjson::Document::AllocatorType &allocator = doc.GetAllocator();
doc.SetObject();
for (auto& pair : paramsMap)
doc.AddMember(
rapidjson::StringRef(pair.first.c_str()),
rapidjson::StringRef(pair.second.c_str()),
allocator);
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
doc.Accept(writer);
strBuff = buffer.GetString();
}
}
void testJsons()
{
std::time_t now = std::time(nullptr);
testRapidJson();
std::cout <<" Testing " << ITERATIONS << " with rapid json took: " << std::time(nullptr) - now << "msec" << '\n';
std::cout <<" Testing " << ITERATIONS << " with map serialization json took: " << CommonUtils::measureFunc<>(testSerializations) << "msec" << '\n';
std::cout <<" Testing " << ITERATIONS << " with rapid json took: " << CommonUtils::measureFunc<>(testRapidJson) << "msec" << '\n';
if( false or not true){
}
// test json-nlohman
now = std::time(nullptr);
testNlohmanJson();
std::cout <<" Testing " << ITERATIONS << " with nlohman json took: " << std::time(nullptr) - now << "msec" << '\n';
std::cout <<" Testing " << ITERATIONS << " with nlohman json took: " << CommonUtils::measureFunc<>(testNlohmanJson) << "msec" << '\n';
}
......
......@@ -11,7 +11,7 @@
#include <Microservice_Client.h>
#include <params/Microservice_Params.h>
#include <document.h> //rapidjson
#include <impl/servers/Microservice_IRestServerMongooseImpl.h>
#include <impl/servers/Microservice_IRestServerCivetWebImpl.h>
#include <impl/servers/Microservice_IMsgQueueServerZmqImpl.h>
#include <impl/servers/Microservice_IRestServerRMQImpl.h>
#include <impl/Microservice_ICacheClientRedisImpl.h>
......@@ -101,8 +101,8 @@ public:
rpj_Doc.AddMember(rapidjson::StringRef(it->first.c_str()),rapidjson::StringRef(dequeIt->c_str()),rpj_Alloc);
}
}
ReadSync(pc_reqCtx);
//ReadAsync2(pc_reqCtx);
// ReadSync(pc_reqCtx);
ReadAsync2(pc_reqCtx);
//this->WriteObjectToResponse(pc_reqCtx,rpj_Doc);
// add metric
long value = rand() % 1000 + 1;
......@@ -302,7 +302,7 @@ void runNewMS(){
.addClient(ClientFactory::createHttpImplMsClient("other-service", "localhost", 32010, true, 10, false,"localhost:6379")) //new cMicroservice_Client(new MSICommandClientHttpImpl(),&clientParams))
.addClient(ClientFactory::createZmqMsgQImp("zmq-service", msApp.name(), 0,
Microservice_ZMQServerParams::eProtocol::eIpc))
.addServer(ServerFactory::createIRestServerMongooseImpl("", 50010, 1))// .addRestServer(new cMicroservice_IRestServerMongooseImpl(new cMicroservice_RestServerParams(50010,"",1)))
.addServer(ServerFactory::createIRestServerCivetWebImpl("", 50010, 1))// .addRestServer(new cMicroservice_IRestServerCivetWebImpl(new cMicroservice_RestServerParams(50010,"",1)))
.addServer(ServerFactory::createIMsgQueueServerZmqImpl(msApp.name(), 0, Microservice_ZMQServerParams::eProtocol::eIpc))
.addHandler("/xxx",(cMicroservice_BaseHandler*)new cMicroserviceHandler("hello"))
.addHandler("/zmq",new MSMsgQHandler())
......
......@@ -8,6 +8,7 @@
#include <iostream>
#include <common/Microservice_MsgQContext.h>
#include <thread>
#include <utils/CommonUtils.h>
static const char *const IPC_FILE1 = "/tmp/service-name1.ipc";
static const char *const IPC_FILE2 = "/tmp/service-name2.ipc";
......@@ -239,7 +240,9 @@ void test_pubsub(zmqpp::context &context) {
int main(int argc, char *argv[]) {
zmqpp::context context;
std::cout << "testing of " << ITERATIONS << " iterations took: " << measure<>::execution(testRequestResponse,context) << " msec" << std::endl;
// std::cout << "testing of " << ITERATIONS << " iterations took: " << measure<>::execution(testRequestResponse,context) << " msec" << std::endl;
std::cout << "testing of " << ITERATIONS << " iterations took: " << CommonUtils::measureFunc<>(testRequestResponse,context) << " msec" << std::endl;
//testRequestResponse(context);
//test_pubsub(context);
//test_Cereal();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment