Commit 8299f380 authored by Pavel Vainerman's avatar Pavel Vainerman

(LogDB): заложил http-сервер.

parent 13ac8507
...@@ -40,7 +40,7 @@ LogDB::LogDB( const string& name , const string& prefix ): ...@@ -40,7 +40,7 @@ LogDB::LogDB( const string& name , const string& prefix ):
auto conf = uniset_conf(); auto conf = uniset_conf();
auto xml = conf->getConfXML(); auto xml = conf->getConfXML();
conf->initLogStream(dblog, prefix + "-log" ); conf->initLogStream(dblog, prefix + "log" );
xmlNode* cnode = conf->findNode(xml->getFirstNode(), "LogDB", name); xmlNode* cnode = conf->findNode(xml->getFirstNode(), "LogDB", name);
...@@ -54,7 +54,7 @@ LogDB::LogDB( const string& name , const string& prefix ): ...@@ -54,7 +54,7 @@ LogDB::LogDB( const string& name , const string& prefix ):
UniXML::iterator it(cnode); UniXML::iterator it(cnode);
qbufSize = conf->getArgPInt("--" + prefix + "-buffer-size", it.getProp("bufferSize"), qbufSize); qbufSize = conf->getArgPInt("--" + prefix + "buffer-size", it.getProp("bufferSize"), qbufSize);
tmConnection_sec = tmConnection_msec / 1000.; tmConnection_sec = tmConnection_msec / 1000.;
...@@ -128,7 +128,7 @@ LogDB::LogDB( const string& name , const string& prefix ): ...@@ -128,7 +128,7 @@ LogDB::LogDB( const string& name , const string& prefix ):
} }
std::string dbfile = conf->getArgParam("--" + prefix + "-dbfile", it.getProp("dbfile")); std::string dbfile = conf->getArgParam("--" + prefix + "dbfile", it.getProp("dbfile"));
if( dbfile.empty() ) if( dbfile.empty() )
{ {
...@@ -149,10 +149,40 @@ LogDB::LogDB( const string& name , const string& prefix ): ...@@ -149,10 +149,40 @@ LogDB::LogDB( const string& name , const string& prefix ):
dbcrit << err.str() << endl; dbcrit << err.str() << endl;
throw uniset::SystemError(err.str()); throw uniset::SystemError(err.str());
} }
#ifndef DISABLE_REST_API
httpHost = conf->getArgParam("--" + prefix + "httpserver-host", "localhost");
httpPort = conf->getArgInt("--" + prefix + "httpserver-port", "8080");
dblog1 << myname << "(init): http server parameters " << httpHost << ":" << httpPort << endl;
Poco::Net::SocketAddress sa(httpHost, httpPort);
try
{
/*! \FIXME: доделать конфигурирование параметров */
Poco::Net::HTTPServerParams* httpParams = new Poco::Net::HTTPServerParams;
httpParams->setMaxQueued(100);
httpParams->setMaxThreads(1);
httpserv = std::make_shared<Poco::Net::HTTPServer>(this, Poco::Net::ServerSocket(sa), httpParams );
}
catch( std::exception& ex )
{
std::stringstream err;
err << myname << "(init): " << httpHost << ":" << httpPort << " ERROR: " << ex.what();
throw uniset::SystemError(err.str());
}
#endif
} }
//-------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------
LogDB::~LogDB() LogDB::~LogDB()
{ {
if( evIsActive() )
evstop();
if( httpserv )
httpserv->stop();
if( db ) if( db )
db->close(); db->close();
} }
...@@ -186,16 +216,17 @@ void LogDB::addLog( LogDB::Log* log, const string& txt ) ...@@ -186,16 +216,17 @@ void LogDB::addLog( LogDB::Log* log, const string& txt )
qbuf.emplace(q.str()); qbuf.emplace(q.str());
} }
//-------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------
std::shared_ptr<LogDB> LogDB::init_logdb( int argc, const char* const* argv, const std::string& prefix ) std::shared_ptr<LogDB> LogDB::init_logdb( int argc, const char* const* argv, const std::string& prefix )
{ {
auto conf = uniset_conf(); auto conf = uniset_conf();
string name = conf->getArgParam("--" + prefix + "-name", ""); string name = conf->getArgParam("--" + prefix + "name", "");
if( name.empty() ) if( name.empty() )
{ {
cerr << "(LogDB): Unknown name. Use --" << prefix << "-name" << endl; cerr << "(LogDB): Unknown name. Use --" << prefix << "name" << endl;
return nullptr; return nullptr;
} }
...@@ -211,6 +242,9 @@ void LogDB::help_print() ...@@ -211,6 +242,9 @@ void LogDB::help_print()
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void LogDB::run( bool async ) void LogDB::run( bool async )
{ {
if( httpserv )
httpserv->start();
if( async ) if( async )
async_evrun(); async_evrun();
else else
...@@ -374,7 +408,7 @@ void LogDB::Log::read( ev::io& watcher ) ...@@ -374,7 +408,7 @@ void LogDB::Log::read( ev::io& watcher )
tcp->receiveBytes(buf, n); tcp->receiveBytes(buf, n);
// нарезаем на строки // нарезаем на строки
for( size_t i = 0; i < n; i++ ) for( int i = 0; i < n; i++ )
{ {
if( buf[i] != '\n' ) if( buf[i] != '\n' )
text += buf[i]; text += buf[i];
...@@ -456,3 +490,165 @@ void LogDB::Log::close() ...@@ -456,3 +490,165 @@ void LogDB::Log::close()
//tcp = nullptr; //tcp = nullptr;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#ifndef DISABLE_REST_API
// -----------------------------------------------------------------------------
class LogDBRequestHandler:
public Poco::Net::HTTPRequestHandler
{
public:
LogDBRequestHandler( LogDB* l ): logdb(l) {}
virtual void handleRequest( Poco::Net::HTTPServerRequest& request,
Poco::Net::HTTPServerResponse& response ) override
{
logdb->handleRequest(request, response);
}
private:
LogDB* logdb;
};
// -----------------------------------------------------------------------------
Poco::Net::HTTPRequestHandler* LogDB::createRequestHandler( const Poco::Net::HTTPServerRequest& req )
{
return new LogDBRequestHandler(this);
}
// -----------------------------------------------------------------------------
void LogDB::handleRequest( Poco::Net::HTTPServerRequest& req, Poco::Net::HTTPServerResponse& resp )
{
dbinfo << myname << "(handleRequest): ...." << endl;
using Poco::Net::HTTPResponse;
// std::ostream& out = resp.send();
try
{
respError(resp, HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, "Unknown request");
}
catch( std::exception& ex )
{
dbcrit << myname << "(handleRequest): request error: " << ex.what() << endl;
respError(resp, HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, ex.what());
}
#if 0
// В этой версии API поддерживается только GET
if( req.getMethod() != "GET" )
{
resp.setStatus(HTTPResponse::HTTP_BAD_REQUEST);
resp.setContentType("text/json");
std::ostream& out = resp.send();
Poco::JSON::Object jdata;
jdata.set("error", resp.getReasonForStatus(resp.getStatus()));
jdata.set("ecode", (int)resp.getStatus());
jdata.set("message", "method must be 'GET'");
jdata.stringify(out);
out.flush();
return;
}
Poco::URI uri(req.getURI());
if( log->is_info() )
log->info() << req.getHost() << ": query: " << uri.getQuery() << endl;
std::vector<std::string> seg;
uri.getPathSegments(seg);
// example: http://host:port/api/version/ObjectName
if( seg.size() < 3
|| seg[0] != "api"
|| seg[1] != UHTTP_API_VERSION
|| seg[2].empty() )
{
resp.setStatus(HTTPResponse::HTTP_BAD_REQUEST);
resp.setContentType("text/json");
std::ostream& out = resp.send();
Poco::JSON::Object jdata;
jdata.set("error", resp.getReasonForStatus(resp.getStatus()));
jdata.set("ecode", (int)resp.getStatus());
jdata.set("message", "BAD REQUEST STRUCTURE");
jdata.stringify(out);
out.flush();
return;
}
const std::string objectName(seg[2]);
auto qp = uri.getQueryParameters();
resp.setStatus(HTTPResponse::HTTP_OK);
resp.setContentType("text/json");
std::ostream& out = resp.send();
try
{
if( objectName == "help" )
{
out << "{ \"help\": ["
"{\"help\": {\"desc\": \"this help\"}},"
"{\"list\": {\"desc\": \"list of objects\"}},"
"{\"ObjectName\": {\"desc\": \"ObjectName information\"}},"
"{\"ObjectName/help\": {\"desc\": \"help for ObjectName\"}},"
"{\"apidocs\": {\"desc\": \"https://github.com/Etersoft/uniset2\"}}"
"]}";
}
else if( objectName == "list" )
{
auto json = registry->httpGetObjectsList(qp);
json->stringify(out);
}
else if( seg.size() == 4 && seg[3] == "help" ) // /api/version/ObjectName/help
{
auto json = registry->httpHelpByName(objectName, qp);
json->stringify(out);
}
else if( seg.size() >= 4 ) // /api/version/ObjectName/xxx..
{
auto json = registry->httpRequestByName(objectName, seg[3], qp);
json->stringify(out);
}
else
{
auto json = registry->httpGetByName(objectName, qp);
json->stringify(out);
}
}
// catch( Poco::JSON::JSONException jsone )
// {
// std::cout << "JSON ERROR: " << jsone.message() << std::endl;
// }
catch( std::exception& ex )
{
ostringstream err;
err << ex.what();
resp.setStatus(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
resp.setContentType("text/json");
Poco::JSON::Object jdata;
jdata.set("error", err.str());
jdata.set("ecode", (int)resp.getStatus());
jdata.stringify(out);
}
out.flush();
#endif
}
// -----------------------------------------------------------------------------
void LogDB::respError( Poco::Net::HTTPServerResponse& resp,
Poco::Net::HTTPResponse::HTTPStatus estatus,
const string& message )
{
resp.setStatus(estatus);
resp.setContentType("text/json");
std::ostream& out = resp.send();
Poco::JSON::Object::Ptr jdata = new Poco::JSON::Object();
jdata->set("error", resp.getReasonForStatus(resp.getStatus()));
jdata->set("ecode", (int)resp.getStatus());
jdata->set("message", message);
jdata->stringify(out);
out.flush();
}
// -----------------------------------------------------------------------------
#endif
// -----------------------------------------------------------------------------
...@@ -64,6 +64,10 @@ namespace uniset ...@@ -64,6 +64,10 @@ namespace uniset
\section sec_LogDB_REST LogDB REST API \section sec_LogDB_REST LogDB REST API
LogDB предоставляет возможность получения логов через REST API. Для этого запускается
http-сервер. Параметры запуска можно указать при помощи:
--prefix-httpserver-host и --prefix-httpserver-port.
\todo Добавить настройки таймаутов, размера буфера, размера для резервирования под строку,... \todo Добавить настройки таймаутов, размера буфера, размера для резервирования под строку,...
\todo Реализовать посылку команд \todo Реализовать посылку команд
...@@ -73,13 +77,17 @@ namespace uniset ...@@ -73,13 +77,17 @@ namespace uniset
*/ */
class LogDB: class LogDB:
public EventLoopServer public EventLoopServer
#ifndef DISABLE_REST_API
, public Poco::Net::HTTPRequestHandler
, public Poco::Net::HTTPRequestHandlerFactory
#endif
{ {
public: public:
LogDB( const std::string& name, const std::string& prefix = "" ); LogDB( const std::string& name, const std::string& prefix = "" );
virtual ~LogDB(); virtual ~LogDB();
/*! глобальная функция для инициализации объекта */ /*! глобальная функция для инициализации объекта */
static std::shared_ptr<LogDB> init_logdb( int argc, const char* const* argv, const std::string& prefix = "logdb" ); static std::shared_ptr<LogDB> init_logdb( int argc, const char* const* argv, const std::string& prefix = "logdb-" );
/*! глобальная функция для вывода help-а */ /*! глобальная функция для вывода help-а */
static void help_print(); static void help_print();
...@@ -90,6 +98,10 @@ namespace uniset ...@@ -90,6 +98,10 @@ namespace uniset
} }
void run( bool async ); void run( bool async );
#ifndef DISABLE_REST_API
Poco::Net::HTTPRequestHandler* createRequestHandler( const Poco::Net::HTTPServerRequest& req );
virtual void handleRequest( Poco::Net::HTTPServerRequest& req, Poco::Net::HTTPServerResponse& resp ) override;
#endif
protected: protected:
...@@ -100,7 +112,9 @@ namespace uniset ...@@ -100,7 +112,9 @@ namespace uniset
void onTimer( ev::timer& t, int revents ); void onTimer( ev::timer& t, int revents );
void onCheckBuffer( ev::timer& t, int revents ); void onCheckBuffer( ev::timer& t, int revents );
void addLog( Log* log, const std::string& txt ); void addLog( Log* log, const std::string& txt );
#ifndef DISABLE_REST_API
void respError( Poco::Net::HTTPServerResponse& resp, Poco::Net::HTTPResponse::HTTPStatus s, const std::string& message );
#endif
std::string myname; std::string myname;
std::unique_ptr<SQLiteInterface> db; std::unique_ptr<SQLiteInterface> db;
...@@ -158,6 +172,13 @@ namespace uniset ...@@ -158,6 +172,13 @@ namespace uniset
ev::timer checkBufferTimer; ev::timer checkBufferTimer;
double tmCheckBuffer_sec = { 1.0 }; double tmCheckBuffer_sec = { 1.0 };
#ifndef DISABLE_REST_API
std::shared_ptr<Poco::Net::HTTPServer> httpserv;
std::string httpHost = { "" };
int httpPort = { 0 };
#endif
private: private:
}; };
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
......
...@@ -20,7 +20,12 @@ int main(int argc, char** argv) ...@@ -20,7 +20,12 @@ int main(int argc, char** argv)
uniset_init(argc, argv, "configure.xml"); uniset_init(argc, argv, "configure.xml");
auto db = LogDB::init_logdb(argc, argv); auto db = LogDB::init_logdb(argc, argv);
if( !db )
return 1;
db->run(false); db->run(false);
return 0;
} }
catch( const std::exception& ex ) catch( const std::exception& ex )
{ {
...@@ -31,5 +36,5 @@ int main(int argc, char** argv) ...@@ -31,5 +36,5 @@ int main(int argc, char** argv)
cerr << "(LogDB::main): catch ..." << endl; cerr << "(LogDB::main): catch ..." << endl;
} }
return 0; return 1;
} }
...@@ -2,8 +2,11 @@ ...@@ -2,8 +2,11 @@
ulimit -Sc 1000000 ulimit -Sc 1000000
#uniset2-start.sh -f #uniset2-start.sh -g \
./uniset2-logdb --confile test.xml --logdb-name LogDB \ ./uniset2-logdb --confile test.xml --logdb-name LogDB \
--logdb-log-add-levels any \ --logdb-log-add-levels any \
--logdb-dbfile ./test.db \ --logdb-dbfile ./test.db \
--logdb-buffer-size 5 --logdb-buffer-size 5 \
--logdb-httpserver-port 8888 \
$*
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 to comment