Commit 553b93d0 by amir

- setting false on seterror in cMicroservice_BaseRestResponse

- fix error resp format
- change rmq-handler to support async operations
parent 2ccf5855
cmake_minimum_required(VERSION 2.8.12)
project(Microservice)
# version stuff
set (Microservice_VERSION_MAJOR 0)
set (Microservice_VERSION_MAJOR 1)
set (Microservice_VERSION_MINOR 3)
set (Microservice_VERSION_PATCH 0)
set(Microservice_VERSION_STRING ${Microservice_VERSION_MAJOR}.${Microservice_VERSION_MINOR}.${Microservice_VERSION_PATCH})
......
## C++ Microservice Framework
## VERSIONS:
# 0.3.1
- setting false on seterror in cMicroservice_BaseRestResponse
- fix error resp format
- change rmq-handler to support async operations
# 0.3.0
- Adding RestResponse that can return the headers and status code of the response
check the ReadSync in the Test file
......
......@@ -27,6 +27,7 @@ public:
virtual ~cMicroservice_BaseRestResponse() {}
void SetError(std::string& error) {
mb_Success = false;
this->mc_Error = error;
}
......
......@@ -35,7 +35,9 @@ namespace nsMicroservice_Constants
static const char* FAILED_TO_GET_PARAMS = "failed to get params";
static const char* JSON_NULL_VALUE = "null";
static const char* SUCCESS_REST_RESPONSE_TEMPLATE = "{ \"success\": true, \"error\": null, \"objectNode\": ";
static const char* ERROR_REST_RESPONSE_TEMPLATE = "{ \"success\": false, \"error\": \"%s\", \"objectNode\": null }";
static const char* SUCCESS_NULL_REST_RESPONSE_TEMPLATE = "{ \"success\": true, \"error\": null, \"objectNode\": null ";
static const char* ERROR_REST_RESPONSE_TEMPLATE_PREFIX = "{ \"success\": false, \"error\": \"";
static const char* ERROR_REST_RESPONSE_TEMPLATE_SUFFIX = "\", \"objectNode\": null ";
static const char* COMMAND_ERROR = "Command Error: ";
static const char* MON_PREFIX = "/_mon";
static const char* LOG_FILE_PATH = "/var/log/mcx/msApp.log";
......
......@@ -155,24 +155,45 @@ void cMicroservice_RMQHandler::SendErrorResp(nsMicroservice_Iface::IResponse* pt
/*
* create error rest response
*/
snprintf(mba_ErrorBuff,
nsMicroservice_Constants::MAX_ERROR_BUFF_URI_LENGTH,
nsMicroservice_Constants::ERROR_REST_RESPONSE_TEMPLATE,
error.c_str());
// snprintf(mba_ErrorBuff,
// nsMicroservice_Constants::MAX_ERROR_BUFF_URI_LENGTH,
// nsMicroservice_Constants::ERROR_REST_RESPONSE_TEMPLATE,
// error.c_str());
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());
// pti_Response->Send(mba_ErrorBuff);
}
void cMicroservice_RMQHandler::WriteObjectToResponse(nsMicroservice_Iface::IResponse* pti_Response,rapidjson::Document& t_ObjectDoc)
{
std::ostringstream c_OutputStream;
t_ObjectDoc.Accept(*this->mpc_Writer);
c_OutputStream << nsMicroservice_Constants::SUCCESS_REST_RESPONSE_TEMPLATE << mpc_Buffer->GetString() << '}';
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();
// std::ostringstream c_OutputStream;
// t_ObjectDoc.Accept(*this->mpc_Writer);
// c_OutputStream << nsMicroservice_Constants::SUCCESS_REST_RESPONSE_TEMPLATE << mpc_Buffer->GetString() << '}';
// pti_Response->Send(c_OutputStream.str().c_str());
// // clear
// mpc_Buffer->Clear();
}
void cMicroservice_RMQHandler::WriteObjectToResponse(nsMicroservice_Iface::IResponse* pti_Response,cMicroservice_BaseRestResponse& t_BaseRestResponse)
......
......@@ -21,16 +21,16 @@
#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_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 = pc_Handler->GetLogger();
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 = pc_Handler->GetLogger();
}
/**
......@@ -43,43 +43,43 @@ mpc_Handler(pc_Handler),mpc_Logger(nullptr),mpc_PubSub(nullptr),p_metrics_factor
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
*/
cMicroservice_Enums::eMethod e_Method = GetMethod(msg);
if(p_metrics_factory_)
PreHandleMetrics(e_Method);
switch (e_Method)
{
case cMicroservice_Enums::eGet:
DoGet(mpc_RequestContext);
break;
case cMicroservice_Enums::ePost:
DoPost(mpc_RequestContext);
break;
case cMicroservice_Enums::ePut:
DoPut(mpc_RequestContext);
break;
case cMicroservice_Enums::eDelete:
DoDelete(mpc_RequestContext);
break;
default:
SendErrorResp(mpc_RequestContext->mpti_Response,nsMicroservice_Constants::METHOD_NOT_IMPLEMENTED);
break;
}
if(p_metrics_factory_)
PostHandleMetrics(e_Method);
/*
* get request context
*/
SetRequestContext(conn,msg);
/*
* Log request
*/
LogRequest(msg);
/*
* now check the method
*/
cMicroservice_Enums::eMethod e_Method = GetMethod(msg);
if(p_metrics_factory_)
PreHandleMetrics(e_Method);
switch (e_Method)
{
case cMicroservice_Enums::eGet:
DoGet(mpc_RequestContext);
break;
case cMicroservice_Enums::ePost:
DoPost(mpc_RequestContext);
break;
case cMicroservice_Enums::ePut:
DoPut(mpc_RequestContext);
break;
case cMicroservice_Enums::eDelete:
DoDelete(mpc_RequestContext);
break;
default:
SendErrorResp(mpc_RequestContext->mpti_Response,nsMicroservice_Constants::METHOD_NOT_IMPLEMENTED);
break;
}
if(p_metrics_factory_)
PostHandleMetrics(e_Method);
}
/**
......@@ -88,47 +88,47 @@ void cMicroservice_RestHandler::HandleRequest(mg_connection *conn,http_message *
*/
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
/*
* 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)
{
// insert empty deque - cannot insert null value
std::deque<std::string> t_QueryDeque;
(*pc_queryParams)[pba_token] = t_QueryDeque;
// 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);
}
pba_token = strtok(NULL, nsMicroservice_Constants::AND_SEPERATOR);
}
}
/**
......@@ -139,93 +139,95 @@ void cMicroservice_RestHandler::GetQueryParams(http_message *msg)
*/
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);
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
*/
// snprintf(mba_ErrorBuff,
// nsMicroservice_Constants::MAX_ERROR_BUFF_URI_LENGTH,
// nsMicroservice_Constants::ERROR_REST_RESPONSE_TEMPLATE,
// error.c_str());
/*
* create error rest response
*/
std::ostringstream c_OutputStream;
c_OutputStream << nsMicroservice_Constants::ERROR_REST_RESPONSE_TEMPLATE << error.c_str() << '}';
/*
* send it
*/
//pti_Response->Send(mba_ErrorBuff);
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;
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
std::ostringstream c_OutputStream;
// t_ObjectDoc.Accept(*this->mpc_Writer);
// c_OutputStream << nsMicroservice_Constants::SUCCESS_REST_RESPONSE_TEMPLATE << mpc_Buffer->GetString() << '}';
t_ObjectDoc.Accept(writer);
c_OutputStream << nsMicroservice_Constants::SUCCESS_REST_RESPONSE_TEMPLATE << buffer.GetString() << '}';
pti_Response->Send(c_OutputStream.str().c_str());
// clear
//mpc_Buffer->Clear();
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());
}
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());
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;
const char* pba_Content = pti_Request->GetContent();
if (pba_Content)
{
if (!t_ObjectDoc.Parse<0>(pba_Content).HasParseError())
return true;
}
return false;
}
......@@ -236,19 +238,19 @@ bool cMicroservice_RestHandler::ReadObjectFromRequest(nsMicroservice_Iface::IReq
*/
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))
/*
* now check the method
*/
cMicroservice_Enums::eMethod e_Method = cMicroservice_Enums::eMaxMethods;
for (int i = 0; i < cMicroservice_Enums::eMaxMethods; i++)
{
e_Method = (cMicroservice_Enums::eMethod) (i);
break;
if (!strncmp(msg->method.p, gbaa_Microservice_MethodNames[i],msg->method.len))
{
e_Method = (cMicroservice_Enums::eMethod) (i);
break;
}
}
}
return e_Method;
return e_Method;
}
void cMicroservice_RestHandler::LogRequest(http_message* msg) {
......@@ -294,7 +296,7 @@ void cMicroservice_RestHandler::PreHandleMetrics(cMicroservice_Enums::eMethod e_
}
}
void cMicroservice_RestHandler::PostHandleMetrics(cMicroservice_Enums::eMethod e_Method)
void cMicroservice_RestHandler::PostHandleMetrics(cMicroservice_Enums::eMethod e_Method)
{
switch(e_Method)
{
......@@ -305,10 +307,10 @@ void cMicroservice_RestHandler::PostHandleMetrics(cMicroservice_Enums::eMethod e
p_post_timer_->stop();
break;
case cMicroservice_Enums::ePut:
break;
case cMicroservice_Enums::eDelete:
break;
default:
break;
......
......@@ -90,24 +90,9 @@ void MSICommandClientHttpImpl::HandleCommand(HttpCommandDataPtr& cmdDataPtr){
if(BuildUrl(cmdDataPtr->p_cmd_params,url))
{
cmdDataPtr->p_response->Reset();
http_client client(url);
//config.set_timeout<std::chrono::seconds>(std::chrono::seconds(2));
http_request request(*cmdDataPtr->p_mtd);
// headers
request.headers().add(header_names::accept,"*/*");
auto& headers = cmdDataPtr->p_cmd_params->GetHeadersMap();
if (!headers.empty()){
for (auto header : headers){
request.headers().add(header.first,header.second);
}
}
// content
if(!cmdDataPtr->p_cmd_params->GetContent().empty())
request.set_body(cmdDataPtr->p_cmd_params->GetContent(),"application/json");
pplx::task<http_response> request_task = createRequestTask(cmdDataPtr, url);
//auto request_task = client.request(*cmdDataPtr->p_mtd);
auto request_task = client.request(request);
if(cmdDataPtr->p_cmd_params->IsAsync_())
{
request_task.then([this,cmdDataPtr](http_response resp){
......@@ -180,6 +165,39 @@ void MSICommandClientHttpImpl::HandleCommand(HttpCommandDataPtr& cmdDataPtr){
}
}
/**
* creating the request task
* adding all the cmd data params
* @param cmdDataPtr
* @param url
* @return request task to perform
*/
pplx::task<http_response>
MSICommandClientHttpImpl::createRequestTask(const MSICommandClientHttpImpl::HttpCommandDataPtr &cmdDataPtr,
const std::string &url) const {
http_client client(url);
//config.set_timeout<std::chrono::seconds>(std::chrono::seconds(2));
http_request request(*cmdDataPtr->p_mtd);
// http_client_config config = client.client_config();
// config.set_timeout<std::chrono::seconds>(std::chrono::seconds(2));
// headers
request.headers().add(header_names::accept, "*/*");
auto& headers = cmdDataPtr->p_cmd_params->GetHeadersMap();
if (!headers.empty()){
for (auto header : headers){
request.headers().add(header.first,header.second);
}
}
// content
if(!cmdDataPtr->p_cmd_params->GetContent().empty())
request.set_body(cmdDataPtr->p_cmd_params->GetContent(),"application/json");
//auto request_task = client.request(*cmdDataPtr->p_mtd);
//auto request_task =
return client.request(request);//request_task;
}
MSRetStat MSICommandClientHttpImpl::Create(MSCommandParams* p_cmd_params, cMicroservice_BaseRestResponse* p_response) {
MSRetStat retstat;
auto cmd_data = std::make_shared<HandleCommandData>(HandleCommandData(p_cmd_params,p_response,&(methods::POST),&retstat,&create_counters_));
......
......@@ -91,6 +91,8 @@ private:
CommandCounters& cmd_counters);
void DelegateRestResponse(cMicroservice_BaseRestResponse *pResponse, web::http::http_response &response);
pplx::task<web::http::http_response> createRequestTask(const HttpCommandDataPtr &cmdDataPtr, const std::string &url) const;
};
......
......@@ -232,10 +232,30 @@ void to_func()
class TO
{
public:
TO() {
std::cout << __PRETTY_FUNCTION__ << '\n';
}
void to_member_func() {
std::cout << " member boring function" << std::endl;
}
};
TO testDocs()
{
cMicroservice_BaseRestResponse resp;
if (resp.GetObjectNode().IsNull()) { std::cout << "empty\n"; }
rapidjson::Document& rpj_Doc = resp.GetObjectNode();
rapidjson::Document::AllocatorType& rpj_Alloc = rpj_Doc.GetAllocator();
rpj_Doc.SetObject();
if (resp.GetObjectNode().IsNull()) { std::cout << "empty\n"; }
TO to;
return to;
}
void test_timers()
{
TO toA;
......@@ -264,6 +284,7 @@ int main(int argc, char *argv[])
{
// testCache();
TO to2 = testDocs();
// test_timers();
runNewMS();
......
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