Adjust /v1/events, too

This commit is contained in:
Alexander A. Klimov 2019-02-15 11:51:12 +01:00
parent 1941c1da28
commit fd239ba3fe
33 changed files with 173 additions and 52 deletions

View File

@ -13,11 +13,14 @@ using namespace icinga;
REGISTER_URLHANDLER("/v1/actions", ActionsHandler);
bool ActionsHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(ActionsHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
};

View File

@ -13,11 +13,14 @@ using namespace icinga;
REGISTER_URLHANDLER("/v1/config/files", ConfigFilesHandler);
bool ConfigFilesHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(ConfigFilesHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
};

View File

@ -11,11 +11,14 @@ using namespace icinga;
REGISTER_URLHANDLER("/v1/config/packages", ConfigPackagesHandler);
bool ConfigPackagesHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(ConfigPackagesHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
private:

View File

@ -12,11 +12,14 @@ using namespace icinga;
REGISTER_URLHANDLER("/v1/config/stages", ConfigStagesHandler);
bool ConfigStagesHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(ConfigStagesHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
private:

View File

@ -54,11 +54,14 @@ static void EnsureFrameCleanupTimer()
}
bool ConsoleHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -23,11 +23,14 @@ public:
DECLARE_PTR_TYPEDEFS(ConsoleHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
static std::vector<String> GetAutocompletionSuggestions(const String& word, ScriptFrame& frame);

View File

@ -15,11 +15,14 @@ using namespace icinga;
REGISTER_URLHANDLER("/v1/objects", CreateObjectHandler);
bool CreateObjectHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(CreateObjectHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
};

View File

@ -15,11 +15,14 @@ using namespace icinga;
REGISTER_URLHANDLER("/v1/objects", DeleteObjectHandler);
bool DeleteObjectHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(DeleteObjectHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
};

View File

@ -5,8 +5,10 @@
#include "remote/filterutility.hpp"
#include "config/configcompiler.hpp"
#include "config/expression.hpp"
#include "base/defer.hpp"
#include "base/objectlock.hpp"
#include "base/json.hpp"
#include <boost/asio/buffer.hpp>
#include <boost/algorithm/string/replace.hpp>
using namespace icinga;
@ -14,13 +16,17 @@ using namespace icinga;
REGISTER_URLHANDLER("/v1/events", EventsHandler);
bool EventsHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace asio = boost::asio;
namespace http = boost::beast::http;
if (url->GetPath().size() != 2)
@ -75,18 +81,24 @@ bool EventsHandler::HandleRequest(
queue->AddClient(&request);
Defer removeClient ([&queue, &request, &queueName]() {
queue->RemoveClient(&request);
EventQueue::UnregisterIfUnused(queueName, queue);
});
hasStartedStreaming = true;
response.result(http::status::ok);
response.set(http::field::content_type, "application/json");
http::async_write(stream, response, yc);
stream.async_flush(yc);
asio::const_buffer newLine ("\n", 1);
for (;;) {
Dictionary::Ptr result = queue->WaitForEvent(&request);
if (!response.IsPeerConnected()) {
queue->RemoveClient(&request);
EventQueue::UnregisterIfUnused(queueName, queue);
return true;
}
if (!result)
continue;
@ -94,14 +106,11 @@ bool EventsHandler::HandleRequest(
boost::algorithm::replace_all(body, "\n", "");
try {
response.WriteBody(body.CStr(), body.GetLength());
response.WriteBody("\n", 1);
} catch (const std::exception&) {
queue->RemoveClient(&request);
EventQueue::UnregisterIfUnused(queueName, queue);
throw;
}
asio::const_buffer payload (body.CStr(), body.GetLength());
stream.async_write_some(payload, yc);
stream.async_write_some(newLine, yc);
stream.async_flush(yc);
}
}

View File

@ -15,11 +15,14 @@ public:
DECLARE_PTR_TYPEDEFS(EventsHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
};

View File

@ -46,9 +46,12 @@ void HttpHandler::Register(const Url::Ptr& url, const HttpHandler::Ptr& handler)
}
void HttpHandler::ProcessRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
boost::beast::http::response<boost::beast::http::string_body>& response
boost::beast::http::response<boost::beast::http::string_body>& response,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
Dictionary::Ptr node = m_UrlTree;
@ -96,7 +99,7 @@ void HttpHandler::ProcessRequest(
bool processed = false;
for (const HttpHandler::Ptr& handler : handlers) {
if (handler->HandleRequest(user, request, url, response, params)) {
if (handler->HandleRequest(stream, user, request, url, response, params, yc, hasStartedStreaming)) {
processed = true;
break;
}

View File

@ -8,7 +8,9 @@
#include "remote/httpresponse.hpp"
#include "remote/apiuser.hpp"
#include "base/registry.hpp"
#include "base/tlsstream.hpp"
#include <vector>
#include <boost/asio/spawn.hpp>
#include <boost/beast/http.hpp>
namespace icinga
@ -25,18 +27,24 @@ public:
DECLARE_PTR_TYPEDEFS(HttpHandler);
virtual bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) = 0;
static void Register(const Url::Ptr& url, const HttpHandler::Ptr& handler);
static void ProcessRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
boost::beast::http::response<boost::beast::http::string_body>& response
boost::beast::http::response<boost::beast::http::string_body>& response,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
);
private:

View File

@ -311,7 +311,7 @@ bool EnsureValidBody(
}
static inline
void ProcessRequest(
bool ProcessRequest(
AsioTlsStream& stream,
boost::beast::http::request<boost::beast::http::string_body>& request,
ApiUser::Ptr& authenticatedUser,
@ -321,11 +321,17 @@ void ProcessRequest(
{
namespace http = boost::beast::http;
bool hasStartedStreaming = false;
try {
CpuBoundWork handlingRequest (yc);
HttpHandler::ProcessRequest(authenticatedUser, request, response);
HttpHandler::ProcessRequest(stream, authenticatedUser, request, response, yc, hasStartedStreaming);
} catch (const std::exception& ex) {
if (hasStartedStreaming) {
return false;
}
http::response<http::string_body> response;
HttpUtility::SendJsonError(response, nullptr, 500, "Unhandled exception" , DiagnosticInformation(ex));
@ -333,11 +339,17 @@ void ProcessRequest(
http::async_write(stream, response, yc);
stream.async_flush(yc);
return;
return true;
}
if (hasStartedStreaming) {
return false;
}
http::async_write(stream, response, yc);
stream.async_flush(yc);
return true;
}
void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
@ -419,7 +431,9 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
break;
}
ProcessRequest(*m_Stream, request, authenticatedUser, response, yc);
if (!ProcessRequest(*m_Stream, request, authenticatedUser, response, yc)) {
break;
}
if (request.version() != 11 || request[http::field::connection] == "close") {
break;

View File

@ -9,11 +9,14 @@ using namespace icinga;
REGISTER_URLHANDLER("/", InfoHandler);
bool InfoHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(InfoHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
};

View File

@ -13,11 +13,14 @@ using namespace icinga;
REGISTER_URLHANDLER("/v1/objects", ModifyObjectHandler);
bool ModifyObjectHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(ModifyObjectHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
};

View File

@ -88,11 +88,14 @@ Dictionary::Ptr ObjectQueryHandler::SerializeObjectAttrs(const Object::Ptr& obje
}
bool ObjectQueryHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(ObjectQueryHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
private:

View File

@ -69,11 +69,14 @@ public:
};
bool StatusHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(StatusHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
};

View File

@ -76,11 +76,14 @@ public:
};
bool TemplateQueryHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(TemplateQueryHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
};

View File

@ -47,11 +47,14 @@ public:
};
bool TypeQueryHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(TypeQueryHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
};

View File

@ -57,11 +57,14 @@ public:
};
bool VariableQueryHandler::HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
)
{
namespace http = boost::beast::http;

View File

@ -14,11 +14,14 @@ public:
DECLARE_PTR_TYPEDEFS(VariableQueryHandler);
bool HandleRequest(
AsioTlsStream& stream,
const ApiUser::Ptr& user,
boost::beast::http::request<boost::beast::http::string_body>& request,
const Url::Ptr& url,
boost::beast::http::response<boost::beast::http::string_body>& response,
const Dictionary::Ptr& params
const Dictionary::Ptr& params,
boost::asio::yield_context& yc,
bool& hasStartedStreaming
) override;
};