diff --git a/lib/remote/actionshandler.cpp b/lib/remote/actionshandler.cpp index 76874cee48f..8d40e7ea127 100644 --- a/lib/remote/actionshandler.cpp +++ b/lib/remote/actionshandler.cpp @@ -37,7 +37,7 @@ bool ActionsHandler::HandleRequest( ApiAction::Ptr action = ApiAction::GetByName(actionName); if (!action) { - HttpUtility::SendJsonError(response, params, 404, "Action '" + actionName + "' does not exist."); + HttpUtility::SendJsonError(response, params, 404, yc, "Action '" + actionName + "' does not exist."); return true; } @@ -55,14 +55,14 @@ bool ActionsHandler::HandleRequest( try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, params, 404, + HttpUtility::SendJsonError(response, params, 404, yc, "No objects found.", DiagnosticInformation(ex)); return true; } if (objs.empty()) { - HttpUtility::SendJsonError(response, params, 404, + HttpUtility::SendJsonError(response, params, 404, yc, "No objects found."); return true; } @@ -83,7 +83,7 @@ bool ActionsHandler::HandleRequest( std::shared_lock wgLock{*waitGroup, std::try_to_lock}; if (!wgLock) { - HttpUtility::SendJsonError(response, params, 503, "Shutting down."); + HttpUtility::SendJsonError(response, params, 503, yc, "Shutting down."); return true; } diff --git a/lib/remote/configfileshandler.cpp b/lib/remote/configfileshandler.cpp index 28ea8be750d..90baa03d9cb 100644 --- a/lib/remote/configfileshandler.cpp +++ b/lib/remote/configfileshandler.cpp @@ -44,7 +44,7 @@ bool ConfigFilesHandler::HandleRequest( } 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'."); + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid Accept header. Either remove the Accept header or set it to 'application/octet-stream'."); return true; } @@ -54,26 +54,26 @@ bool ConfigFilesHandler::HandleRequest( String stageName = HttpUtility::GetLastParameter(params, "stage"); if (!ConfigPackageUtility::ValidatePackageName(packageName)) { - HttpUtility::SendJsonError(response, params, 400, "Invalid package name."); + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid package name."); return true; } if (!ConfigPackageUtility::ValidateStageName(stageName)) { - HttpUtility::SendJsonError(response, params, 400, "Invalid stage name."); + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid stage name."); return true; } String relativePath = HttpUtility::GetLastParameter(params, "path"); if (ConfigPackageUtility::ContainsDotDot(relativePath)) { - HttpUtility::SendJsonError(response, params, 400, "Path contains '..' (not allowed)."); + HttpUtility::SendJsonError(response, params, 400, yc, "Path contains '..' (not allowed)."); return true; } String path = ConfigPackageUtility::GetPackageDir() + "/" + packageName + "/" + stageName + "/" + relativePath; if (!Utility::PathExists(path)) { - HttpUtility::SendJsonError(response, params, 404, "Path not found."); + HttpUtility::SendJsonError(response, params, 404, yc, "Path not found."); return true; } @@ -82,7 +82,7 @@ bool ConfigFilesHandler::HandleRequest( response.set(http::field::content_type, "application/octet-stream"); response.SendFile(path, yc); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, params, 500, "Could not read file.", + HttpUtility::SendJsonError(response, params, 500, yc, "Could not read file.", DiagnosticInformation(ex)); } diff --git a/lib/remote/configpackageshandler.cpp b/lib/remote/configpackageshandler.cpp index 7e0dc976d1d..67707145525 100644 --- a/lib/remote/configpackageshandler.cpp +++ b/lib/remote/configpackageshandler.cpp @@ -31,9 +31,9 @@ bool ConfigPackagesHandler::HandleRequest( if (request.method() == http::verb::get) HandleGet(request, response, yc); else if (request.method() == http::verb::post) - HandlePost(request, response); + HandlePost(request, response, yc); else if (request.method() == http::verb::delete_) - HandleDelete(request, response); + HandleDelete(request, response, yc); else return false; @@ -55,7 +55,7 @@ void ConfigPackagesHandler::HandleGet(const HttpApiRequest& request, HttpApiResp try { packages = ConfigPackageUtility::GetPackages(); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, params, 500, "Could not retrieve packages.", + HttpUtility::SendJsonError(response, params, 500, yc, "Could not retrieve packages.", DiagnosticInformation(ex)); return; } @@ -90,7 +90,7 @@ void ConfigPackagesHandler::HandleGet(const HttpApiRequest& request, HttpApiResp HttpUtility::SendJsonBody(response, params, result, yc); } -void ConfigPackagesHandler::HandlePost(const HttpApiRequest& request, HttpApiResponse& response) +void ConfigPackagesHandler::HandlePost(const HttpApiRequest& request, HttpApiResponse& response, boost::asio::yield_context& yc) { namespace http = boost::beast::http; @@ -106,13 +106,13 @@ void ConfigPackagesHandler::HandlePost(const HttpApiRequest& request, HttpApiRes String packageName = HttpUtility::GetLastParameter(params, "package"); if (!ConfigPackageUtility::ValidatePackageName(packageName)) { - HttpUtility::SendJsonError(response, params, 400, "Invalid package name '" + packageName + "'."); + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid package name '" + packageName + "'."); return; } ConfigObjectsSharedLock configObjectsSharedLock(std::try_to_lock); if (!configObjectsSharedLock) { - HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading"); + HttpUtility::SendJsonError(response, params, 503, yc, "Icinga is reloading"); return; } @@ -121,7 +121,7 @@ void ConfigPackagesHandler::HandlePost(const HttpApiRequest& request, HttpApiRes ConfigPackageUtility::CreatePackage(packageName); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, params, 500, "Could not create package '" + packageName + "'.", + HttpUtility::SendJsonError(response, params, 500, yc, "Could not create package '" + packageName + "'.", DiagnosticInformation(ex)); return; } @@ -137,10 +137,10 @@ void ConfigPackagesHandler::HandlePost(const HttpApiRequest& request, HttpApiRes }); response.result(http::status::ok); - HttpUtility::SendJsonBody(response, params, result); + HttpUtility::SendJsonBody(response, params, result, yc); } -void ConfigPackagesHandler::HandleDelete(const HttpApiRequest& request, HttpApiResponse& response) +void ConfigPackagesHandler::HandleDelete(const HttpApiRequest& request, HttpApiResponse& response, boost::asio::yield_context& yc) { namespace http = boost::beast::http; @@ -156,20 +156,20 @@ void ConfigPackagesHandler::HandleDelete(const HttpApiRequest& request, HttpApiR String packageName = HttpUtility::GetLastParameter(params, "package"); if (!ConfigPackageUtility::ValidatePackageName(packageName)) { - HttpUtility::SendJsonError(response, params, 400, "Invalid package name '" + packageName + "'."); + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid package name '" + packageName + "'."); return; } ConfigObjectsSharedLock lock(std::try_to_lock); if (!lock) { - HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading"); + HttpUtility::SendJsonError(response, params, 503, yc, "Icinga is reloading"); return; } try { ConfigPackageUtility::DeletePackage(packageName); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, params, 500, "Failed to delete package '" + packageName + "'.", + HttpUtility::SendJsonError(response, params, 500, yc, "Failed to delete package '" + packageName + "'.", DiagnosticInformation(ex)); return; } @@ -185,5 +185,5 @@ void ConfigPackagesHandler::HandleDelete(const HttpApiRequest& request, HttpApiR }); response.result(http::status::ok); - HttpUtility::SendJsonBody(response, params, result); + HttpUtility::SendJsonBody(response, params, result, yc); } diff --git a/lib/remote/configpackageshandler.hpp b/lib/remote/configpackageshandler.hpp index e8742ebd1b0..47aeb46c8f1 100644 --- a/lib/remote/configpackageshandler.hpp +++ b/lib/remote/configpackageshandler.hpp @@ -23,8 +23,8 @@ class ConfigPackagesHandler final : public HttpHandler private: void HandleGet(const HttpApiRequest& request, HttpApiResponse& response, boost::asio::yield_context& yc); - void HandlePost(const HttpApiRequest& request, HttpApiResponse& response); - void HandleDelete(const HttpApiRequest& request, HttpApiResponse& response); + void HandlePost(const HttpApiRequest& request, HttpApiResponse& response, boost::asio::yield_context& yc); + void HandleDelete(const HttpApiRequest& request, HttpApiResponse& response, boost::asio::yield_context& yc); }; diff --git a/lib/remote/configstageshandler.cpp b/lib/remote/configstageshandler.cpp index 8bcd16bbeb0..09389f139b5 100644 --- a/lib/remote/configstageshandler.cpp +++ b/lib/remote/configstageshandler.cpp @@ -38,9 +38,9 @@ bool ConfigStagesHandler::HandleRequest( if (request.method() == http::verb::get) HandleGet(request, response, yc); else if (request.method() == http::verb::post) - HandlePost(request, response); + HandlePost(request, response, yc); else if (request.method() == http::verb::delete_) - HandleDelete(request, response); + HandleDelete(request, response, yc); else return false; @@ -67,10 +67,10 @@ void ConfigStagesHandler::HandleGet(const HttpApiRequest& request, HttpApiRespon String stageName = HttpUtility::GetLastParameter(params, "stage"); if (!ConfigPackageUtility::ValidatePackageName(packageName)) - return HttpUtility::SendJsonError(response, params, 400, "Invalid package name '" + packageName + "'."); + return HttpUtility::SendJsonError(response, params, 400, yc, "Invalid package name '" + packageName + "'."); if (!ConfigPackageUtility::ValidateStageName(stageName)) - return HttpUtility::SendJsonError(response, params, 400, "Invalid stage name '" + stageName + "'."); + return HttpUtility::SendJsonError(response, params, 400, yc, "Invalid stage name '" + stageName + "'."); std::vector > paths = ConfigPackageUtility::GetFiles(packageName, stageName); @@ -90,7 +90,7 @@ void ConfigStagesHandler::HandleGet(const HttpApiRequest& request, HttpApiRespon HttpUtility::SendJsonBody(response, params, result, yc); } -void ConfigStagesHandler::HandlePost(const HttpApiRequest& request, HttpApiResponse& response) +void ConfigStagesHandler::HandlePost(const HttpApiRequest& request, HttpApiResponse& response, boost::asio::yield_context& yc) { namespace http = boost::beast::http; @@ -106,7 +106,7 @@ void ConfigStagesHandler::HandlePost(const HttpApiRequest& request, HttpApiRespo String packageName = HttpUtility::GetLastParameter(params, "package"); if (!ConfigPackageUtility::ValidatePackageName(packageName)) - return HttpUtility::SendJsonError(response, params, 400, "Invalid package name '" + packageName + "'."); + return HttpUtility::SendJsonError(response, params, 400, yc, "Invalid package name '" + packageName + "'."); bool reload = true; @@ -131,7 +131,7 @@ void ConfigStagesHandler::HandlePost(const HttpApiRequest& request, HttpApiRespo ConfigObjectsSharedLock configObjectsSharedLock(std::try_to_lock); if (!configObjectsSharedLock) { - HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading"); + HttpUtility::SendJsonError(response, params, 503, yc, "Icinga is reloading"); return; } @@ -152,7 +152,7 @@ void ConfigStagesHandler::HandlePost(const HttpApiRequest& request, HttpApiRespo */ if (l_RunningPackageUpdates && l_LastReloadFailedTime == currentReloadFailedTime) { return HttpUtility::SendJsonError( - response, params, 423, + response, params, 423, yc, "Conflicting request, there is already an ongoing package update in progress. Please try it again later." ); } @@ -173,7 +173,7 @@ void ConfigStagesHandler::HandlePost(const HttpApiRequest& request, HttpApiRespo /* validate the config. on success, activate stage and reload */ ConfigPackageUtility::AsyncTryActivateStage(packageName, stageName, activate, reload, resetPackageUpdates); } catch (const std::exception& ex) { - return HttpUtility::SendJsonError(response, params, 500, + return HttpUtility::SendJsonError(response, params, 500, yc, "Stage creation failed.", DiagnosticInformation(ex)); } @@ -198,10 +198,10 @@ void ConfigStagesHandler::HandlePost(const HttpApiRequest& request, HttpApiRespo }); response.result(http::status::ok); - HttpUtility::SendJsonBody(response, params, result); + HttpUtility::SendJsonBody(response, params, result, yc); } -void ConfigStagesHandler::HandleDelete(const HttpApiRequest& request, HttpApiResponse& response) +void ConfigStagesHandler::HandleDelete(const HttpApiRequest& request, HttpApiResponse& response, boost::asio::yield_context& yc) { namespace http = boost::beast::http; @@ -221,21 +221,21 @@ void ConfigStagesHandler::HandleDelete(const HttpApiRequest& request, HttpApiRes String stageName = HttpUtility::GetLastParameter(params, "stage"); if (!ConfigPackageUtility::ValidatePackageName(packageName)) - return HttpUtility::SendJsonError(response, params, 400, "Invalid package name '" + packageName + "'."); + return HttpUtility::SendJsonError(response, params, 400, yc, "Invalid package name '" + packageName + "'."); if (!ConfigPackageUtility::ValidateStageName(stageName)) - return HttpUtility::SendJsonError(response, params, 400, "Invalid stage name '" + stageName + "'."); + return HttpUtility::SendJsonError(response, params, 400, yc, "Invalid stage name '" + stageName + "'."); ConfigObjectsSharedLock lock(std::try_to_lock); if (!lock) { - HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading"); + HttpUtility::SendJsonError(response, params, 503, yc, "Icinga is reloading"); return; } try { ConfigPackageUtility::DeleteStage(packageName, stageName); } catch (const std::exception& ex) { - return HttpUtility::SendJsonError(response, params, 500, + return HttpUtility::SendJsonError(response, params, 500, yc, "Failed to delete stage '" + stageName + "' in package '" + packageName + "'.", DiagnosticInformation(ex)); } @@ -252,5 +252,5 @@ void ConfigStagesHandler::HandleDelete(const HttpApiRequest& request, HttpApiRes }); response.result(http::status::ok); - HttpUtility::SendJsonBody(response, params, result); + HttpUtility::SendJsonBody(response, params, result, yc); } diff --git a/lib/remote/configstageshandler.hpp b/lib/remote/configstageshandler.hpp index 8dda34122db..1c9cd6eaa79 100644 --- a/lib/remote/configstageshandler.hpp +++ b/lib/remote/configstageshandler.hpp @@ -23,8 +23,8 @@ class ConfigStagesHandler final : public HttpHandler private: void HandleGet(const HttpApiRequest& request, HttpApiResponse& response, boost::asio::yield_context& yc); - void HandlePost(const HttpApiRequest& request, HttpApiResponse& response); - void HandleDelete(const HttpApiRequest& request, HttpApiResponse& response); + void HandlePost(const HttpApiRequest& request, HttpApiResponse& response, boost::asio::yield_context& yc); + void HandleDelete(const HttpApiRequest& request, HttpApiResponse& response, boost::asio::yield_context& yc); }; } diff --git a/lib/remote/consolehandler.cpp b/lib/remote/consolehandler.cpp index 9490d2420fa..e548744d88d 100644 --- a/lib/remote/consolehandler.cpp +++ b/lib/remote/consolehandler.cpp @@ -73,7 +73,7 @@ bool ConsoleHandler::HandleRequest( const WaitGroup::Ptr&, const HttpApiRequest& request, HttpApiResponse& response, - boost::asio::yield_context& + boost::asio::yield_context& yc ) { namespace http = boost::beast::http; @@ -106,21 +106,21 @@ bool ConsoleHandler::HandleRequest( ConfigObjectsSharedLock lock (std::try_to_lock); if (!lock) { - HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading."); + HttpUtility::SendJsonError(response, params, 503, yc, "Icinga is reloading."); return true; } if (methodName == "execute-script") - return ExecuteScriptHelper(request, response, command, session, sandboxed); + return ExecuteScriptHelper(request, response, command, session, sandboxed, yc); else if (methodName == "auto-complete-script") - return AutocompleteScriptHelper(request, response, command, session, sandboxed); + return AutocompleteScriptHelper(request, response, command, session, sandboxed, yc); - HttpUtility::SendJsonError(response, params, 400, "Invalid method specified: " + methodName); + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid method specified: " + methodName); return true; } bool ConsoleHandler::ExecuteScriptHelper(const HttpApiRequest& request, HttpApiResponse& response, - const String& command, const String& session, bool sandboxed) + const String& command, const String& session, bool sandboxed, boost::asio::yield_context& yc) { namespace http = boost::beast::http; @@ -133,7 +133,7 @@ bool ConsoleHandler::ExecuteScriptHelper(const HttpApiRequest& request, HttpApiR std::unique_lock frameLock(lsf->Mutex, std::try_to_lock); if (!frameLock) { - HttpUtility::SendJsonError(response, request.Params(), 409, "Session is currently in use by another request."); + HttpUtility::SendJsonError(response, request.Params(), 409, yc, "Session is currently in use by another request."); return true; } @@ -195,13 +195,13 @@ bool ConsoleHandler::ExecuteScriptHelper(const HttpApiRequest& request, HttpApiR }); response.result(http::status::ok); - HttpUtility::SendJsonBody(response, request.Params(), result); + HttpUtility::SendJsonBody(response, request.Params(), result, yc); return true; } bool ConsoleHandler::AutocompleteScriptHelper(const HttpApiRequest& request, HttpApiResponse& response, - const String& command, const String& session, bool sandboxed) + const String& command, const String& session, bool sandboxed, boost::asio::yield_context& yc) { namespace http = boost::beast::http; @@ -214,7 +214,7 @@ bool ConsoleHandler::AutocompleteScriptHelper(const HttpApiRequest& request, Htt std::unique_lock frameLock(lsf->Mutex, std::try_to_lock); if (!frameLock) { - HttpUtility::SendJsonError(response, request.Params(), 409, "Session is currently in use by another request."); + HttpUtility::SendJsonError(response, request.Params(), 409, yc, "Session is currently in use by another request."); return true; } @@ -240,7 +240,7 @@ bool ConsoleHandler::AutocompleteScriptHelper(const HttpApiRequest& request, Htt }); response.result(http::status::ok); - HttpUtility::SendJsonBody(response, request.Params(), result); + HttpUtility::SendJsonBody(response, request.Params(), result, yc); return true; } diff --git a/lib/remote/consolehandler.hpp b/lib/remote/consolehandler.hpp index 17f8a71c1e0..100f7ecf5db 100644 --- a/lib/remote/consolehandler.hpp +++ b/lib/remote/consolehandler.hpp @@ -36,9 +36,9 @@ class ConsoleHandler final : public HttpHandler private: static bool ExecuteScriptHelper(const HttpApiRequest& request, HttpApiResponse& response, - const String& command, const String& session, bool sandboxed); + const String& command, const String& session, bool sandboxed, boost::asio::yield_context& yc); static bool AutocompleteScriptHelper(const HttpApiRequest& request, HttpApiResponse& response, - const String& command, const String& session, bool sandboxed); + const String& command, const String& session, bool sandboxed, boost::asio::yield_context& yc); }; diff --git a/lib/remote/createobjecthandler.cpp b/lib/remote/createobjecthandler.cpp index 29d1d52b520..7ae9eecbef9 100644 --- a/lib/remote/createobjecthandler.cpp +++ b/lib/remote/createobjecthandler.cpp @@ -20,7 +20,7 @@ bool CreateObjectHandler::HandleRequest( const WaitGroup::Ptr& waitGroup, const HttpApiRequest& request, HttpApiResponse& response, - boost::asio::yield_context& + boost::asio::yield_context& yc ) { namespace http = boost::beast::http; @@ -38,7 +38,7 @@ bool CreateObjectHandler::HandleRequest( Type::Ptr type = FilterUtility::TypeFromPluralName(url->GetPath()[2]); if (!type) { - HttpUtility::SendJsonError(response, params, 400, "Invalid type specified."); + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid type specified."); return true; } @@ -99,13 +99,13 @@ bool CreateObjectHandler::HandleRequest( ConfigObjectsSharedLock lock (std::try_to_lock); if (!lock) { - HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading"); + HttpUtility::SendJsonError(response, params, 503, yc, "Icinga is reloading"); return true; } std::shared_lock wgLock{*waitGroup, std::try_to_lock}; if (!wgLock) { - HttpUtility::SendJsonError(response, params, 503, "Shutting down."); + HttpUtility::SendJsonError(response, params, 503, yc, "Shutting down."); return true; } @@ -126,7 +126,7 @@ bool CreateObjectHandler::HandleRequest( result1->Set("status", "Object could not be created."); response.result(http::status::internal_server_error); - HttpUtility::SendJsonBody(response, params, result); + HttpUtility::SendJsonBody(response, params, result, yc); return true; } @@ -143,7 +143,7 @@ bool CreateObjectHandler::HandleRequest( result1->Set("diagnostic_information", diagnosticInformation); response.result(http::status::internal_server_error); - HttpUtility::SendJsonBody(response, params, result); + HttpUtility::SendJsonBody(response, params, result, yc); return true; } @@ -159,7 +159,7 @@ bool CreateObjectHandler::HandleRequest( result1->Set("status", "Object was not created but 'ignore_on_error' was set to true"); response.result(http::status::ok); - HttpUtility::SendJsonBody(response, params, result); + HttpUtility::SendJsonBody(response, params, result, yc); return true; } diff --git a/lib/remote/deleteobjecthandler.cpp b/lib/remote/deleteobjecthandler.cpp index a918d4a3002..10872194f08 100644 --- a/lib/remote/deleteobjecthandler.cpp +++ b/lib/remote/deleteobjecthandler.cpp @@ -38,7 +38,7 @@ bool DeleteObjectHandler::HandleRequest( Type::Ptr type = FilterUtility::TypeFromPluralName(url->GetPath()[2]); if (!type) { - HttpUtility::SendJsonError(response, params, 400, "Invalid type specified."); + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid type specified."); return true; } @@ -59,7 +59,7 @@ bool DeleteObjectHandler::HandleRequest( try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, params, 404, + HttpUtility::SendJsonError(response, params, 404, yc, "No objects found.", DiagnosticInformation(ex)); return true; @@ -71,7 +71,7 @@ bool DeleteObjectHandler::HandleRequest( ConfigObjectsSharedLock lock (std::try_to_lock); if (!lock) { - HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading"); + HttpUtility::SendJsonError(response, params, 503, yc, "Icinga is reloading"); return true; } @@ -81,7 +81,7 @@ bool DeleteObjectHandler::HandleRequest( std::shared_lock wgLock{*waitGroup, std::try_to_lock}; if (!wgLock) { - HttpUtility::SendJsonError(response, params, 503, "Shutting down."); + HttpUtility::SendJsonError(response, params, 503, yc, "Shutting down."); return true; } diff --git a/lib/remote/eventshandler.cpp b/lib/remote/eventshandler.cpp index e1c354b9611..93b180851bd 100644 --- a/lib/remote/eventshandler.cpp +++ b/lib/remote/eventshandler.cpp @@ -61,14 +61,14 @@ bool EventsHandler::HandleRequest( return false; if (request.version() == 10) { - HttpUtility::SendJsonError(response, params, 400, "HTTP/1.0 not supported for event streams."); + HttpUtility::SendJsonError(response, params, 400, yc, "HTTP/1.0 not supported for event streams."); return true; } Array::Ptr types = params->Get("types"); if (!types) { - HttpUtility::SendJsonError(response, params, 400, "'types' query parameter is required."); + HttpUtility::SendJsonError(response, params, 400, yc, "'types' query parameter is required."); return true; } diff --git a/lib/remote/httphandler.cpp b/lib/remote/httphandler.cpp index 3413251a31b..e6d5bcb355d 100644 --- a/lib/remote/httphandler.cpp +++ b/lib/remote/httphandler.cpp @@ -91,7 +91,7 @@ void HttpHandler::ProcessRequest( try { request.DecodeParams(); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, request.Params(), 400, "Invalid request body: " + DiagnosticInformation(ex, false)); + HttpUtility::SendJsonError(response, request.Params(), 400, yc, "Invalid request body: " + DiagnosticInformation(ex, false)); return; } @@ -131,7 +131,7 @@ void HttpHandler::ProcessRequest( } if (!processed) { - HttpUtility::SendJsonError(response, request.Params(), 404, "The requested path '" + boost::algorithm::join(path, "/") + + HttpUtility::SendJsonError(response, request.Params(), 404, yc, "The requested path '" + boost::algorithm::join(path, "/") + "' could not be found or the request method is not valid for this path."); return; } diff --git a/lib/remote/httpmessage.cpp b/lib/remote/httpmessage.cpp index 7641e75ab23..744cc49bdfc 100644 --- a/lib/remote/httpmessage.cpp +++ b/lib/remote/httpmessage.cpp @@ -146,8 +146,6 @@ void OutgoingHttpMessage::Clear() template void OutgoingHttpMessage::Flush(boost::asio::yield_context yc, bool finish) { - m_CpuBoundWork.reset(); - if (!Base::chunked() && !Base::has_content_length()) { ASSERT(!m_SerializationStarted); Base::prepare_payload(); @@ -185,6 +183,7 @@ void OutgoingHttpMessage::Flush(boost::asio::yie template void OutgoingHttpMessage::StartStreaming() { + m_CpuBoundWork.reset(); ASSERT(Base::body().Size() == 0 && !m_SerializationStarted); Base::body().Start(); Base::chunked(true); diff --git a/lib/remote/httpserverconnection.cpp b/lib/remote/httpserverconnection.cpp index 07becaaf58c..457242ac565 100644 --- a/lib/remote/httpserverconnection.cpp +++ b/lib/remote/httpserverconnection.cpp @@ -198,7 +198,7 @@ bool EnsureValidHeaders( response.result(http::status::bad_request); if (!httpError && request[http::field::accept] == "application/json") { - HttpUtility::SendJsonError(response, nullptr, 400, "Bad Request: " + errorMsg); + HttpUtility::SendJsonError(response, nullptr, 400, yc, "Bad Request: " + errorMsg); } else { response.set(http::field::content_type, "text/html"); response.body() << "

Bad Request

" << errorMsg << "

"; @@ -315,7 +315,7 @@ bool EnsureAuthenticatedUser( response.set(http::field::connection, "close"); if (request[http::field::accept] == "application/json") { - HttpUtility::SendJsonError(response, nullptr, 401, "Unauthorized. Please check your user credentials."); + HttpUtility::SendJsonError(response, nullptr, 401, yc, "Unauthorized. Please check your user credentials."); } else { response.set(http::field::content_type, "text/html"); response.body() << "

Unauthorized. Please check your user credentials.

"; @@ -396,7 +396,7 @@ bool EnsureValidBody( response.result(http::status::bad_request); if (request[http::field::accept] == "application/json") { - HttpUtility::SendJsonError(response, nullptr, 400, "Bad Request: " + ec.message()); + HttpUtility::SendJsonError(response, nullptr, 400, yc, "Bad Request: " + ec.message()); } else { response.set(http::field::content_type, "text/html"); response.body() << "

Bad Request

" << ec.message() << "

"; @@ -438,7 +438,7 @@ void ProcessRequest( throw; } - HttpUtility::SendJsonError(response, request.Params(), 500, "Unhandled exception", DiagnosticInformation(ex)); + HttpUtility::SendJsonError(response, request.Params(), 500, yc, "Unhandled exception", DiagnosticInformation(ex)); } response.Flush(yc); diff --git a/lib/remote/httputility.cpp b/lib/remote/httputility.cpp index 5e466bb8ab2..5ce4c7d1a15 100644 --- a/lib/remote/httputility.cpp +++ b/lib/remote/httputility.cpp @@ -75,16 +75,8 @@ void HttpUtility::SendJsonBody(HttpApiResponse& response, const Dictionary::Ptr& response.GetJsonEncoder(params && GetLastParameter(params, "pretty")).Encode(val, &yc); } -void HttpUtility::SendJsonBody(HttpApiResponse& response, const Dictionary::Ptr& params, const Value& val) -{ - namespace http = boost::beast::http; - - response.set(http::field::content_type, "application/json"); - response.GetJsonEncoder(params && GetLastParameter(params, "pretty")).Encode(val); -} - -void HttpUtility::SendJsonError(HttpApiResponse& response, - const Dictionary::Ptr& params, int code, const String& info, const String& diagnosticInformation) +void HttpUtility::SendJsonError(HttpApiResponse& response, const Dictionary::Ptr& params, + int code, boost::asio::yield_context& yc, const String& info, const String& diagnosticInformation) { Dictionary::Ptr result = new Dictionary({ { "error", code } }); @@ -99,7 +91,7 @@ void HttpUtility::SendJsonError(HttpApiResponse& response, response.Clear(); response.result(code); - HttpUtility::SendJsonBody(response, params, result); + HttpUtility::SendJsonBody(response, params, result, yc); } /** diff --git a/lib/remote/httputility.hpp b/lib/remote/httputility.hpp index c8e5ccf2439..d4c1387ceea 100644 --- a/lib/remote/httputility.hpp +++ b/lib/remote/httputility.hpp @@ -26,9 +26,8 @@ class HttpUtility static Value GetLastParameter(const Dictionary::Ptr& params, const String& key); static void SendJsonBody(HttpApiResponse& response, const Dictionary::Ptr& params, const Value& val, boost::asio::yield_context& yc); - static void SendJsonBody(HttpApiResponse& response, const Dictionary::Ptr& params, const Value& val); static void SendJsonError(HttpApiResponse& response, const Dictionary::Ptr& params, const int code, - const String& info = {}, const String& diagnosticInformation = {}); + boost::asio::yield_context& yc, const String& info = {}, const String& diagnosticInformation = {}); static bool IsValidHeaderName(std::string_view name); static bool IsValidHeaderValue(std::string_view value); diff --git a/lib/remote/infohandler.cpp b/lib/remote/infohandler.cpp index e463b369c5f..a0b5d6a0c10 100644 --- a/lib/remote/infohandler.cpp +++ b/lib/remote/infohandler.cpp @@ -13,7 +13,7 @@ bool InfoHandler::HandleRequest( const WaitGroup::Ptr&, const HttpApiRequest& request, HttpApiResponse& response, - boost::asio::yield_context& + boost::asio::yield_context& yc ) { namespace http = boost::beast::http; @@ -73,7 +73,7 @@ bool InfoHandler::HandleRequest( { "results", new Array({ result1 }) } }); - HttpUtility::SendJsonBody(response, params, result); + HttpUtility::SendJsonBody(response, params, result, yc); } else { response.set(http::field::content_type, "text/html"); diff --git a/lib/remote/mallocinfohandler.cpp b/lib/remote/mallocinfohandler.cpp index ee76f0b0d8c..b5a34a3da7e 100644 --- a/lib/remote/mallocinfohandler.cpp +++ b/lib/remote/mallocinfohandler.cpp @@ -22,7 +22,7 @@ bool MallocInfoHandler::HandleRequest( const WaitGroup::Ptr&, const HttpApiRequest& request, HttpApiResponse& response, - boost::asio::yield_context& + boost::asio::yield_context& yc ) { namespace http = boost::beast::http; @@ -42,7 +42,7 @@ bool MallocInfoHandler::HandleRequest( FilterUtility::CheckPermission(user, "debug"); #ifndef HAVE_MALLOC_INFO - HttpUtility::SendJsonError(response, params, 501, "malloc_info(3) not available."); + HttpUtility::SendJsonError(response, params, 501, yc, "malloc_info(3) not available."); #else /* HAVE_MALLOC_INFO */ char* buf = nullptr; size_t bufSize = 0; diff --git a/lib/remote/modifyobjecthandler.cpp b/lib/remote/modifyobjecthandler.cpp index 5d97919dde9..840a7731355 100644 --- a/lib/remote/modifyobjecthandler.cpp +++ b/lib/remote/modifyobjecthandler.cpp @@ -36,7 +36,7 @@ bool ModifyObjectHandler::HandleRequest( Type::Ptr type = FilterUtility::TypeFromPluralName(url->GetPath()[2]); if (!type) { - HttpUtility::SendJsonError(response, params, 400, "Invalid type specified."); + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid type specified."); return true; } @@ -57,7 +57,7 @@ bool ModifyObjectHandler::HandleRequest( try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, params, 404, + HttpUtility::SendJsonError(response, params, 404, yc, "No objects found.", DiagnosticInformation(ex)); return true; @@ -66,7 +66,7 @@ bool ModifyObjectHandler::HandleRequest( Value attrsVal = params->Get("attrs"); if (attrsVal.GetReflectionType() != Dictionary::TypeInstance && attrsVal.GetType() != ValueEmpty) { - HttpUtility::SendJsonError(response, params, 400, + HttpUtility::SendJsonError(response, params, 400, yc, "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?"); return true; @@ -77,7 +77,7 @@ bool ModifyObjectHandler::HandleRequest( Value restoreAttrsVal = params->Get("restore_attrs"); if (restoreAttrsVal.GetReflectionType() != Array::TypeInstance && restoreAttrsVal.GetType() != ValueEmpty) { - HttpUtility::SendJsonError(response, params, 400, + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid type for 'restore_attrs' attribute specified. Array type is required."); return true; } @@ -85,7 +85,7 @@ bool ModifyObjectHandler::HandleRequest( Array::Ptr restoreAttrs = restoreAttrsVal; if (!(attrs || restoreAttrs)) { - HttpUtility::SendJsonError(response, params, 400, + HttpUtility::SendJsonError(response, params, 400, yc, "Missing both 'attrs' and 'restore_attrs'. " "Or is this a POST query and you missed adding a 'X-HTTP-Method-Override: GET' header?"); return true; @@ -99,7 +99,7 @@ bool ModifyObjectHandler::HandleRequest( ConfigObjectsSharedLock lock (std::try_to_lock); if (!lock) { - HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading"); + HttpUtility::SendJsonError(response, params, 503, yc, "Icinga is reloading"); return true; } @@ -107,7 +107,7 @@ bool ModifyObjectHandler::HandleRequest( std::shared_lock wgLock{*waitGroup, std::try_to_lock}; if (!wgLock) { - HttpUtility::SendJsonError(response, params, 503, "Shutting down."); + HttpUtility::SendJsonError(response, params, 503, yc, "Shutting down."); return true; } diff --git a/lib/remote/objectqueryhandler.cpp b/lib/remote/objectqueryhandler.cpp index 2c81c6a73bb..74eea1c80e8 100644 --- a/lib/remote/objectqueryhandler.cpp +++ b/lib/remote/objectqueryhandler.cpp @@ -114,7 +114,7 @@ bool ObjectQueryHandler::HandleRequest( Type::Ptr type = FilterUtility::TypeFromPluralName(url->GetPath()[2]); if (!type) { - HttpUtility::SendJsonError(response, params, 400, "Invalid type specified."); + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid type specified."); return true; } @@ -127,7 +127,7 @@ bool ObjectQueryHandler::HandleRequest( try { uattrs = params->Get("attrs"); } catch (const std::exception&) { - HttpUtility::SendJsonError(response, params, 400, + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid type for 'attrs' attribute specified. Array type is required."); return true; } @@ -135,7 +135,7 @@ bool ObjectQueryHandler::HandleRequest( try { ujoins = params->Get("joins"); } catch (const std::exception&) { - HttpUtility::SendJsonError(response, params, 400, + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid type for 'joins' attribute specified. Array type is required."); return true; } @@ -143,7 +143,7 @@ bool ObjectQueryHandler::HandleRequest( try { umetas = params->Get("meta"); } catch (const std::exception&) { - HttpUtility::SendJsonError(response, params, 400, + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid type for 'meta' attribute specified. Array type is required."); return true; } @@ -158,7 +158,7 @@ bool ObjectQueryHandler::HandleRequest( } else if (meta == "location") { includeLocation = true; } else { - HttpUtility::SendJsonError(response, params, 400, "Invalid field specified for meta: " + meta); + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid field specified for meta: " + meta); return true; } } @@ -179,7 +179,7 @@ bool ObjectQueryHandler::HandleRequest( try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, params, 404, + HttpUtility::SendJsonError(response, params, 404, yc, "No objects found.", DiagnosticInformation(ex)); return true; diff --git a/lib/remote/statushandler.cpp b/lib/remote/statushandler.cpp index 1b0aa17170e..6a5d4dd30f2 100644 --- a/lib/remote/statushandler.cpp +++ b/lib/remote/statushandler.cpp @@ -73,7 +73,7 @@ bool StatusHandler::HandleRequest( const WaitGroup::Ptr&, const HttpApiRequest& request, HttpApiResponse& response, - boost::asio::yield_context& + boost::asio::yield_context& yc ) { namespace http = boost::beast::http; @@ -103,7 +103,7 @@ bool StatusHandler::HandleRequest( try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, params, 404, + HttpUtility::SendJsonError(response, params, 404, yc, "No objects found.", DiagnosticInformation(ex)); return true; @@ -114,7 +114,7 @@ bool StatusHandler::HandleRequest( }); response.result(http::status::ok); - HttpUtility::SendJsonBody(response, params, result); + HttpUtility::SendJsonBody(response, params, result, yc); return true; } diff --git a/lib/remote/templatequeryhandler.cpp b/lib/remote/templatequeryhandler.cpp index 1aaba790622..7de879d2a55 100644 --- a/lib/remote/templatequeryhandler.cpp +++ b/lib/remote/templatequeryhandler.cpp @@ -98,7 +98,7 @@ bool TemplateQueryHandler::HandleRequest( Type::Ptr type = FilterUtility::TypeFromPluralName(url->GetPath()[2]); if (!type) { - HttpUtility::SendJsonError(response, params, 400, "Invalid type specified."); + HttpUtility::SendJsonError(response, params, 400, yc, "Invalid type specified."); return true; } @@ -120,7 +120,7 @@ bool TemplateQueryHandler::HandleRequest( try { objs = FilterUtility::GetFilterTargets(qd, params, user, "tmpl"); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, params, 404, + HttpUtility::SendJsonError(response, params, 404, yc, "No templates found.", DiagnosticInformation(ex)); return true; diff --git a/lib/remote/typequeryhandler.cpp b/lib/remote/typequeryhandler.cpp index 203dfbf41f5..c98ffa95f55 100644 --- a/lib/remote/typequeryhandler.cpp +++ b/lib/remote/typequeryhandler.cpp @@ -82,7 +82,7 @@ bool TypeQueryHandler::HandleRequest( try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, params, 404, + HttpUtility::SendJsonError(response, params, 404, yc, "No objects found.", DiagnosticInformation(ex)); return true; diff --git a/lib/remote/variablequeryhandler.cpp b/lib/remote/variablequeryhandler.cpp index 505983c45e2..f8672e84d4b 100644 --- a/lib/remote/variablequeryhandler.cpp +++ b/lib/remote/variablequeryhandler.cpp @@ -92,7 +92,7 @@ bool VariableQueryHandler::HandleRequest( try { objs = FilterUtility::GetFilterTargets(qd, params, user, "variable"); } catch (const std::exception& ex) { - HttpUtility::SendJsonError(response, params, 404, + HttpUtility::SendJsonError(response, params, 404, yc, "No variables found.", DiagnosticInformation(ex)); return true; diff --git a/test/remote-httpmessage.cpp b/test/remote-httpmessage.cpp index 96b1948e861..4e2ff1d316c 100644 --- a/test/remote-httpmessage.cpp +++ b/test/remote-httpmessage.cpp @@ -267,7 +267,7 @@ BOOST_AUTO_TEST_CASE(response_sendjsonbody) HttpApiResponse response(server); response.result(http::status::ok); - HttpUtility::SendJsonBody(response, nullptr, new Dictionary{{"test", 1}}); + HttpUtility::SendJsonBody(response, nullptr, new Dictionary{{"test", 1}}, yc); BOOST_REQUIRE_NO_THROW(response.Flush(yc)); @@ -285,7 +285,7 @@ BOOST_AUTO_TEST_CASE(response_sendjsonbody) BOOST_REQUIRE(!ec); BOOST_REQUIRE_EQUAL(parser.get().result(), http::status::ok); - BOOST_REQUIRE_EQUAL(parser.get().chunked(), false); + BOOST_REQUIRE_EQUAL(parser.get().chunked(), true); Dictionary::Ptr body = JsonDecode(parser.get().body()); BOOST_REQUIRE_EQUAL(body->Get("test"), 1); } @@ -298,7 +298,7 @@ BOOST_AUTO_TEST_CASE(response_sendjsonerror) // This has to be overwritten in SendJsonError. response.result(http::status::ok); - HttpUtility::SendJsonError(response, nullptr, 404, "Not found."); + HttpUtility::SendJsonError(response, nullptr, 404, yc, "Not found."); BOOST_REQUIRE_NO_THROW(response.Flush(yc)); @@ -316,7 +316,7 @@ BOOST_AUTO_TEST_CASE(response_sendjsonerror) BOOST_REQUIRE(!ec); BOOST_REQUIRE_EQUAL(parser.get().result(), http::status::not_found); - BOOST_REQUIRE_EQUAL(parser.get().chunked(), false); + BOOST_REQUIRE_EQUAL(parser.get().chunked(), true); Dictionary::Ptr body = JsonDecode(parser.get().body()); BOOST_REQUIRE_EQUAL(body->Get("error"), 404); BOOST_REQUIRE_EQUAL(body->Get("status"), "Not found.");