Commit c3f077a6 authored by Pavel Vainerman's avatar Pavel Vainerman

(UHttp): поддержка команды 'list' (список объектов)

parent 3d0492dc
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// -------------------------------------------------------------------------
#ifndef UHttpRequesrHandler_H_
#define UHttpRequesrHandler_H_
// -------------------------------------------------------------------------
#include <memory>
#include <Poco/Net/HTTPRequestHandler.h>
#include <Poco/Net/HTTPRequestHandlerFactory.h>
#include <Poco/Net/HTTPServerRequest.h>
#include <Poco/Net/HTTPServerResponse.h>
#include <Poco/URI.h>
#include "json.hpp"
#include "DebugStream.h"
// -------------------------------------------------------------------------
/*! \page UHttpServer API
*
* Формат запроса: /api/version/get/xxx
*
* Версия API: v01
* /api/version/get/ObjectName - получение информации об объекте ObjectName (json)
* /api/version/get/list - Получение списка доступных объектов
*
* \todo подумать над /api/version/get/tree - получение "дерева" объектов (древовидный список с учётом подчинения Manager/Objects)
*/
// -------------------------------------------------------------------------
namespace UniSetTypes
{
namespace UHttp
{
// текущая версия API
const std::string UHTTP_API_VERSION="v01";
/*! интерфейс для объекта выдающего json-данные */
class IHttpRequest
{
public:
IHttpRequest(){}
virtual ~IHttpRequest(){}
virtual nlohmann::json getData( const Poco::URI::QueryParameters& p ) = 0;
};
// -------------------------------------------------------------------------
/*! интерфейс для обработки запросов к объектам */
class IHttpRequestRegistry
{
public:
IHttpRequestRegistry(){}
virtual ~IHttpRequestRegistry(){}
virtual nlohmann::json getDataByName( const std::string& name, const Poco::URI::QueryParameters& p ) = 0;
virtual nlohmann::json getObjectsList( const Poco::URI::QueryParameters& p ) = 0;
};
// -------------------------------------------------------------------------
class UHttpRequestHandler:
public Poco::Net::HTTPRequestHandler
{
public:
UHttpRequestHandler( std::shared_ptr<IHttpRequestRegistry> _registry );
virtual void handleRequest( Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp ) override;
private:
std::shared_ptr<IHttpRequestRegistry> registry;
std::shared_ptr<DebugStream> log;
};
// -------------------------------------------------------------------------
class UHttpRequestHandlerFactory:
public Poco::Net::HTTPRequestHandlerFactory
{
public:
UHttpRequestHandlerFactory( std::shared_ptr<IHttpRequestRegistry>& _registry );
virtual Poco::Net::HTTPRequestHandler* createRequestHandler( const Poco::Net::HTTPServerRequest & ) override;
private:
std::shared_ptr<IHttpRequestRegistry> registry;
};
}
}
// -------------------------------------------------------------------------
#endif // UHttpRequesrHandler_H_
// -------------------------------------------------------------------------
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// -------------------------------------------------------------------------
#ifndef UHttpServer_H_
#define UHttpServer_H_
// -------------------------------------------------------------------------
#include <string>
#include <memory>
#include <Poco/Net/HTTPServer.h>
#include "DebugStream.h"
#include "ThreadCreator.h"
#include "UHttpRequestHandler.h"
// -------------------------------------------------------------------------
/*! \page pgUHttpServer Http сервер
Http сервер предназначен для получения информации о UniSetObject-ах через http (json).
*/
// -------------------------------------------------------------------------
namespace UniSetTypes
{
namespace UHttp
{
class UHttpServer
{
public:
UHttpServer( std::shared_ptr<IHttpRequestRegistry>& supplier, const std::string& host, int port );
virtual ~UHttpServer();
void start();
void stop();
std::shared_ptr<DebugStream> log();
protected:
UHttpServer();
private:
std::shared_ptr<DebugStream> mylog;
Poco::Net::SocketAddress sa;
std::shared_ptr<Poco::Net::HTTPServer> http;
std::shared_ptr<UHttpRequestHandlerFactory> reqFactory;
};
}
}
// -------------------------------------------------------------------------
#endif // UHttpServer_H_
// -------------------------------------------------------------------------
......@@ -85,7 +85,9 @@ class UniSetActivator:
return abortScript;
}
// Поддрежка REST API (IHttpRequestRegistry)
virtual nlohmann::json getDataByName( const std::string& name , const Poco::URI::QueryParameters& p ) override;
virtual nlohmann::json getObjectsList( const Poco::URI::QueryParameters& p ) override;
protected:
......
......@@ -127,6 +127,12 @@ class UniSetManager:
const std::shared_ptr<UniSetObject> findObject( const std::string& name );
const std::shared_ptr<UniSetManager> findManager( const std::string& name );
// рекурсивный поиск по всем объекам
const std::shared_ptr<UniSetObject> deepFindObject( const std::string& name );
// рекурсивное наполнение списка объектов
void getAllObjectsList( std::vector<std::shared_ptr<UniSetObject>>& vec, size_t lim=1000 );
typedef UniSetManagerList::iterator MListIterator;
int getObjectsInfo(const std::shared_ptr<UniSetManager>& mngr, UniSetTypes::SimpleInfoSeq* seq,
......
......@@ -101,6 +101,7 @@ class UniSetObject:
//! поместить сообщение в очередь
virtual void push( const UniSetTypes::TransportMessage& msg ) override;
// HTTP API
virtual nlohmann::json getData( const Poco::URI::QueryParameters& p ) override;
// -------------- вспомогательные --------------
......
......@@ -47,28 +47,41 @@ void UHttpRequestHandler::handleRequest( Poco::Net::HTTPServerRequest& req, Poco
std::vector<std::string> seg;
uri.getPathSegments(seg);
// example: http://host:port/api-version/get/ObjectName
if( seg.size() < 3
|| seg[0] != UHTTP_API_VERSION
|| seg[1] != "get"
|| seg[2].empty() )
// example: http://host:port/api/version/get/ObjectName
if( seg.size() < 4
|| seg[1] != UHTTP_API_VERSION
|| seg[2] != "get"
|| seg[3].empty() )
{
resp.setStatus(HTTPResponse::HTTP_BAD_REQUEST);
resp.setContentType("text/json");
std::ostream& out = resp.send();
nlohmann::json jdata;
jdata["error"] = "HTTP_BAD_REQUEST";
jdata["ecode"] = HTTPResponse::HTTP_BAD_REQUEST;
out << jdata.dump();
out.flush();
return;
}
const std::string objectName(seg[2]);
const std::string objectName(seg[3]);
auto qp = uri.getQueryParameters();
resp.setStatus(HTTPResponse::HTTP_OK);
resp.setContentType("text/json");
std::ostream& out = resp.send();
if( objectName == "list" )
{
auto json = registry->getObjectsList(qp);
out << json.dump();
}
else
{
auto json = registry->getDataByName(objectName, qp);
out << json.dump();
}
out.flush();
}
// -------------------------------------------------------------------------
......
......@@ -863,17 +863,37 @@ UniSetActivator::TerminateEvent_Signal UniSetActivator::signal_terminate_event()
// ------------------------------------------------------------------------------------------
nlohmann::json UniSetActivator::getDataByName( const string& name, const Poco::URI::QueryParameters& p )
{
auto obj = findObject(name);
if( name == myname )
return getData(p);
auto obj = deepFindObject(name);
if( obj )
return obj->getData(p);
auto man = findManager(name);
if( man )
return man->getData(p);
//! \todo Продумать что возвращать если объект не найден
nlohmann::json j = "";
return j; // return empty json
nlohmann::json jdata;
ostringstream err;
err << "Object '" << name << "' not found";
jdata["error"] = err.str();
jdata["ecode"] = Poco::Net::HTTPResponse::HTTP_OK;
return jdata;
}
// ------------------------------------------------------------------------------------------
nlohmann::json UniSetActivator::getObjectsList( const Poco::URI::QueryParameters& p )
{
nlohmann::json jdata;
std::vector<std::shared_ptr<UniSetObject>> vec;
vec.reserve(objectsCount());
//! \todo Доделать обработку параметров beg,lim на случай большого количества объектов (и частичных запросов)
size_t lim = 1000;
getAllObjectsList(vec,lim);
for( const auto& o: vec )
jdata.push_back(o->getName());
return jdata;
}
// ------------------------------------------------------------------------------------------
void UniSetActivator::terminated( int signo )
......
......@@ -433,6 +433,53 @@ const std::shared_ptr<UniSetManager> UniSetManager::findManager( const string& n
return nullptr;
}
// ------------------------------------------------------------------------------------------
const std::shared_ptr<UniSetObject> UniSetManager::deepFindObject( const string& name )
{
{
auto obj = findObject(name);
if( obj )
return obj;
}
auto man = findManager(name);
if( man )
{
auto obj = dynamic_pointer_cast<UniSetObject>(man);
return obj;
}
// ищем в глубину у каждого менеджера
for( const auto& m: mlist )
{
auto obj = m->deepFindObject(name);
if( obj )
return obj;
}
return nullptr;
}
// ------------------------------------------------------------------------------------------
void UniSetManager::getAllObjectsList( std::vector<std::shared_ptr<UniSetObject> >& vec, size_t lim )
{
// добавить себя
vec.push_back(get_ptr());
// добавить подчинённые объекты
for( const auto& o: olist )
{
vec.push_back(o);
if( lim > 0 && vec.size() >= lim )
return;
}
// добавить рекурсивно по менеджерам
for( const auto& m: mlist )
{
// вызываем рекурсивно
m->getAllObjectsList(vec,lim);
}
}
// ------------------------------------------------------------------------------------------
void UniSetManager::sigterm( int signo )
{
sig = signo;
......
......@@ -39,6 +39,15 @@ class UTestRequestRegistry:
return j;
}
virtual nlohmann::json getObjectsList( const Poco::URI::QueryParameters& p ) override
{
nlohmann::json j;
j.push_back("TestObject");
j.push_back("TestObject2");
j.push_back("TestObject3");
return j;
}
private:
UTestSupplier sup;
};
......
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