icinga2/lib/remote/eventshandler.cpp
Egor-OSSRevival 0d32ae3159
Some checks failed
Container Image / Container Image (push) Has been cancelled
Linux / alpine:bash (push) Has been cancelled
Linux / amazonlinux:2 (push) Has been cancelled
Linux / amazonlinux:2023 (push) Has been cancelled
Linux / debian:11 (linux/386) (push) Has been cancelled
Linux / debian:11 (push) Has been cancelled
Linux / debian:12 (linux/386) (push) Has been cancelled
Linux / debian:12 (push) Has been cancelled
Linux / debian:13 (push) Has been cancelled
Linux / fedora:41 (push) Has been cancelled
Linux / fedora:42 (push) Has been cancelled
Linux / fedora:43 (push) Has been cancelled
Linux / opensuse/leap:15.6 (push) Has been cancelled
Linux / opensuse/leap:16.0 (push) Has been cancelled
Linux / registry.suse.com/bci/bci-base:16.0 (push) Has been cancelled
Linux / registry.suse.com/suse/sle15:15.6 (push) Has been cancelled
Linux / registry.suse.com/suse/sle15:15.7 (push) Has been cancelled
Linux / rockylinux/rockylinux:10 (push) Has been cancelled
Linux / rockylinux:8 (push) Has been cancelled
Linux / rockylinux:9 (push) Has been cancelled
Linux / ubuntu:22.04 (push) Has been cancelled
Linux / ubuntu:24.04 (push) Has been cancelled
Linux / ubuntu:25.04 (push) Has been cancelled
Linux / ubuntu:25.10 (push) Has been cancelled
Windows / Windows (push) Has been cancelled
docs: Remove 'queue' parameter requirement from event stream document… (#10495)
* docs: Remove 'queue' parameter requirement from event stream documentation

* Update AUTHORS
2026-01-07 14:51:26 +01:00

119 lines
3 KiB
C++

/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
#include "remote/eventshandler.hpp"
#include "remote/httputility.hpp"
#include "remote/filterutility.hpp"
#include "config/configcompiler.hpp"
#include "config/expression.hpp"
#include "base/defer.hpp"
#include "base/io-engine.hpp"
#include "base/objectlock.hpp"
#include "base/json.hpp"
#include <boost/asio/buffer.hpp>
#include <boost/asio/write.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <map>
#include <set>
using namespace icinga;
REGISTER_URLHANDLER("/v1/events", EventsHandler);
const std::map<String, EventType> l_EventTypes ({
{"AcknowledgementCleared", EventType::AcknowledgementCleared},
{"AcknowledgementSet", EventType::AcknowledgementSet},
{"CheckResult", EventType::CheckResult},
{"CommentAdded", EventType::CommentAdded},
{"CommentRemoved", EventType::CommentRemoved},
{"DowntimeAdded", EventType::DowntimeAdded},
{"DowntimeRemoved", EventType::DowntimeRemoved},
{"DowntimeStarted", EventType::DowntimeStarted},
{"DowntimeTriggered", EventType::DowntimeTriggered},
{"Flapping", EventType::Flapping},
{"Notification", EventType::Notification},
{"StateChange", EventType::StateChange},
{"ObjectCreated", EventType::ObjectCreated},
{"ObjectDeleted", EventType::ObjectDeleted},
{"ObjectModified", EventType::ObjectModified}
});
const String l_ApiQuery ("<API query>");
bool EventsHandler::HandleRequest(
const WaitGroup::Ptr&,
const HttpRequest& request,
HttpResponse& response,
boost::asio::yield_context& yc
)
{
namespace asio = boost::asio;
namespace http = boost::beast::http;
auto url = request.Url();
auto user = request.User();
auto params = request.Params();
if (url->GetPath().size() != 2)
return false;
if (request.method() != http::verb::post)
return false;
if (request.version() == 10) {
HttpUtility::SendJsonError(response, params, 400, "HTTP/1.0 not supported for event streams.");
return true;
}
Array::Ptr types = params->Get("types");
if (!types) {
HttpUtility::SendJsonError(response, params, 400, "'types' query parameter is required.");
return true;
}
{
ObjectLock olock(types);
for (String type : types) {
FilterUtility::CheckPermission(user, "events/" + type);
}
}
std::set<EventType> eventTypes;
{
ObjectLock olock(types);
for (String type : types) {
auto typeId (l_EventTypes.find(type));
if (typeId != l_EventTypes.end()) {
eventTypes.emplace(typeId->second);
}
}
}
EventsSubscriber subscriber (std::move(eventTypes), HttpUtility::GetLastParameter(params, "filter"), l_ApiQuery);
IoBoundWorkSlot dontLockTheIoThread (yc);
response.result(http::status::ok);
response.set(http::field::content_type, "application/json");
response.StartStreaming(true);
// Send response headers before waiting for the first event.
response.Flush(yc);
auto encoder = response.GetJsonEncoder();
for (;;) {
auto event (subscriber.GetInbox()->Shift(yc));
if (response.IsClientDisconnected()) {
return true;
}
if (event) {
encoder.Encode(event);
response.body() << '\n';
response.Flush(yc);
}
}
}