mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-27 07:34:15 +02:00
Use new HTTP message classes in HttpServerConnection and Handlers
This commit is contained in:
parent
71d490e0cc
commit
ee64f85e9c
@ -18,29 +18,26 @@ REGISTER_URLHANDLER("/v1/actions", ActionsHandler);
|
|||||||
bool ActionsHandler::HandleRequest(
|
bool ActionsHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() != 3)
|
if (request.Url()->GetPath().size() != 3)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() != http::verb::post)
|
if (request.method() != http::verb::post)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
String actionName = url->GetPath()[2];
|
String actionName = request.Url()->GetPath()[2];
|
||||||
|
|
||||||
ApiAction::Ptr action = ApiAction::GetByName(actionName);
|
ApiAction::Ptr action = ApiAction::GetByName(actionName);
|
||||||
|
|
||||||
if (!action) {
|
if (!action) {
|
||||||
HttpUtility::SendJsonError(response, params, 404, "Action '" + actionName + "' does not exist.");
|
response.SendJsonError(request.Params(), 404, "Action '" + actionName + "' does not exist.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,21 +53,21 @@ bool ActionsHandler::HandleRequest(
|
|||||||
qd.Permission = permission;
|
qd.Permission = permission;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objs = FilterUtility::GetFilterTargets(qd, params, user);
|
objs = FilterUtility::GetFilterTargets(qd, request.Params(), request.User());
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 404,
|
response.SendJsonError(request.Params(), 404,
|
||||||
"No objects found.",
|
"No objects found.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (objs.empty()) {
|
if (objs.empty()) {
|
||||||
HttpUtility::SendJsonError(response, params, 404,
|
response.SendJsonError(request.Params(), 404,
|
||||||
"No objects found.");
|
"No objects found.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FilterUtility::CheckPermission(user, permission);
|
FilterUtility::CheckPermission(request.User(), permission);
|
||||||
objs.emplace_back(nullptr);
|
objs.emplace_back(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,19 +76,16 @@ bool ActionsHandler::HandleRequest(
|
|||||||
Log(LogNotice, "ApiActionHandler")
|
Log(LogNotice, "ApiActionHandler")
|
||||||
<< "Running action " << actionName;
|
<< "Running action " << actionName;
|
||||||
|
|
||||||
bool verbose = false;
|
bool verbose = request.IsVerbose();
|
||||||
|
|
||||||
ActionsHandler::AuthenticatedApiUser = user;
|
ActionsHandler::AuthenticatedApiUser = request.User();
|
||||||
Defer a ([]() {
|
Defer a ([]() {
|
||||||
ActionsHandler::AuthenticatedApiUser = nullptr;
|
ActionsHandler::AuthenticatedApiUser = nullptr;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (params)
|
|
||||||
verbose = HttpUtility::GetLastParameter(params, "verbose");
|
|
||||||
|
|
||||||
std::shared_lock wgLock{*waitGroup, std::try_to_lock};
|
std::shared_lock wgLock{*waitGroup, std::try_to_lock};
|
||||||
if (!wgLock) {
|
if (!wgLock) {
|
||||||
HttpUtility::SendJsonError(response, params, 503, "Shutting down.");
|
response.SendJsonError(request.Params(), 503, "Shutting down.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +106,7 @@ bool ActionsHandler::HandleRequest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
results.emplace_back(action->Invoke(obj, params));
|
results.emplace_back(action->Invoke(obj, request.Params()));
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
Dictionary::Ptr fail = new Dictionary({
|
Dictionary::Ptr fail = new Dictionary({
|
||||||
{ "code", 500 },
|
{ "code", 500 },
|
||||||
@ -161,7 +155,7 @@ bool ActionsHandler::HandleRequest(
|
|||||||
{ "results", new Array(std::move(results)) }
|
{ "results", new Array(std::move(results)) }
|
||||||
});
|
});
|
||||||
|
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
@ -16,11 +16,8 @@ REGISTER_URLHANDLER("/v1/config/files", ConfigFilesHandler);
|
|||||||
bool ConfigFilesHandler::HandleRequest(
|
bool ConfigFilesHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr&,
|
const WaitGroup::Ptr&,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
@ -30,50 +27,50 @@ bool ConfigFilesHandler::HandleRequest(
|
|||||||
if (request.method() != http::verb::get)
|
if (request.method() != http::verb::get)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const std::vector<String>& urlPath = url->GetPath();
|
const std::vector<String>& urlPath = request.Url()->GetPath();
|
||||||
|
|
||||||
if (urlPath.size() >= 4)
|
if (urlPath.size() >= 4)
|
||||||
params->Set("package", urlPath[3]);
|
request.Params()->Set("package", urlPath[3]);
|
||||||
|
|
||||||
if (urlPath.size() >= 5)
|
if (urlPath.size() >= 5)
|
||||||
params->Set("stage", urlPath[4]);
|
request.Params()->Set("stage", urlPath[4]);
|
||||||
|
|
||||||
if (urlPath.size() >= 6) {
|
if (urlPath.size() >= 6) {
|
||||||
std::vector<String> tmpPath(urlPath.begin() + 5, urlPath.end());
|
std::vector<String> tmpPath(urlPath.begin() + 5, urlPath.end());
|
||||||
params->Set("path", boost::algorithm::join(tmpPath, "/"));
|
request.Params()->Set("path", boost::algorithm::join(tmpPath, "/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request[http::field::accept] == "application/json") {
|
if (request[http::field::accept] == "application/json") {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid Accept header. Either remove the Accept header or set it to 'application/octet-stream'.");
|
response.SendJsonError(request.Params(), 400, "Invalid Accept header. Either remove the Accept header or set it to 'application/octet-stream'.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FilterUtility::CheckPermission(user, "config/query");
|
FilterUtility::CheckPermission(request.User(), "config/query");
|
||||||
|
|
||||||
String packageName = HttpUtility::GetLastParameter(params, "package");
|
String packageName = request.GetLastParameter("package");
|
||||||
String stageName = HttpUtility::GetLastParameter(params, "stage");
|
String stageName = request.GetLastParameter("stage");
|
||||||
|
|
||||||
if (!ConfigPackageUtility::ValidatePackageName(packageName)) {
|
if (!ConfigPackageUtility::ValidatePackageName(packageName)) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid package name.");
|
response.SendJsonError(request.Params(), 400, "Invalid package name.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ConfigPackageUtility::ValidateStageName(stageName)) {
|
if (!ConfigPackageUtility::ValidateStageName(stageName)) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid stage name.");
|
response.SendJsonError(request.Params(), 400, "Invalid stage name.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String relativePath = HttpUtility::GetLastParameter(params, "path");
|
String relativePath = request.GetLastParameter("path");
|
||||||
|
|
||||||
if (ConfigPackageUtility::ContainsDotDot(relativePath)) {
|
if (ConfigPackageUtility::ContainsDotDot(relativePath)) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Path contains '..' (not allowed).");
|
response.SendJsonError(request.Params(), 400, "Path contains '..' (not allowed).");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String path = ConfigPackageUtility::GetPackageDir() + "/" + packageName + "/" + stageName + "/" + relativePath;
|
String path = ConfigPackageUtility::GetPackageDir() + "/" + packageName + "/" + stageName + "/" + relativePath;
|
||||||
|
|
||||||
if (!Utility::PathExists(path)) {
|
if (!Utility::PathExists(path)) {
|
||||||
HttpUtility::SendJsonError(response, params, 404, "Path not found.");
|
response.SendJsonError(request.Params(), 404, "Path not found.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,13 +78,11 @@ bool ConfigFilesHandler::HandleRequest(
|
|||||||
std::ifstream fp(path.CStr(), std::ifstream::in | std::ifstream::binary);
|
std::ifstream fp(path.CStr(), std::ifstream::in | std::ifstream::binary);
|
||||||
fp.exceptions(std::ifstream::badbit);
|
fp.exceptions(std::ifstream::badbit);
|
||||||
|
|
||||||
String content((std::istreambuf_iterator<char>(fp)), std::istreambuf_iterator<char>());
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
response.set(http::field::content_type, "application/octet-stream");
|
response.set(http::field::content_type, "application/octet-stream");
|
||||||
response.body() = content;
|
response.body() << fp.rdbuf();
|
||||||
response.content_length(response.body().size());
|
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 500, "Could not read file.",
|
response.SendJsonError(request.Params(), 500, "Could not read file.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
@ -13,50 +13,41 @@ REGISTER_URLHANDLER("/v1/config/packages", ConfigPackagesHandler);
|
|||||||
bool ConfigPackagesHandler::HandleRequest(
|
bool ConfigPackagesHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr&,
|
const WaitGroup::Ptr&,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() > 4)
|
if (request.Url()->GetPath().size() > 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() == http::verb::get)
|
if (request.method() == http::verb::get)
|
||||||
HandleGet(user, request, url, response, params);
|
HandleGet(request, response);
|
||||||
else if (request.method() == http::verb::post)
|
else if (request.method() == http::verb::post)
|
||||||
HandlePost(user, request, url, response, params);
|
HandlePost(request, response);
|
||||||
else if (request.method() == http::verb::delete_)
|
else if (request.method() == http::verb::delete_)
|
||||||
HandleDelete(user, request, url, response, params);
|
HandleDelete(request, response);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigPackagesHandler::HandleGet(
|
void ConfigPackagesHandler::HandleGet(HttpRequest& request, HttpResponse& response)
|
||||||
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
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
FilterUtility::CheckPermission(user, "config/query");
|
FilterUtility::CheckPermission(request.User(), "config/query");
|
||||||
|
|
||||||
std::vector<String> packages;
|
std::vector<String> packages;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
packages = ConfigPackageUtility::GetPackages();
|
packages = ConfigPackageUtility::GetPackages();
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 500, "Could not retrieve packages.",
|
response.SendJsonError(request.Params(), 500, "Could not retrieve packages.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -86,28 +77,22 @@ void ConfigPackagesHandler::HandleGet(
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigPackagesHandler::HandlePost(
|
void ConfigPackagesHandler::HandlePost(HttpRequest& request, HttpResponse& response)
|
||||||
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
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
FilterUtility::CheckPermission(user, "config/modify");
|
FilterUtility::CheckPermission(request.User(), "config/modify");
|
||||||
|
|
||||||
if (url->GetPath().size() >= 4)
|
if (request.Url()->GetPath().size() >= 4)
|
||||||
params->Set("package", url->GetPath()[3]);
|
request.Params()->Set("package", request.Url()->GetPath()[3]);
|
||||||
|
|
||||||
String packageName = HttpUtility::GetLastParameter(params, "package");
|
String packageName = request.GetLastParameter("package");
|
||||||
|
|
||||||
if (!ConfigPackageUtility::ValidatePackageName(packageName)) {
|
if (!ConfigPackageUtility::ValidatePackageName(packageName)) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid package name '" + packageName + "'.");
|
response.SendJsonError(request.Params(), 400, "Invalid package name '" + packageName + "'.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +101,7 @@ void ConfigPackagesHandler::HandlePost(
|
|||||||
|
|
||||||
ConfigPackageUtility::CreatePackage(packageName);
|
ConfigPackageUtility::CreatePackage(packageName);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 500, "Could not create package '" + packageName + "'.",
|
response.SendJsonError(request.Params(), 500, "Could not create package '" + packageName + "'.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -132,35 +117,29 @@ void ConfigPackagesHandler::HandlePost(
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigPackagesHandler::HandleDelete(
|
void ConfigPackagesHandler::HandleDelete(HttpRequest& request, HttpResponse& response)
|
||||||
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
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
FilterUtility::CheckPermission(user, "config/modify");
|
FilterUtility::CheckPermission(request.User(), "config/modify");
|
||||||
|
|
||||||
if (url->GetPath().size() >= 4)
|
if (request.Url()->GetPath().size() >= 4)
|
||||||
params->Set("package", url->GetPath()[3]);
|
request.Params()->Set("package", request.Url()->GetPath()[3]);
|
||||||
|
|
||||||
String packageName = HttpUtility::GetLastParameter(params, "package");
|
String packageName = request.GetLastParameter("package");
|
||||||
|
|
||||||
if (!ConfigPackageUtility::ValidatePackageName(packageName)) {
|
if (!ConfigPackageUtility::ValidatePackageName(packageName)) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid package name '" + packageName + "'.");
|
response.SendJsonError(request.Params(), 400, "Invalid package name '" + packageName + "'.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ConfigPackageUtility::DeletePackage(packageName);
|
ConfigPackageUtility::DeletePackage(packageName);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 500, "Failed to delete package '" + packageName + "'.",
|
response.SendJsonError(request.Params(), 500, "Failed to delete package '" + packageName + "'.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -176,5 +155,5 @@ void ConfigPackagesHandler::HandleDelete(
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
}
|
}
|
||||||
|
@ -16,37 +16,16 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void HandleGet(
|
void HandleGet(HttpRequest& request, HttpResponse& response);
|
||||||
const ApiUser::Ptr& user,
|
void HandlePost(HttpRequest& request, HttpResponse& response);
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
void HandleDelete(HttpRequest& request, HttpResponse& response);
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params
|
|
||||||
);
|
|
||||||
void HandlePost(
|
|
||||||
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
|
|
||||||
);
|
|
||||||
void HandleDelete(
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,58 +17,49 @@ std::atomic<bool> ConfigStagesHandler::m_RunningPackageUpdates (false);
|
|||||||
bool ConfigStagesHandler::HandleRequest(
|
bool ConfigStagesHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr&,
|
const WaitGroup::Ptr&,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() > 5)
|
if (request.Url()->GetPath().size() > 5)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() == http::verb::get)
|
if (request.method() == http::verb::get)
|
||||||
HandleGet(user, request, url, response, params);
|
HandleGet(request, response);
|
||||||
else if (request.method() == http::verb::post)
|
else if (request.method() == http::verb::post)
|
||||||
HandlePost(user, request, url, response, params);
|
HandlePost(request, response);
|
||||||
else if (request.method() == http::verb::delete_)
|
else if (request.method() == http::verb::delete_)
|
||||||
HandleDelete(user, request, url, response, params);
|
HandleDelete(request, response);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigStagesHandler::HandleGet(
|
void ConfigStagesHandler::HandleGet(HttpRequest& request, HttpResponse& response)
|
||||||
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
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
FilterUtility::CheckPermission(user, "config/query");
|
FilterUtility::CheckPermission(request.User(), "config/query");
|
||||||
|
|
||||||
if (url->GetPath().size() >= 4)
|
if (request.Url()->GetPath().size() >= 4)
|
||||||
params->Set("package", url->GetPath()[3]);
|
request.Params()->Set("package", request.Url()->GetPath()[3]);
|
||||||
|
|
||||||
if (url->GetPath().size() >= 5)
|
if (request.Url()->GetPath().size() >= 5)
|
||||||
params->Set("stage", url->GetPath()[4]);
|
request.Params()->Set("stage", request.Url()->GetPath()[4]);
|
||||||
|
|
||||||
String packageName = HttpUtility::GetLastParameter(params, "package");
|
String packageName = request.GetLastParameter("package");
|
||||||
String stageName = HttpUtility::GetLastParameter(params, "stage");
|
String stageName = request.GetLastParameter("stage");
|
||||||
|
|
||||||
if (!ConfigPackageUtility::ValidatePackageName(packageName))
|
if (!ConfigPackageUtility::ValidatePackageName(packageName))
|
||||||
return HttpUtility::SendJsonError(response, params, 400, "Invalid package name '" + packageName + "'.");
|
return response.SendJsonError(request.Params(), 400, "Invalid package name '" + packageName + "'.");
|
||||||
|
|
||||||
if (!ConfigPackageUtility::ValidateStageName(stageName))
|
if (!ConfigPackageUtility::ValidateStageName(stageName))
|
||||||
return HttpUtility::SendJsonError(response, params, 400, "Invalid stage name '" + stageName + "'.");
|
return response.SendJsonError(request.Params(), 400, "Invalid stage name '" + stageName + "'.");
|
||||||
|
|
||||||
ArrayData results;
|
ArrayData results;
|
||||||
|
|
||||||
@ -88,40 +79,34 @@ void ConfigStagesHandler::HandleGet(
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigStagesHandler::HandlePost(
|
void ConfigStagesHandler::HandlePost(HttpRequest& request, HttpResponse& response)
|
||||||
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
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
FilterUtility::CheckPermission(user, "config/modify");
|
FilterUtility::CheckPermission(request.User(), "config/modify");
|
||||||
|
|
||||||
if (url->GetPath().size() >= 4)
|
if (request.Url()->GetPath().size() >= 4)
|
||||||
params->Set("package", url->GetPath()[3]);
|
request.Params()->Set("package", request.Url()->GetPath()[3]);
|
||||||
|
|
||||||
String packageName = HttpUtility::GetLastParameter(params, "package");
|
String packageName = request.GetLastParameter("package");
|
||||||
|
|
||||||
if (!ConfigPackageUtility::ValidatePackageName(packageName))
|
if (!ConfigPackageUtility::ValidatePackageName(packageName))
|
||||||
return HttpUtility::SendJsonError(response, params, 400, "Invalid package name '" + packageName + "'.");
|
return response.SendJsonError(request.Params(), 400, "Invalid package name '" + packageName + "'.");
|
||||||
|
|
||||||
bool reload = true;
|
bool reload = true;
|
||||||
|
|
||||||
if (params->Contains("reload"))
|
if (request.Params()->Contains("reload"))
|
||||||
reload = HttpUtility::GetLastParameter(params, "reload");
|
reload = request.GetLastParameter("reload");
|
||||||
|
|
||||||
bool activate = true;
|
bool activate = true;
|
||||||
|
|
||||||
if (params->Contains("activate"))
|
if (request.Params()->Contains("activate"))
|
||||||
activate = HttpUtility::GetLastParameter(params, "activate");
|
activate = request.GetLastParameter("activate");
|
||||||
|
|
||||||
Dictionary::Ptr files = params->Get("files");
|
Dictionary::Ptr files = request.Params()->Get("files");
|
||||||
|
|
||||||
String stageName;
|
String stageName;
|
||||||
|
|
||||||
@ -133,7 +118,7 @@ void ConfigStagesHandler::HandlePost(
|
|||||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Parameter 'reload' must be false when 'activate' is false."));
|
BOOST_THROW_EXCEPTION(std::invalid_argument("Parameter 'reload' must be false when 'activate' is false."));
|
||||||
|
|
||||||
if (m_RunningPackageUpdates.exchange(true)) {
|
if (m_RunningPackageUpdates.exchange(true)) {
|
||||||
return HttpUtility::SendJsonError(response, params, 423,
|
return response.SendJsonError(request.Params(), 423,
|
||||||
"Conflicting request, there is already an ongoing package update in progress. Please try it again later.");
|
"Conflicting request, there is already an ongoing package update in progress. Please try it again later.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +131,7 @@ void ConfigStagesHandler::HandlePost(
|
|||||||
/* validate the config. on success, activate stage and reload */
|
/* validate the config. on success, activate stage and reload */
|
||||||
ConfigPackageUtility::AsyncTryActivateStage(packageName, stageName, activate, reload, resetPackageUpdates);
|
ConfigPackageUtility::AsyncTryActivateStage(packageName, stageName, activate, reload, resetPackageUpdates);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
return HttpUtility::SendJsonError(response, params, 500,
|
return response.SendJsonError(request.Params(), 500,
|
||||||
"Stage creation failed.",
|
"Stage creation failed.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
}
|
}
|
||||||
@ -171,40 +156,34 @@ void ConfigStagesHandler::HandlePost(
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigStagesHandler::HandleDelete(
|
void ConfigStagesHandler::HandleDelete(HttpRequest& request, HttpResponse& response)
|
||||||
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
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
FilterUtility::CheckPermission(user, "config/modify");
|
FilterUtility::CheckPermission(request.User(), "config/modify");
|
||||||
|
|
||||||
if (url->GetPath().size() >= 4)
|
if (request.Url()->GetPath().size() >= 4)
|
||||||
params->Set("package", url->GetPath()[3]);
|
request.Params()->Set("package", request.Url()->GetPath()[3]);
|
||||||
|
|
||||||
if (url->GetPath().size() >= 5)
|
if (request.Url()->GetPath().size() >= 5)
|
||||||
params->Set("stage", url->GetPath()[4]);
|
request.Params()->Set("stage", request.Url()->GetPath()[4]);
|
||||||
|
|
||||||
String packageName = HttpUtility::GetLastParameter(params, "package");
|
String packageName = request.GetLastParameter("package");
|
||||||
String stageName = HttpUtility::GetLastParameter(params, "stage");
|
String stageName = request.GetLastParameter("stage");
|
||||||
|
|
||||||
if (!ConfigPackageUtility::ValidatePackageName(packageName))
|
if (!ConfigPackageUtility::ValidatePackageName(packageName))
|
||||||
return HttpUtility::SendJsonError(response, params, 400, "Invalid package name '" + packageName + "'.");
|
return response.SendJsonError(request.Params(), 400, "Invalid package name '" + packageName + "'.");
|
||||||
|
|
||||||
if (!ConfigPackageUtility::ValidateStageName(stageName))
|
if (!ConfigPackageUtility::ValidateStageName(stageName))
|
||||||
return HttpUtility::SendJsonError(response, params, 400, "Invalid stage name '" + stageName + "'.");
|
return response.SendJsonError(request.Params(), 400, "Invalid stage name '" + stageName + "'.");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ConfigPackageUtility::DeleteStage(packageName, stageName);
|
ConfigPackageUtility::DeleteStage(packageName, stageName);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
return HttpUtility::SendJsonError(response, params, 500,
|
return response.SendJsonError(request.Params(), 500,
|
||||||
"Failed to delete stage '" + stageName + "' in package '" + packageName + "'.",
|
"Failed to delete stage '" + stageName + "' in package '" + packageName + "'.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
}
|
}
|
||||||
@ -221,5 +200,5 @@ void ConfigStagesHandler::HandleDelete(
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
}
|
}
|
||||||
|
@ -17,37 +17,16 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void HandleGet(
|
void HandleGet(HttpRequest& request, HttpResponse& response);
|
||||||
const ApiUser::Ptr& user,
|
void HandlePost(HttpRequest& request, HttpResponse& response);
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
void HandleDelete(HttpRequest& request, HttpResponse& response);
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params
|
|
||||||
);
|
|
||||||
void HandlePost(
|
|
||||||
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
|
|
||||||
);
|
|
||||||
void HandleDelete(
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
static std::atomic<bool> m_RunningPackageUpdates;
|
static std::atomic<bool> m_RunningPackageUpdates;
|
||||||
};
|
};
|
||||||
|
@ -56,18 +56,15 @@ static void EnsureFrameCleanupTimer()
|
|||||||
bool ConsoleHandler::HandleRequest(
|
bool ConsoleHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr&,
|
const WaitGroup::Ptr&,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() != 3)
|
if (request.Url()->GetPath().size() != 3)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() != http::verb::post)
|
if (request.method() != http::verb::post)
|
||||||
@ -75,38 +72,37 @@ bool ConsoleHandler::HandleRequest(
|
|||||||
|
|
||||||
QueryDescription qd;
|
QueryDescription qd;
|
||||||
|
|
||||||
String methodName = url->GetPath()[2];
|
String methodName = request.Url()->GetPath()[2];
|
||||||
|
|
||||||
FilterUtility::CheckPermission(user, "console");
|
FilterUtility::CheckPermission(request.User(), "console");
|
||||||
|
|
||||||
String session = HttpUtility::GetLastParameter(params, "session");
|
String session = request.GetLastParameter("session");
|
||||||
|
|
||||||
if (session.IsEmpty())
|
if (session.IsEmpty())
|
||||||
session = Utility::NewUniqueID();
|
session = Utility::NewUniqueID();
|
||||||
|
|
||||||
String command = HttpUtility::GetLastParameter(params, "command");
|
String command = request.GetLastParameter("command");
|
||||||
|
|
||||||
bool sandboxed = HttpUtility::GetLastParameter(params, "sandboxed");
|
bool sandboxed = request.GetLastParameter("sandboxed");
|
||||||
|
|
||||||
ConfigObjectsSharedLock lock (std::try_to_lock);
|
ConfigObjectsSharedLock lock (std::try_to_lock);
|
||||||
|
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading.");
|
response.SendJsonError(request.Params(), 503, "Icinga is reloading.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (methodName == "execute-script")
|
if (methodName == "execute-script")
|
||||||
return ExecuteScriptHelper(request, response, params, command, session, sandboxed);
|
return ExecuteScriptHelper(request, response, command, session, sandboxed);
|
||||||
else if (methodName == "auto-complete-script")
|
else if (methodName == "auto-complete-script")
|
||||||
return AutocompleteScriptHelper(request, response, params, command, session, sandboxed);
|
return AutocompleteScriptHelper(request, response, command, session, sandboxed);
|
||||||
|
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid method specified: " + methodName);
|
response.SendJsonError(request.Params(), 400, "Invalid method specified: " + methodName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConsoleHandler::ExecuteScriptHelper(boost::beast::http::request<boost::beast::http::string_body>& request,
|
bool ConsoleHandler::ExecuteScriptHelper(HttpRequest& request, HttpResponse& response,
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
const String& command, const String& session, bool sandboxed)
|
||||||
const Dictionary::Ptr& params, const String& command, const String& session, bool sandboxed)
|
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
@ -174,14 +170,13 @@ bool ConsoleHandler::ExecuteScriptHelper(boost::beast::http::request<boost::beas
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConsoleHandler::AutocompleteScriptHelper(boost::beast::http::request<boost::beast::http::string_body>& request,
|
bool ConsoleHandler::AutocompleteScriptHelper(HttpRequest& request, HttpResponse& response,
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
const String& command, const String& session, bool sandboxed)
|
||||||
const Dictionary::Ptr& params, const String& command, const String& session, bool sandboxed)
|
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
@ -213,7 +208,7 @@ bool ConsoleHandler::AutocompleteScriptHelper(boost::beast::http::request<boost:
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
@ -37,12 +34,10 @@ public:
|
|||||||
static std::vector<String> GetAutocompletionSuggestions(const String& word, ScriptFrame& frame);
|
static std::vector<String> GetAutocompletionSuggestions(const String& word, ScriptFrame& frame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool ExecuteScriptHelper(boost::beast::http::request<boost::beast::http::string_body>& request,
|
static bool ExecuteScriptHelper(HttpRequest& request, HttpResponse& response,
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
const String& command, const String& session, bool sandboxed);
|
||||||
const Dictionary::Ptr& params, const String& command, const String& session, bool sandboxed);
|
static bool AutocompleteScriptHelper(HttpRequest& request, HttpResponse& response,
|
||||||
static bool AutocompleteScriptHelper(boost::beast::http::request<boost::beast::http::string_body>& request,
|
const String& command, const String& session, bool sandboxed);
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params, const String& command, const String& session, bool sandboxed);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,35 +18,32 @@ REGISTER_URLHANDLER("/v1/objects", CreateObjectHandler);
|
|||||||
bool CreateObjectHandler::HandleRequest(
|
bool CreateObjectHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() != 4)
|
if (request.Url()->GetPath().size() != 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() != http::verb::put)
|
if (request.method() != http::verb::put)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Type::Ptr type = FilterUtility::TypeFromPluralName(url->GetPath()[2]);
|
Type::Ptr type = FilterUtility::TypeFromPluralName(request.Url()->GetPath()[2]);
|
||||||
|
|
||||||
if (!type) {
|
if (!type) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid type specified.");
|
response.SendJsonError(request.Params(), 400, "Invalid type specified.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FilterUtility::CheckPermission(user, "objects/create/" + type->GetName());
|
FilterUtility::CheckPermission(request.User(), "objects/create/" + type->GetName());
|
||||||
|
|
||||||
String name = url->GetPath()[3];
|
String name = request.Url()->GetPath()[3];
|
||||||
Array::Ptr templates = params->Get("templates");
|
Array::Ptr templates = request.Params()->Get("templates");
|
||||||
Dictionary::Ptr attrs = params->Get("attrs");
|
Dictionary::Ptr attrs = request.Params()->Get("attrs");
|
||||||
|
|
||||||
/* Put created objects into the local zone if not explicitly defined.
|
/* Put created objects into the local zone if not explicitly defined.
|
||||||
* This allows additional zone members to sync the
|
* This allows additional zone members to sync the
|
||||||
@ -82,8 +79,8 @@ bool CreateObjectHandler::HandleRequest(
|
|||||||
|
|
||||||
bool ignoreOnError = false;
|
bool ignoreOnError = false;
|
||||||
|
|
||||||
if (params->Contains("ignore_on_error"))
|
if (request.Params()->Contains("ignore_on_error"))
|
||||||
ignoreOnError = HttpUtility::GetLastParameter(params, "ignore_on_error");
|
ignoreOnError = request.GetLastParameter("ignore_on_error");
|
||||||
|
|
||||||
Dictionary::Ptr result = new Dictionary({
|
Dictionary::Ptr result = new Dictionary({
|
||||||
{ "results", new Array({ result1 }) }
|
{ "results", new Array({ result1 }) }
|
||||||
@ -91,21 +88,18 @@ bool CreateObjectHandler::HandleRequest(
|
|||||||
|
|
||||||
String config;
|
String config;
|
||||||
|
|
||||||
bool verbose = false;
|
bool verbose = request.IsVerbose();
|
||||||
|
|
||||||
if (params)
|
|
||||||
verbose = HttpUtility::GetLastParameter(params, "verbose");
|
|
||||||
|
|
||||||
ConfigObjectsSharedLock lock (std::try_to_lock);
|
ConfigObjectsSharedLock lock (std::try_to_lock);
|
||||||
|
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading");
|
response.SendJsonError(request.Params(), 503, "Icinga is reloading");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_lock wgLock{*waitGroup, std::try_to_lock};
|
std::shared_lock wgLock{*waitGroup, std::try_to_lock};
|
||||||
if (!wgLock) {
|
if (!wgLock) {
|
||||||
HttpUtility::SendJsonError(response, params, 503, "Shutting down.");
|
response.SendJsonError(request.Params(), 503, "Shutting down.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +120,7 @@ bool CreateObjectHandler::HandleRequest(
|
|||||||
result1->Set("status", "Object could not be created.");
|
result1->Set("status", "Object could not be created.");
|
||||||
|
|
||||||
response.result(http::status::internal_server_error);
|
response.result(http::status::internal_server_error);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -143,7 +137,7 @@ bool CreateObjectHandler::HandleRequest(
|
|||||||
result1->Set("diagnostic_information", diagnosticInformation);
|
result1->Set("diagnostic_information", diagnosticInformation);
|
||||||
|
|
||||||
response.result(http::status::internal_server_error);
|
response.result(http::status::internal_server_error);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -159,7 +153,7 @@ bool CreateObjectHandler::HandleRequest(
|
|||||||
result1->Set("status", "Object was not created but 'ignore_on_error' was set to true");
|
result1->Set("status", "Object was not created but 'ignore_on_error' was set to true");
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
@ -18,27 +18,24 @@ REGISTER_URLHANDLER("/v1/objects", DeleteObjectHandler);
|
|||||||
bool DeleteObjectHandler::HandleRequest(
|
bool DeleteObjectHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() < 3 || url->GetPath().size() > 4)
|
if (request.Url()->GetPath().size() < 3 || request.Url()->GetPath().size() > 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() != http::verb::delete_)
|
if (request.method() != http::verb::delete_)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Type::Ptr type = FilterUtility::TypeFromPluralName(url->GetPath()[2]);
|
Type::Ptr type = FilterUtility::TypeFromPluralName(request.Url()->GetPath()[2]);
|
||||||
|
|
||||||
if (!type) {
|
if (!type) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid type specified.");
|
response.SendJsonError(request.Params(), 400, "Invalid type specified.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,32 +43,32 @@ bool DeleteObjectHandler::HandleRequest(
|
|||||||
qd.Types.insert(type->GetName());
|
qd.Types.insert(type->GetName());
|
||||||
qd.Permission = "objects/delete/" + type->GetName();
|
qd.Permission = "objects/delete/" + type->GetName();
|
||||||
|
|
||||||
params->Set("type", type->GetName());
|
request.Params()->Set("type", type->GetName());
|
||||||
|
|
||||||
if (url->GetPath().size() >= 4) {
|
if (request.Url()->GetPath().size() >= 4) {
|
||||||
String attr = type->GetName();
|
String attr = type->GetName();
|
||||||
boost::algorithm::to_lower(attr);
|
boost::algorithm::to_lower(attr);
|
||||||
params->Set(attr, url->GetPath()[3]);
|
request.Params()->Set(attr, request.Url()->GetPath()[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Value> objs;
|
std::vector<Value> objs;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objs = FilterUtility::GetFilterTargets(qd, params, user);
|
objs = FilterUtility::GetFilterTargets(qd, request.Params(), request.User());
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 404,
|
response.SendJsonError(request.Params(), 404,
|
||||||
"No objects found.",
|
"No objects found.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cascade = HttpUtility::GetLastParameter(params, "cascade");
|
bool cascade = request.GetLastParameter("cascade");
|
||||||
bool verbose = HttpUtility::GetLastParameter(params, "verbose");
|
bool verbose = request.IsVerbose();
|
||||||
|
|
||||||
ConfigObjectsSharedLock lock (std::try_to_lock);
|
ConfigObjectsSharedLock lock (std::try_to_lock);
|
||||||
|
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading");
|
response.SendJsonError(request.Params(), 503, "Icinga is reloading");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +78,7 @@ bool DeleteObjectHandler::HandleRequest(
|
|||||||
|
|
||||||
std::shared_lock wgLock{*waitGroup, std::try_to_lock};
|
std::shared_lock wgLock{*waitGroup, std::try_to_lock};
|
||||||
if (!wgLock) {
|
if (!wgLock) {
|
||||||
HttpUtility::SendJsonError(response, params, 503, "Shutting down.");
|
response.SendJsonError(request.Params(), 503, "Shutting down.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +140,7 @@ bool DeleteObjectHandler::HandleRequest(
|
|||||||
else
|
else
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
|
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
@ -42,11 +42,8 @@ const String l_ApiQuery ("<API query>");
|
|||||||
bool EventsHandler::HandleRequest(
|
bool EventsHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr&,
|
const WaitGroup::Ptr&,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
@ -54,35 +51,35 @@ bool EventsHandler::HandleRequest(
|
|||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() != 2)
|
if (request.Url()->GetPath().size() != 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() != http::verb::post)
|
if (request.method() != http::verb::post)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.version() == 10) {
|
if (request.version() == 10) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "HTTP/1.0 not supported for event streams.");
|
response.SendJsonError(request.Params(), 400, "HTTP/1.0 not supported for event streams.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array::Ptr types = params->Get("types");
|
Array::Ptr types = request.Params()->Get("types");
|
||||||
|
|
||||||
if (!types) {
|
if (!types) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "'types' query parameter is required.");
|
response.SendJsonError(request.Params(), 400, "'types' query parameter is required.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ObjectLock olock(types);
|
ObjectLock olock(types);
|
||||||
for (String type : types) {
|
for (String type : types) {
|
||||||
FilterUtility::CheckPermission(user, "events/" + type);
|
FilterUtility::CheckPermission(request.User(), "events/" + type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String queueName = HttpUtility::GetLastParameter(params, "queue");
|
String queueName = request.GetLastParameter("queue");
|
||||||
|
|
||||||
if (queueName.IsEmpty()) {
|
if (queueName.IsEmpty()) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "'queue' query parameter is required.");
|
response.SendJsonError(request.Params(), 400, "'queue' query parameter is required.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +96,7 @@ bool EventsHandler::HandleRequest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EventsSubscriber subscriber (std::move(eventTypes), HttpUtility::GetLastParameter(params, "filter"), l_ApiQuery);
|
EventsSubscriber subscriber (std::move(eventTypes), request.GetLastParameter("filter"), l_ApiQuery);
|
||||||
|
|
||||||
server.StartStreaming();
|
server.StartStreaming();
|
||||||
|
|
||||||
|
@ -17,11 +17,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
@ -49,9 +49,8 @@ void HttpHandler::Register(const Url::Ptr& url, const HttpHandler::Ptr& handler)
|
|||||||
void HttpHandler::ProcessRequest(
|
void HttpHandler::ProcessRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
@ -59,8 +58,7 @@ void HttpHandler::ProcessRequest(
|
|||||||
Dictionary::Ptr node = m_UrlTree;
|
Dictionary::Ptr node = m_UrlTree;
|
||||||
std::vector<HttpHandler::Ptr> handlers;
|
std::vector<HttpHandler::Ptr> handlers;
|
||||||
|
|
||||||
Url::Ptr url = new Url(std::string(request.target()));
|
auto& path (request.Url()->GetPath());
|
||||||
auto& path (url->GetPath());
|
|
||||||
|
|
||||||
for (std::vector<String>::size_type i = 0; i <= path.size(); i++) {
|
for (std::vector<String>::size_type i = 0; i <= path.size(); i++) {
|
||||||
Array::Ptr current_handlers = node->Get("handlers");
|
Array::Ptr current_handlers = node->Get("handlers");
|
||||||
@ -90,12 +88,10 @@ void HttpHandler::ProcessRequest(
|
|||||||
|
|
||||||
std::reverse(handlers.begin(), handlers.end());
|
std::reverse(handlers.begin(), handlers.end());
|
||||||
|
|
||||||
Dictionary::Ptr params;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
params = HttpUtility::FetchRequestParameters(url, request.body());
|
request.DecodeParams();
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid request body: " + DiagnosticInformation(ex, false));
|
response.SendJsonError(nullptr, 400, "Invalid request body: " + DiagnosticInformation(ex, false));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +105,7 @@ void HttpHandler::ProcessRequest(
|
|||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
for (const HttpHandler::Ptr& handler : handlers) {
|
for (const HttpHandler::Ptr& handler : handlers) {
|
||||||
if (handler->HandleRequest(waitGroup, stream, user, request, url, response, params, yc, server)) {
|
if (handler->HandleRequest(waitGroup, stream, request, response, yc, server)) {
|
||||||
processed = true;
|
processed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -122,7 +118,7 @@ void HttpHandler::ProcessRequest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!processed) {
|
if (!processed) {
|
||||||
HttpUtility::SendJsonError(response, params, 404, "The requested path '" + boost::algorithm::join(path, "/") +
|
response.SendJsonError(request.Params(), 404, "The requested path '" + boost::algorithm::join(path, "/") +
|
||||||
"' could not be found or the request method is not valid for this path.");
|
"' could not be found or the request method is not valid for this path.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
#define HTTPHANDLER_H
|
#define HTTPHANDLER_H
|
||||||
|
|
||||||
#include "remote/i2-remote.hpp"
|
#include "remote/i2-remote.hpp"
|
||||||
|
#include "base/io-engine.hpp"
|
||||||
#include "remote/url.hpp"
|
#include "remote/url.hpp"
|
||||||
#include "remote/httpserverconnection.hpp"
|
#include "remote/httpserverconnection.hpp"
|
||||||
|
#include "remote/httpmessage.hpp"
|
||||||
#include "remote/apiuser.hpp"
|
#include "remote/apiuser.hpp"
|
||||||
#include "base/registry.hpp"
|
#include "base/registry.hpp"
|
||||||
#include "base/tlsstream.hpp"
|
#include "base/tlsstream.hpp"
|
||||||
@ -29,11 +31,8 @@ public:
|
|||||||
virtual bool HandleRequest(
|
virtual bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) = 0;
|
) = 0;
|
||||||
@ -42,9 +41,8 @@ public:
|
|||||||
static void ProcessRequest(
|
static void ProcessRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
);
|
);
|
||||||
|
@ -129,10 +129,9 @@ bool HttpServerConnection::Disconnected()
|
|||||||
|
|
||||||
static inline
|
static inline
|
||||||
bool EnsureValidHeaders(
|
bool EnsureValidHeaders(
|
||||||
AsioTlsStream& stream,
|
|
||||||
boost::beast::flat_buffer& buf,
|
boost::beast::flat_buffer& buf,
|
||||||
boost::beast::http::parser<true, boost::beast::http::string_body>& parser,
|
HttpRequest& request,
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
HttpResponse& response,
|
||||||
bool& shuttingDown,
|
bool& shuttingDown,
|
||||||
boost::asio::yield_context& yc
|
boost::asio::yield_context& yc
|
||||||
)
|
)
|
||||||
@ -147,7 +146,7 @@ bool EnsureValidHeaders(
|
|||||||
|
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
http::async_read_header(stream, buf, parser, yc[ec]);
|
request.ParseHeader(buf, yc[ec]);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
if (ec == boost::asio::error::operation_aborted)
|
if (ec == boost::asio::error::operation_aborted)
|
||||||
@ -156,7 +155,7 @@ bool EnsureValidHeaders(
|
|||||||
errorMsg = ec.message();
|
errorMsg = ec.message();
|
||||||
httpError = true;
|
httpError = true;
|
||||||
} else {
|
} else {
|
||||||
switch (parser.get().version()) {
|
switch (request.version()) {
|
||||||
case 10:
|
case 10:
|
||||||
case 11:
|
case 11:
|
||||||
break;
|
break;
|
||||||
@ -165,24 +164,21 @@ bool EnsureValidHeaders(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response.version(request.version());
|
||||||
|
|
||||||
if (!errorMsg.IsEmpty() || httpError) {
|
if (!errorMsg.IsEmpty() || httpError) {
|
||||||
response.result(http::status::bad_request);
|
response.result(http::status::bad_request);
|
||||||
|
|
||||||
if (!httpError && parser.get()[http::field::accept] == "application/json") {
|
if (!httpError && request[http::field::accept] == "application/json") {
|
||||||
HttpUtility::SendJsonBody(response, nullptr, new Dictionary({
|
response.SendJsonError(400, "Bad Request: " + errorMsg);
|
||||||
{ "error", 400 },
|
|
||||||
{ "status", String("Bad Request: ") + errorMsg }
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
response.set(http::field::content_type, "text/html");
|
response.set(http::field::content_type, "text/html");
|
||||||
response.body() = String("<h1>Bad Request</h1><p><pre>") + errorMsg + "</pre></p>";
|
response.body() << "<h1>Bad Request</h1><p><pre>" << errorMsg << "</pre></p>\r\n";
|
||||||
response.content_length(response.body().size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response.set(http::field::connection, "close");
|
response.set(http::field::connection, "close");
|
||||||
|
|
||||||
http::async_write(stream, response, yc);
|
response.Write(yc);
|
||||||
stream.async_flush(yc);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -192,28 +188,25 @@ bool EnsureValidHeaders(
|
|||||||
|
|
||||||
static inline
|
static inline
|
||||||
void HandleExpect100(
|
void HandleExpect100(
|
||||||
AsioTlsStream& stream,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
boost::asio::yield_context& yc
|
boost::asio::yield_context& yc
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (request[http::field::expect] == "100-continue") {
|
if (request[http::field::expect] == "100-continue") {
|
||||||
http::response<http::string_body> response;
|
|
||||||
|
|
||||||
response.result(http::status::continue_);
|
response.result(http::status::continue_);
|
||||||
|
|
||||||
http::async_write(stream, response, yc);
|
response.Write(yc);
|
||||||
stream.async_flush(yc);
|
response.Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
bool HandleAccessControl(
|
bool HandleAccessControl(
|
||||||
AsioTlsStream& stream,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
boost::asio::yield_context& yc
|
boost::asio::yield_context& yc
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -240,12 +233,10 @@ bool HandleAccessControl(
|
|||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
response.set(http::field::access_control_allow_methods, "GET, POST, PUT, DELETE");
|
response.set(http::field::access_control_allow_methods, "GET, POST, PUT, DELETE");
|
||||||
response.set(http::field::access_control_allow_headers, "Authorization, Content-Type, X-HTTP-Method-Override");
|
response.set(http::field::access_control_allow_headers, "Authorization, Content-Type, X-HTTP-Method-Override");
|
||||||
response.body() = "Preflight OK";
|
response.body() << "Preflight OK";
|
||||||
response.content_length(response.body().size());
|
|
||||||
response.set(http::field::connection, "close");
|
response.set(http::field::connection, "close");
|
||||||
|
|
||||||
http::async_write(stream, response, yc);
|
response.Write(yc);
|
||||||
stream.async_flush(yc);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -258,9 +249,8 @@ bool HandleAccessControl(
|
|||||||
|
|
||||||
static inline
|
static inline
|
||||||
bool EnsureAcceptHeader(
|
bool EnsureAcceptHeader(
|
||||||
AsioTlsStream& stream,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
boost::asio::yield_context& yc
|
boost::asio::yield_context& yc
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -269,12 +259,10 @@ bool EnsureAcceptHeader(
|
|||||||
if (request.method() != http::verb::get && request[http::field::accept] != "application/json") {
|
if (request.method() != http::verb::get && request[http::field::accept] != "application/json") {
|
||||||
response.result(http::status::bad_request);
|
response.result(http::status::bad_request);
|
||||||
response.set(http::field::content_type, "text/html");
|
response.set(http::field::content_type, "text/html");
|
||||||
response.body() = "<h1>Accept header is missing or not set to 'application/json'.</h1>";
|
response.body() << "<h1>Accept header is missing or not set to 'application/json'.</h1>\r\n";
|
||||||
response.content_length(response.body().size());
|
|
||||||
response.set(http::field::connection, "close");
|
response.set(http::field::connection, "close");
|
||||||
|
|
||||||
http::async_write(stream, response, yc);
|
response.Write(yc);
|
||||||
stream.async_flush(yc);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -284,16 +272,14 @@ bool EnsureAcceptHeader(
|
|||||||
|
|
||||||
static inline
|
static inline
|
||||||
bool EnsureAuthenticatedUser(
|
bool EnsureAuthenticatedUser(
|
||||||
AsioTlsStream& stream,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
ApiUser::Ptr& authenticatedUser,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
boost::asio::yield_context& yc
|
boost::asio::yield_context& yc
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (!authenticatedUser) {
|
if (!request.User()) {
|
||||||
Log(LogWarning, "HttpServerConnection")
|
Log(LogWarning, "HttpServerConnection")
|
||||||
<< "Unauthorized request: " << request.method_string() << ' ' << request.target();
|
<< "Unauthorized request: " << request.method_string() << ' ' << request.target();
|
||||||
|
|
||||||
@ -302,18 +288,13 @@ bool EnsureAuthenticatedUser(
|
|||||||
response.set(http::field::connection, "close");
|
response.set(http::field::connection, "close");
|
||||||
|
|
||||||
if (request[http::field::accept] == "application/json") {
|
if (request[http::field::accept] == "application/json") {
|
||||||
HttpUtility::SendJsonBody(response, nullptr, new Dictionary({
|
response.SendJsonError(401, "Unauthorized. Please check your user credentials.");
|
||||||
{ "error", 401 },
|
|
||||||
{ "status", "Unauthorized. Please check your user credentials." }
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
response.set(http::field::content_type, "text/html");
|
response.set(http::field::content_type, "text/html");
|
||||||
response.body() = "<h1>Unauthorized. Please check your user credentials.</h1>";
|
response.body() << "<h1>Unauthorized. Please check your user credentials.</h1>\r\n";
|
||||||
response.content_length(response.body().size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
http::async_write(stream, response, yc);
|
response.Write(yc);
|
||||||
stream.async_flush(yc);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -323,11 +304,9 @@ bool EnsureAuthenticatedUser(
|
|||||||
|
|
||||||
static inline
|
static inline
|
||||||
bool EnsureValidBody(
|
bool EnsureValidBody(
|
||||||
AsioTlsStream& stream,
|
|
||||||
boost::beast::flat_buffer& buf,
|
boost::beast::flat_buffer& buf,
|
||||||
boost::beast::http::parser<true, boost::beast::http::string_body>& parser,
|
HttpRequest& request,
|
||||||
ApiUser::Ptr& authenticatedUser,
|
HttpResponse& response,
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
bool& shuttingDown,
|
bool& shuttingDown,
|
||||||
boost::asio::yield_context& yc
|
boost::asio::yield_context& yc
|
||||||
)
|
)
|
||||||
@ -336,7 +315,7 @@ bool EnsureValidBody(
|
|||||||
|
|
||||||
{
|
{
|
||||||
size_t maxSize = 1024 * 1024;
|
size_t maxSize = 1024 * 1024;
|
||||||
Array::Ptr permissions = authenticatedUser->GetPermissions();
|
Array::Ptr permissions = request.User()->GetPermissions();
|
||||||
|
|
||||||
if (permissions) {
|
if (permissions) {
|
||||||
ObjectLock olock(permissions);
|
ObjectLock olock(permissions);
|
||||||
@ -366,7 +345,7 @@ bool EnsureValidBody(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.body_limit(maxSize);
|
request.Parser().body_limit(maxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shuttingDown)
|
if (shuttingDown)
|
||||||
@ -374,7 +353,7 @@ bool EnsureValidBody(
|
|||||||
|
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
http::async_read(stream, buf, parser, yc[ec]);
|
request.ParseBody(buf, yc[ec]);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
if (ec == boost::asio::error::operation_aborted)
|
if (ec == boost::asio::error::operation_aborted)
|
||||||
@ -389,21 +368,16 @@ bool EnsureValidBody(
|
|||||||
|
|
||||||
response.result(http::status::bad_request);
|
response.result(http::status::bad_request);
|
||||||
|
|
||||||
if (parser.get()[http::field::accept] == "application/json") {
|
if (request[http::field::accept] == "application/json") {
|
||||||
HttpUtility::SendJsonBody(response, nullptr, new Dictionary({
|
response.SendJsonError(400, "Bad Request: " + ec.message());
|
||||||
{ "error", 400 },
|
|
||||||
{ "status", String("Bad Request: ") + ec.message() }
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
response.set(http::field::content_type, "text/html");
|
response.set(http::field::content_type, "text/html");
|
||||||
response.body() = String("<h1>Bad Request</h1><p><pre>") + ec.message() + "</pre></p>";
|
response.body() << "<h1>Bad Request</h1><p><pre>" << ec.message() << "</pre></p>\r\n";
|
||||||
response.content_length(response.body().size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response.set(http::field::connection, "close");
|
response.set(http::field::connection, "close");
|
||||||
|
|
||||||
http::async_write(stream, response, yc);
|
response.Write(yc);
|
||||||
stream.async_flush(yc);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -414,9 +388,8 @@ bool EnsureValidBody(
|
|||||||
static inline
|
static inline
|
||||||
bool ProcessRequest(
|
bool ProcessRequest(
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpRequest& request,
|
||||||
ApiUser::Ptr& authenticatedUser,
|
HttpResponse& response,
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
HttpServerConnection& server,
|
HttpServerConnection& server,
|
||||||
bool& hasStartedStreaming,
|
bool& hasStartedStreaming,
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
@ -424,42 +397,21 @@ bool ProcessRequest(
|
|||||||
boost::asio::yield_context& yc
|
boost::asio::yield_context& yc
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Cache the elapsed time to acquire a CPU semaphore used to detect extremely heavy workloads.
|
// Cache the elapsed time to acquire a CPU semaphore used to detect extremely heavy workloads.
|
||||||
auto start (std::chrono::steady_clock::now());
|
auto start (std::chrono::steady_clock::now());
|
||||||
CpuBoundWork handlingRequest (yc);
|
CpuBoundWork handlingRequest (yc);
|
||||||
cpuBoundWorkTime = std::chrono::steady_clock::now() - start;
|
cpuBoundWorkTime = std::chrono::steady_clock::now() - start;
|
||||||
|
|
||||||
HttpHandler::ProcessRequest(waitGroup, stream, authenticatedUser, request, response, yc, server);
|
HttpHandler::ProcessRequest(waitGroup, stream, request, response, yc, server);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
if (hasStartedStreaming) {
|
response.SendJsonError(request.Params(), 500, "Unhandled exception", DiagnosticInformation(ex));
|
||||||
return false;
|
response.Write(yc);
|
||||||
}
|
|
||||||
|
|
||||||
auto sysErr (dynamic_cast<const boost::system::system_error*>(&ex));
|
|
||||||
|
|
||||||
if (sysErr && sysErr->code() == boost::asio::error::operation_aborted) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
http::response<http::string_body> response;
|
|
||||||
|
|
||||||
HttpUtility::SendJsonError(response, nullptr, 500, "Unhandled exception" , DiagnosticInformation(ex));
|
|
||||||
|
|
||||||
http::async_write(stream, response, yc);
|
|
||||||
stream.async_flush(yc);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasStartedStreaming) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
http::async_write(stream, response, yc);
|
response.body().Finish();
|
||||||
stream.async_flush(yc);
|
response.Write(yc);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -481,23 +433,21 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
|
|||||||
while (m_WaitGroup->IsLockable()) {
|
while (m_WaitGroup->IsLockable()) {
|
||||||
m_Seen = Utility::GetTime();
|
m_Seen = Utility::GetTime();
|
||||||
|
|
||||||
http::parser<true, http::string_body> parser;
|
HttpRequest request(m_Stream);
|
||||||
http::response<http::string_body> response;
|
HttpResponse response(m_Stream);
|
||||||
|
|
||||||
parser.header_limit(1024 * 1024);
|
request.Parser().header_limit(1024 * 1024);
|
||||||
parser.body_limit(-1);
|
request.Parser().body_limit(-1);
|
||||||
|
|
||||||
response.set(http::field::server, l_ServerHeader);
|
response.set(http::field::server, l_ServerHeader);
|
||||||
|
|
||||||
if (!EnsureValidHeaders(*m_Stream, buf, parser, response, m_ShuttingDown, yc)) {
|
if (!EnsureValidHeaders(buf, request, response, m_ShuttingDown, yc)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Seen = Utility::GetTime();
|
m_Seen = Utility::GetTime();
|
||||||
auto start (ch::steady_clock::now());
|
auto start (ch::steady_clock::now());
|
||||||
|
|
||||||
auto& request (parser.get());
|
|
||||||
|
|
||||||
{
|
{
|
||||||
auto method (http::string_to_verb(request["X-Http-Method-Override"]));
|
auto method (http::string_to_verb(request["X-Http-Method-Override"]));
|
||||||
|
|
||||||
@ -506,19 +456,20 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleExpect100(*m_Stream, request, yc);
|
HandleExpect100(request, response, yc);
|
||||||
|
|
||||||
auto authenticatedUser (m_ApiUser);
|
if (m_ApiUser) {
|
||||||
|
request.User(m_ApiUser);
|
||||||
if (!authenticatedUser) {
|
} else {
|
||||||
authenticatedUser = ApiUser::GetByAuthHeader(std::string(request[http::field::authorization]));
|
auto user = ApiUser::GetByAuthHeader(std::string(request[http::field::authorization]));
|
||||||
|
request.User(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log logMsg (LogInformation, "HttpServerConnection");
|
Log logMsg (LogInformation, "HttpServerConnection");
|
||||||
|
|
||||||
logMsg << "Request " << request.method_string() << ' ' << request.target()
|
logMsg << "Request " << request.method_string() << ' ' << request.target()
|
||||||
<< " (from " << m_PeerAddress
|
<< " (from " << m_PeerAddress
|
||||||
<< ", user: " << (authenticatedUser ? authenticatedUser->GetName() : "<unauthenticated>")
|
<< ", user: " << (request.User() ? request.User()->GetName() : "<unauthenticated>")
|
||||||
<< ", agent: " << request[http::field::user_agent]; //operator[] - Returns the value for a field, or "" if it does not exist.
|
<< ", agent: " << request[http::field::user_agent]; //operator[] - Returns the value for a field, or "" if it does not exist.
|
||||||
|
|
||||||
ch::steady_clock::duration cpuBoundWorkTime(0);
|
ch::steady_clock::duration cpuBoundWorkTime(0);
|
||||||
@ -531,29 +482,29 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
|
|||||||
logMsg << " took total " << ch::duration_cast<ch::milliseconds>(ch::steady_clock::now() - start).count() << "ms.";
|
logMsg << " took total " << ch::duration_cast<ch::milliseconds>(ch::steady_clock::now() - start).count() << "ms.";
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!HandleAccessControl(*m_Stream, request, response, yc)) {
|
if (!HandleAccessControl(request, response, yc)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EnsureAcceptHeader(*m_Stream, request, response, yc)) {
|
if (!EnsureAcceptHeader(request, response, yc)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EnsureAuthenticatedUser(*m_Stream, request, authenticatedUser, response, yc)) {
|
if (!EnsureAuthenticatedUser(request, response, yc)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EnsureValidBody(*m_Stream, buf, parser, authenticatedUser, response, m_ShuttingDown, yc)) {
|
if (!EnsureValidBody(buf, request, response, m_ShuttingDown, yc)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Seen = std::numeric_limits<decltype(m_Seen)>::max();
|
m_Seen = std::numeric_limits<decltype(m_Seen)>::max();
|
||||||
|
|
||||||
if (!ProcessRequest(*m_Stream, request, authenticatedUser, response, *this, m_HasStartedStreaming, m_WaitGroup, cpuBoundWorkTime, yc)) {
|
if (!ProcessRequest(*m_Stream, request, response, *this, m_HasStartedStreaming, m_WaitGroup, cpuBoundWorkTime, yc)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.version() != 11 || request[http::field::connection] == "close") {
|
if (!request.keep_alive()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,40 +3,10 @@
|
|||||||
#include "remote/httputility.hpp"
|
#include "remote/httputility.hpp"
|
||||||
#include "remote/url.hpp"
|
#include "remote/url.hpp"
|
||||||
#include "base/json.hpp"
|
#include "base/json.hpp"
|
||||||
#include "base/logger.hpp"
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
Dictionary::Ptr HttpUtility::FetchRequestParameters(const Url::Ptr& url, const std::string& body)
|
|
||||||
{
|
|
||||||
Dictionary::Ptr result;
|
|
||||||
|
|
||||||
if (!body.empty()) {
|
|
||||||
Log(LogDebug, "HttpUtility")
|
|
||||||
<< "Request body: '" << body << '\'';
|
|
||||||
|
|
||||||
result = JsonDecode(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
result = new Dictionary();
|
|
||||||
|
|
||||||
std::map<String, std::vector<String>> query;
|
|
||||||
for (const auto& kv : url->GetQuery()) {
|
|
||||||
query[kv.first].emplace_back(kv.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& kv : query) {
|
|
||||||
result->Set(kv.first, Array::FromVector(kv.second));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value HttpUtility::GetLastParameter(const Dictionary::Ptr& params, const String& key)
|
Value HttpUtility::GetLastParameter(const Dictionary::Ptr& params, const String& key)
|
||||||
{
|
{
|
||||||
Value varr = params->Get(key);
|
Value varr = params->Get(key);
|
||||||
@ -51,30 +21,3 @@ Value HttpUtility::GetLastParameter(const Dictionary::Ptr& params, const String&
|
|||||||
else
|
else
|
||||||
return arr->Get(arr->GetLength() - 1);
|
return arr->Get(arr->GetLength() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpUtility::SendJsonBody(boost::beast::http::response<boost::beast::http::string_body>& response, const Dictionary::Ptr& params, const Value& val)
|
|
||||||
{
|
|
||||||
namespace http = boost::beast::http;
|
|
||||||
|
|
||||||
response.set(http::field::content_type, "application/json");
|
|
||||||
response.body() = JsonEncode(val, params && GetLastParameter(params, "pretty"));
|
|
||||||
response.content_length(response.body().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void HttpUtility::SendJsonError(boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params, int code, const String& info, const String& diagnosticInformation)
|
|
||||||
{
|
|
||||||
Dictionary::Ptr result = new Dictionary({ { "error", code } });
|
|
||||||
|
|
||||||
if (!info.IsEmpty()) {
|
|
||||||
result->Set("status", info);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params && HttpUtility::GetLastParameter(params, "verbose") && !diagnosticInformation.IsEmpty()) {
|
|
||||||
result->Set("diagnostic_information", diagnosticInformation);
|
|
||||||
}
|
|
||||||
|
|
||||||
response.result(code);
|
|
||||||
|
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
|
||||||
}
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include "remote/url.hpp"
|
#include "remote/url.hpp"
|
||||||
#include "base/dictionary.hpp"
|
#include "base/dictionary.hpp"
|
||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace icinga
|
namespace icinga
|
||||||
{
|
{
|
||||||
@ -20,12 +19,7 @@ class HttpUtility
|
|||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Dictionary::Ptr FetchRequestParameters(const Url::Ptr& url, const std::string& body);
|
|
||||||
static Value GetLastParameter(const Dictionary::Ptr& params, const String& key);
|
static Value GetLastParameter(const Dictionary::Ptr& params, const String& key);
|
||||||
|
|
||||||
static void SendJsonBody(boost::beast::http::response<boost::beast::http::string_body>& response, const Dictionary::Ptr& params, const Value& val);
|
|
||||||
static void SendJsonError(boost::beast::http::response<boost::beast::http::string_body>& response, const Dictionary::Ptr& params, const int code,
|
|
||||||
const String& verbose = String(), const String& diagnosticInformation = String());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,36 +11,33 @@ REGISTER_URLHANDLER("/", InfoHandler);
|
|||||||
bool InfoHandler::HandleRequest(
|
bool InfoHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr&,
|
const WaitGroup::Ptr&,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() > 2)
|
if (request.Url()->GetPath().size() > 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() != http::verb::get)
|
if (request.method() != http::verb::get)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (url->GetPath().empty()) {
|
if (request.Url()->GetPath().empty()) {
|
||||||
response.result(http::status::found);
|
response.result(http::status::found);
|
||||||
response.set(http::field::location, "/v1");
|
response.set(http::field::location, "/v1");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url->GetPath()[0] != "v1" || url->GetPath().size() != 1)
|
if (request.Url()->GetPath()[0] != "v1" || request.Url()->GetPath().size() != 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
|
|
||||||
std::vector<String> permInfo;
|
std::vector<String> permInfo;
|
||||||
Array::Ptr permissions = user->GetPermissions();
|
Array::Ptr permissions = request.User()->GetPermissions();
|
||||||
|
|
||||||
if (permissions) {
|
if (permissions) {
|
||||||
ObjectLock olock(permissions);
|
ObjectLock olock(permissions);
|
||||||
@ -63,7 +60,7 @@ bool InfoHandler::HandleRequest(
|
|||||||
|
|
||||||
if (request[http::field::accept] == "application/json") {
|
if (request[http::field::accept] == "application/json") {
|
||||||
Dictionary::Ptr result1 = new Dictionary({
|
Dictionary::Ptr result1 = new Dictionary({
|
||||||
{ "user", user->GetName() },
|
{ "user", request.User()->GetName() },
|
||||||
{ "permissions", Array::FromVector(permInfo) },
|
{ "permissions", Array::FromVector(permInfo) },
|
||||||
{ "version", Application::GetAppVersion() },
|
{ "version", Application::GetAppVersion() },
|
||||||
{ "info", "More information about API requests is available in the documentation at https://icinga.com/docs/icinga2/latest/" }
|
{ "info", "More information about API requests is available in the documentation at https://icinga.com/docs/icinga2/latest/" }
|
||||||
@ -73,27 +70,27 @@ bool InfoHandler::HandleRequest(
|
|||||||
{ "results", new Array({ result1 }) }
|
{ "results", new Array({ result1 }) }
|
||||||
});
|
});
|
||||||
|
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
} else {
|
} else {
|
||||||
response.set(http::field::content_type, "text/html");
|
response.set(http::field::content_type, "text/html");
|
||||||
|
|
||||||
String body = "<html><head><title>Icinga 2</title></head><h1>Hello from Icinga 2 (Version: " + Application::GetAppVersion() + ")!</h1>";
|
auto & body = response.body();
|
||||||
body += "<p>You are authenticated as <b>" + user->GetName() + "</b>. ";
|
body << "<html><head><title>Icinga 2</title></head><h1>Hello from Icinga 2 (Version: "
|
||||||
|
<< Application::GetAppVersion() << ")!</h1>";
|
||||||
|
body << "<p>You are authenticated as <b>" << request.User()->GetName() << "</b>. ";
|
||||||
|
|
||||||
if (!permInfo.empty()) {
|
if (!permInfo.empty()) {
|
||||||
body += "Your user has the following permissions:</p> <ul>";
|
body << "Your user has the following permissions:</p> <ul>";
|
||||||
|
|
||||||
for (const String& perm : permInfo) {
|
for (const String& perm : permInfo) {
|
||||||
body += "<li>" + perm + "</li>";
|
body << "<li>" << perm << "</li>";
|
||||||
}
|
}
|
||||||
|
|
||||||
body += "</ul>";
|
body << "</ul>";
|
||||||
} else
|
} else
|
||||||
body += "Your user does not have any permissions.</p>";
|
body << "Your user does not have any permissions.</p>";
|
||||||
|
|
||||||
body += R"(<p>More information about API requests is available in the <a href="https://icinga.com/docs/icinga2/latest/" target="_blank">documentation</a>.</p></html>)";
|
body << R"(<p>More information about API requests is available in the <a href="https://icinga.com/docs/icinga2/latest/" target="_blank">documentation</a>.</p></html>)";
|
||||||
response.body() = body;
|
|
||||||
response.content_length(response.body().size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -16,11 +16,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
@ -20,18 +20,15 @@ REGISTER_URLHANDLER("/v1/debug/malloc_info", MallocInfoHandler);
|
|||||||
bool MallocInfoHandler::HandleRequest(
|
bool MallocInfoHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr&,
|
const WaitGroup::Ptr&,
|
||||||
AsioTlsStream&,
|
AsioTlsStream&,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context&,
|
boost::asio::yield_context&,
|
||||||
HttpServerConnection&
|
HttpServerConnection&
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() != 3) {
|
if (request.Url()->GetPath().size() != 3) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,10 +36,10 @@ bool MallocInfoHandler::HandleRequest(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FilterUtility::CheckPermission(user, "debug");
|
FilterUtility::CheckPermission(request.User(), "debug");
|
||||||
|
|
||||||
#ifndef HAVE_MALLOC_INFO
|
#ifndef HAVE_MALLOC_INFO
|
||||||
HttpUtility::SendJsonError(response, params, 501, "malloc_info(3) not available.");
|
response.SendJsonError(request.Params(), 501, "malloc_info(3) not available.");
|
||||||
#else /* HAVE_MALLOC_INFO */
|
#else /* HAVE_MALLOC_INFO */
|
||||||
char* buf = nullptr;
|
char* buf = nullptr;
|
||||||
size_t bufSize = 0;
|
size_t bufSize = 0;
|
||||||
@ -87,8 +84,7 @@ bool MallocInfoHandler::HandleRequest(
|
|||||||
|
|
||||||
response.result(200);
|
response.result(200);
|
||||||
response.set(http::field::content_type, "application/xml");
|
response.set(http::field::content_type, "application/xml");
|
||||||
response.body() = std::string(buf, bufSize);
|
response.body() << std::string(buf, bufSize);
|
||||||
response.content_length(response.body().size());
|
|
||||||
#endif /* HAVE_MALLOC_INFO */
|
#endif /* HAVE_MALLOC_INFO */
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -15,11 +15,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
@ -16,27 +16,24 @@ REGISTER_URLHANDLER("/v1/objects", ModifyObjectHandler);
|
|||||||
bool ModifyObjectHandler::HandleRequest(
|
bool ModifyObjectHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() < 3 || url->GetPath().size() > 4)
|
if (request.Url()->GetPath().size() < 3 || request.Url()->GetPath().size() > 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() != http::verb::post)
|
if (request.method() != http::verb::post)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Type::Ptr type = FilterUtility::TypeFromPluralName(url->GetPath()[2]);
|
Type::Ptr type = FilterUtility::TypeFromPluralName(request.Url()->GetPath()[2]);
|
||||||
|
|
||||||
if (!type) {
|
if (!type) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid type specified.");
|
response.SendJsonError(request.Params(), 400, "Invalid type specified.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,29 +41,29 @@ bool ModifyObjectHandler::HandleRequest(
|
|||||||
qd.Types.insert(type->GetName());
|
qd.Types.insert(type->GetName());
|
||||||
qd.Permission = "objects/modify/" + type->GetName();
|
qd.Permission = "objects/modify/" + type->GetName();
|
||||||
|
|
||||||
params->Set("type", type->GetName());
|
request.Params()->Set("type", type->GetName());
|
||||||
|
|
||||||
if (url->GetPath().size() >= 4) {
|
if (request.Url()->GetPath().size() >= 4) {
|
||||||
String attr = type->GetName();
|
String attr = type->GetName();
|
||||||
boost::algorithm::to_lower(attr);
|
boost::algorithm::to_lower(attr);
|
||||||
params->Set(attr, url->GetPath()[3]);
|
request.Params()->Set(attr, request.Url()->GetPath()[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Value> objs;
|
std::vector<Value> objs;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objs = FilterUtility::GetFilterTargets(qd, params, user);
|
objs = FilterUtility::GetFilterTargets(qd, request.Params(), request.User());
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 404,
|
response.SendJsonError(request.Params(), 404,
|
||||||
"No objects found.",
|
"No objects found.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value attrsVal = params->Get("attrs");
|
Value attrsVal = request.Params()->Get("attrs");
|
||||||
|
|
||||||
if (attrsVal.GetReflectionType() != Dictionary::TypeInstance && attrsVal.GetType() != ValueEmpty) {
|
if (attrsVal.GetReflectionType() != Dictionary::TypeInstance && attrsVal.GetType() != ValueEmpty) {
|
||||||
HttpUtility::SendJsonError(response, params, 400,
|
response.SendJsonError(request.Params(), 400,
|
||||||
"Invalid type for 'attrs' attribute specified. Dictionary type is required."
|
"Invalid type for 'attrs' attribute specified. Dictionary type is required."
|
||||||
"Or is this a POST query and you missed adding a 'X-HTTP-Method-Override: GET' header?");
|
"Or is this a POST query and you missed adding a 'X-HTTP-Method-Override: GET' header?");
|
||||||
return true;
|
return true;
|
||||||
@ -74,10 +71,10 @@ bool ModifyObjectHandler::HandleRequest(
|
|||||||
|
|
||||||
Dictionary::Ptr attrs = attrsVal;
|
Dictionary::Ptr attrs = attrsVal;
|
||||||
|
|
||||||
Value restoreAttrsVal = params->Get("restore_attrs");
|
Value restoreAttrsVal = request.Params()->Get("restore_attrs");
|
||||||
|
|
||||||
if (restoreAttrsVal.GetReflectionType() != Array::TypeInstance && restoreAttrsVal.GetType() != ValueEmpty) {
|
if (restoreAttrsVal.GetReflectionType() != Array::TypeInstance && restoreAttrsVal.GetType() != ValueEmpty) {
|
||||||
HttpUtility::SendJsonError(response, params, 400,
|
response.SendJsonError(request.Params(), 400,
|
||||||
"Invalid type for 'restore_attrs' attribute specified. Array type is required.");
|
"Invalid type for 'restore_attrs' attribute specified. Array type is required.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -85,21 +82,18 @@ bool ModifyObjectHandler::HandleRequest(
|
|||||||
Array::Ptr restoreAttrs = restoreAttrsVal;
|
Array::Ptr restoreAttrs = restoreAttrsVal;
|
||||||
|
|
||||||
if (!(attrs || restoreAttrs)) {
|
if (!(attrs || restoreAttrs)) {
|
||||||
HttpUtility::SendJsonError(response, params, 400,
|
response.SendJsonError(request.Params(), 400,
|
||||||
"Missing both 'attrs' and 'restore_attrs'. "
|
"Missing both 'attrs' and 'restore_attrs'. "
|
||||||
"Or is this a POST query and you missed adding a 'X-HTTP-Method-Override: GET' header?");
|
"Or is this a POST query and you missed adding a 'X-HTTP-Method-Override: GET' header?");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool verbose = false;
|
bool verbose = request.IsVerbose();
|
||||||
|
|
||||||
if (params)
|
|
||||||
verbose = HttpUtility::GetLastParameter(params, "verbose");
|
|
||||||
|
|
||||||
ConfigObjectsSharedLock lock (std::try_to_lock);
|
ConfigObjectsSharedLock lock (std::try_to_lock);
|
||||||
|
|
||||||
if (!lock) {
|
if (!lock) {
|
||||||
HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading");
|
response.SendJsonError(request.Params(), 503, "Icinga is reloading");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +101,7 @@ bool ModifyObjectHandler::HandleRequest(
|
|||||||
|
|
||||||
std::shared_lock wgLock{*waitGroup, std::try_to_lock};
|
std::shared_lock wgLock{*waitGroup, std::try_to_lock};
|
||||||
if (!wgLock) {
|
if (!wgLock) {
|
||||||
HttpUtility::SendJsonError(response, params, 503, "Shutting down.");
|
response.SendJsonError(request.Params(), 503, "Shutting down.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +179,7 @@ bool ModifyObjectHandler::HandleRequest(
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
@ -91,27 +91,24 @@ Dictionary::Ptr ObjectQueryHandler::SerializeObjectAttrs(const Object::Ptr& obje
|
|||||||
bool ObjectQueryHandler::HandleRequest(
|
bool ObjectQueryHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr&,
|
const WaitGroup::Ptr&,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() < 3 || url->GetPath().size() > 4)
|
if (request.Url()->GetPath().size() < 3 || request.Url()->GetPath().size() > 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() != http::verb::get)
|
if (request.method() != http::verb::get)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Type::Ptr type = FilterUtility::TypeFromPluralName(url->GetPath()[2]);
|
Type::Ptr type = FilterUtility::TypeFromPluralName(request.Url()->GetPath()[2]);
|
||||||
|
|
||||||
if (!type) {
|
if (!type) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid type specified.");
|
response.SendJsonError(request.Params(), 400, "Invalid type specified.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,45 +119,45 @@ bool ObjectQueryHandler::HandleRequest(
|
|||||||
Array::Ptr uattrs, ujoins, umetas;
|
Array::Ptr uattrs, ujoins, umetas;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
uattrs = params->Get("attrs");
|
uattrs = request.Params()->Get("attrs");
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
HttpUtility::SendJsonError(response, params, 400,
|
response.SendJsonError(request.Params(), 400,
|
||||||
"Invalid type for 'attrs' attribute specified. Array type is required.");
|
"Invalid type for 'attrs' attribute specified. Array type is required.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ujoins = params->Get("joins");
|
ujoins = request.Params()->Get("joins");
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
HttpUtility::SendJsonError(response, params, 400,
|
response.SendJsonError(request.Params(), 400,
|
||||||
"Invalid type for 'joins' attribute specified. Array type is required.");
|
"Invalid type for 'joins' attribute specified. Array type is required.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
umetas = params->Get("meta");
|
umetas = request.Params()->Get("meta");
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
HttpUtility::SendJsonError(response, params, 400,
|
response.SendJsonError(request.Params(), 400,
|
||||||
"Invalid type for 'meta' attribute specified. Array type is required.");
|
"Invalid type for 'meta' attribute specified. Array type is required.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allJoins = HttpUtility::GetLastParameter(params, "all_joins");
|
bool allJoins = request.GetLastParameter("all_joins");
|
||||||
|
|
||||||
params->Set("type", type->GetName());
|
request.Params()->Set("type", type->GetName());
|
||||||
|
|
||||||
if (url->GetPath().size() >= 4) {
|
if (request.Url()->GetPath().size() >= 4) {
|
||||||
String attr = type->GetName();
|
String attr = type->GetName();
|
||||||
boost::algorithm::to_lower(attr);
|
boost::algorithm::to_lower(attr);
|
||||||
params->Set(attr, url->GetPath()[3]);
|
request.Params()->Set(attr, request.Url()->GetPath()[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Value> objs;
|
std::vector<Value> objs;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objs = FilterUtility::GetFilterTargets(qd, params, user);
|
objs = FilterUtility::GetFilterTargets(qd, request.Params(), request.User());
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 404,
|
response.SendJsonError(request.Params(), 404,
|
||||||
"No objects found.",
|
"No objects found.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
return true;
|
return true;
|
||||||
@ -218,7 +215,7 @@ bool ObjectQueryHandler::HandleRequest(
|
|||||||
} else if (meta == "location") {
|
} else if (meta == "location") {
|
||||||
metaAttrs.emplace_back("location", obj->GetSourceLocation());
|
metaAttrs.emplace_back("location", obj->GetSourceLocation());
|
||||||
} else {
|
} else {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid field specified for meta: " + meta);
|
response.SendJsonError(request.Params(), 400, "Invalid field specified for meta: " + meta);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,7 +226,7 @@ bool ObjectQueryHandler::HandleRequest(
|
|||||||
try {
|
try {
|
||||||
result1.emplace_back("attrs", SerializeObjectAttrs(obj, String(), uattrs, false, false));
|
result1.emplace_back("attrs", SerializeObjectAttrs(obj, String(), uattrs, false, false));
|
||||||
} catch (const ScriptError& ex) {
|
} catch (const ScriptError& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, ex.what());
|
response.SendJsonError(request.Params(), 400, ex.what());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,14 +237,14 @@ bool ObjectQueryHandler::HandleRequest(
|
|||||||
int fid = type->GetFieldId(joinAttr);
|
int fid = type->GetFieldId(joinAttr);
|
||||||
|
|
||||||
if (fid < 0) {
|
if (fid < 0) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid field specified for join: " + joinAttr);
|
response.SendJsonError(request.Params(), 400, "Invalid field specified for join: " + joinAttr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Field field = type->GetFieldInfo(fid);
|
Field field = type->GetFieldInfo(fid);
|
||||||
|
|
||||||
if (!(field.Attributes & FANavigation)) {
|
if (!(field.Attributes & FANavigation)) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Not a joinable field: " + joinAttr);
|
response.SendJsonError(request.Params(), 400, "Not a joinable field: " + joinAttr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +261,7 @@ bool ObjectQueryHandler::HandleRequest(
|
|||||||
String permission = "objects/query/" + reflectionType->GetName();
|
String permission = "objects/query/" + reflectionType->GetName();
|
||||||
|
|
||||||
std::unique_ptr<Expression> permissionFilter;
|
std::unique_ptr<Expression> permissionFilter;
|
||||||
granted = FilterUtility::HasPermission(user, permission, &permissionFilter);
|
granted = FilterUtility::HasPermission(request.User(), permission, &permissionFilter);
|
||||||
|
|
||||||
it = typePermissions.insert({reflectionType.get(), std::make_pair(granted, std::move(permissionFilter))}).first;
|
it = typePermissions.insert({reflectionType.get(), std::make_pair(granted, std::move(permissionFilter))}).first;
|
||||||
}
|
}
|
||||||
@ -304,7 +301,7 @@ bool ObjectQueryHandler::HandleRequest(
|
|||||||
try {
|
try {
|
||||||
joins.emplace_back(prefix, SerializeObjectAttrs(joinedObj, prefix, ujoins, true, allJoins));
|
joins.emplace_back(prefix, SerializeObjectAttrs(joinedObj, prefix, ujoins, true, allJoins));
|
||||||
} catch (const ScriptError& ex) {
|
} catch (const ScriptError& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, ex.what());
|
response.SendJsonError(request.Params(), 400, ex.what());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -319,7 +316,7 @@ bool ObjectQueryHandler::HandleRequest(
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(request.Params(), result);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
@ -71,18 +71,15 @@ public:
|
|||||||
bool StatusHandler::HandleRequest(
|
bool StatusHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr&,
|
const WaitGroup::Ptr&,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() > 3)
|
if (request.Url()->GetPath().size() > 3)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() != http::verb::get)
|
if (request.method() != http::verb::get)
|
||||||
@ -93,17 +90,17 @@ bool StatusHandler::HandleRequest(
|
|||||||
qd.Provider = new StatusTargetProvider();
|
qd.Provider = new StatusTargetProvider();
|
||||||
qd.Permission = "status/query";
|
qd.Permission = "status/query";
|
||||||
|
|
||||||
params->Set("type", "Status");
|
request.Params()->Set("type", "Status");
|
||||||
|
|
||||||
if (url->GetPath().size() >= 3)
|
if (request.Url()->GetPath().size() >= 3)
|
||||||
params->Set("status", url->GetPath()[2]);
|
request.Params()->Set("status", request.Url()->GetPath()[2]);
|
||||||
|
|
||||||
std::vector<Value> objs;
|
std::vector<Value> objs;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objs = FilterUtility::GetFilterTargets(qd, params, user);
|
objs = FilterUtility::GetFilterTargets(qd, request.Params(), request.User());
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 404,
|
response.SendJsonError(request.Params(), 404,
|
||||||
"No objects found.",
|
"No objects found.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
return true;
|
return true;
|
||||||
@ -114,7 +111,7 @@ bool StatusHandler::HandleRequest(
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
@ -78,27 +78,24 @@ public:
|
|||||||
bool TemplateQueryHandler::HandleRequest(
|
bool TemplateQueryHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr&,
|
const WaitGroup::Ptr&,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() < 3 || url->GetPath().size() > 4)
|
if (request.Url()->GetPath().size() < 3 || request.Url()->GetPath().size() > 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() != http::verb::get)
|
if (request.method() != http::verb::get)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Type::Ptr type = FilterUtility::TypeFromPluralName(url->GetPath()[2]);
|
Type::Ptr type = FilterUtility::TypeFromPluralName(request.Url()->GetPath()[2]);
|
||||||
|
|
||||||
if (!type) {
|
if (!type) {
|
||||||
HttpUtility::SendJsonError(response, params, 400, "Invalid type specified.");
|
response.SendJsonError(request.Params(), 400, "Invalid type specified.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,20 +104,20 @@ bool TemplateQueryHandler::HandleRequest(
|
|||||||
qd.Permission = "templates/query/" + type->GetName();
|
qd.Permission = "templates/query/" + type->GetName();
|
||||||
qd.Provider = new TemplateTargetProvider();
|
qd.Provider = new TemplateTargetProvider();
|
||||||
|
|
||||||
params->Set("type", type->GetName());
|
request.Params()->Set("type", type->GetName());
|
||||||
|
|
||||||
if (url->GetPath().size() >= 4) {
|
if (request.Url()->GetPath().size() >= 4) {
|
||||||
String attr = type->GetName();
|
String attr = type->GetName();
|
||||||
boost::algorithm::to_lower(attr);
|
boost::algorithm::to_lower(attr);
|
||||||
params->Set(attr, url->GetPath()[3]);
|
request.Params()->Set(attr, request.Url()->GetPath()[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Value> objs;
|
std::vector<Value> objs;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objs = FilterUtility::GetFilterTargets(qd, params, user, "tmpl");
|
objs = FilterUtility::GetFilterTargets(qd, request.Params(), request.User(), "tmpl");
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 404,
|
response.SendJsonError(request.Params(), 404,
|
||||||
"No templates found.",
|
"No templates found.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
return true;
|
return true;
|
||||||
@ -131,7 +128,7 @@ bool TemplateQueryHandler::HandleRequest(
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
@ -49,18 +49,15 @@ public:
|
|||||||
bool TypeQueryHandler::HandleRequest(
|
bool TypeQueryHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr&,
|
const WaitGroup::Ptr&,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() > 3)
|
if (request.Url()->GetPath().size() > 3)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() != http::verb::get)
|
if (request.method() != http::verb::get)
|
||||||
@ -71,20 +68,20 @@ bool TypeQueryHandler::HandleRequest(
|
|||||||
qd.Permission = "types";
|
qd.Permission = "types";
|
||||||
qd.Provider = new TypeTargetProvider();
|
qd.Provider = new TypeTargetProvider();
|
||||||
|
|
||||||
if (params->Contains("type"))
|
if (request.Params()->Contains("type"))
|
||||||
params->Set("name", params->Get("type"));
|
request.Params()->Set("name", request.Params()->Get("type"));
|
||||||
|
|
||||||
params->Set("type", "Type");
|
request.Params()->Set("type", "Type");
|
||||||
|
|
||||||
if (url->GetPath().size() >= 3)
|
if (request.Url()->GetPath().size() >= 3)
|
||||||
params->Set("name", url->GetPath()[2]);
|
request.Params()->Set("name", request.Url()->GetPath()[2]);
|
||||||
|
|
||||||
std::vector<Value> objs;
|
std::vector<Value> objs;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objs = FilterUtility::GetFilterTargets(qd, params, user);
|
objs = FilterUtility::GetFilterTargets(qd, request.Params(), request.User());
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 404,
|
response.SendJsonError(request.Params(), 404,
|
||||||
"No objects found.",
|
"No objects found.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
return true;
|
return true;
|
||||||
@ -151,7 +148,7 @@ bool TypeQueryHandler::HandleRequest(
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
@ -59,18 +59,15 @@ public:
|
|||||||
bool VariableQueryHandler::HandleRequest(
|
bool VariableQueryHandler::HandleRequest(
|
||||||
const WaitGroup::Ptr&,
|
const WaitGroup::Ptr&,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
if (url->GetPath().size() > 3)
|
if (request.Url()->GetPath().size() > 3)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (request.method() != http::verb::get)
|
if (request.method() != http::verb::get)
|
||||||
@ -81,17 +78,17 @@ bool VariableQueryHandler::HandleRequest(
|
|||||||
qd.Permission = "variables";
|
qd.Permission = "variables";
|
||||||
qd.Provider = new VariableTargetProvider();
|
qd.Provider = new VariableTargetProvider();
|
||||||
|
|
||||||
params->Set("type", "Variable");
|
request.Params()->Set("type", "Variable");
|
||||||
|
|
||||||
if (url->GetPath().size() >= 3)
|
if (request.Url()->GetPath().size() >= 3)
|
||||||
params->Set("variable", url->GetPath()[2]);
|
request.Params()->Set("variable", request.Url()->GetPath()[2]);
|
||||||
|
|
||||||
std::vector<Value> objs;
|
std::vector<Value> objs;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objs = FilterUtility::GetFilterTargets(qd, params, user, "variable");
|
objs = FilterUtility::GetFilterTargets(qd, request.Params(), request.User(), "variable");
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
HttpUtility::SendJsonError(response, params, 404,
|
response.SendJsonError(request.Params(), 404,
|
||||||
"No variables found.",
|
"No variables found.",
|
||||||
DiagnosticInformation(ex));
|
DiagnosticInformation(ex));
|
||||||
return true;
|
return true;
|
||||||
@ -115,7 +112,7 @@ bool VariableQueryHandler::HandleRequest(
|
|||||||
});
|
});
|
||||||
|
|
||||||
response.result(http::status::ok);
|
response.result(http::status::ok);
|
||||||
HttpUtility::SendJsonBody(response, params, result);
|
response.SendJsonBody(result, request.IsPretty());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,8 @@ public:
|
|||||||
bool HandleRequest(
|
bool HandleRequest(
|
||||||
const WaitGroup::Ptr& waitGroup,
|
const WaitGroup::Ptr& waitGroup,
|
||||||
AsioTlsStream& stream,
|
AsioTlsStream& stream,
|
||||||
const ApiUser::Ptr& user,
|
HttpRequest& request,
|
||||||
boost::beast::http::request<boost::beast::http::string_body>& request,
|
HttpResponse& response,
|
||||||
const Url::Ptr& url,
|
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
|
||||||
const Dictionary::Ptr& params,
|
|
||||||
boost::asio::yield_context& yc,
|
boost::asio::yield_context& yc,
|
||||||
HttpServerConnection& server
|
HttpServerConnection& server
|
||||||
) override;
|
) override;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user