#include "base/singleton.hpp"
#include "base/exception.hpp"
#include <boost/algorithm/string/join.hpp>
+#include <boost/beast/http.hpp>
using namespace icinga;
handlers->Add(handler);
}
-void HttpHandler::ProcessRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response)
+void HttpHandler::ProcessRequest(
+ const ApiUser::Ptr& user,
+ boost::beast::http::request<boost::beast::http::string_body>& request,
+ boost::beast::http::response<boost::beast::http::string_body>& response
+)
{
Dictionary::Ptr node = m_UrlTree;
std::vector<HttpHandler::Ptr> handlers;
- const std::vector<String>& path = request.RequestUrl->GetPath();
+
+ Url::Ptr url = new Url(request.target().to_string());
+ auto& path (url->GetPath());
for (std::vector<String>::size_type i = 0; i <= path.size(); i++) {
Array::Ptr current_handlers = node->Get("handlers");
Dictionary::Ptr params;
try {
- params = HttpUtility::FetchRequestParameters(request);
+ params = HttpUtility::FetchRequestParameters(url, request.body());
} catch (const std::exception& ex) {
HttpUtility::SendJsonError(response, params, 400, "Invalid request body: " + DiagnosticInformation(ex, false));
return;
bool processed = false;
for (const HttpHandler::Ptr& handler : handlers) {
- if (handler->HandleRequest(user, request, response, params)) {
+ if (handler->HandleRequest(user, request, url, response, params)) {
processed = true;
break;
}
}
if (!processed) {
- String path = boost::algorithm::join(request.RequestUrl->GetPath(), "/");
- HttpUtility::SendJsonError(response, params, 404, "The requested path '" + path +
- "' could not be found or the request method is not valid for this path.");
+ HttpUtility::SendJsonError(response, params, 404, "The requested path '" + boost::algorithm::join(path, "/") +
+ "' could not be found or the request method is not valid for this path.");
return;
}
}
#define HTTPHANDLER_H
#include "remote/i2-remote.hpp"
+#include "remote/url.hpp"
#include "remote/httpresponse.hpp"
#include "remote/apiuser.hpp"
#include "base/registry.hpp"
#include <vector>
+#include <boost/beast/http.hpp>
namespace icinga
{
public:
DECLARE_PTR_TYPEDEFS(HttpHandler);
- virtual bool HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response, const Dictionary::Ptr& params) = 0;
+ virtual bool HandleRequest(
+ 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
+ ) = 0;
static void Register(const Url::Ptr& url, const HttpHandler::Ptr& handler);
- static void ProcessRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response);
+ static void ProcessRequest(
+ const ApiUser::Ptr& user,
+ boost::beast::http::request<boost::beast::http::string_body>& request,
+ boost::beast::http::response<boost::beast::http::string_body>& response
+ );
private:
static Dictionary::Ptr m_UrlTree;
{
namespace http = boost::beast::http;
- HttpUtility::SendJsonError(response, nullptr, 503, "Unhandled exception" , "");
+ try {
+ CpuBoundWork handlingRequest (yc);
+
+ HttpHandler::ProcessRequest(authenticatedUser, request, response);
+ } catch (const std::exception& ex) {
+ 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;
+ }
http::async_write(stream, response, yc);
stream.async_flush(yc);
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
#include "remote/httputility.hpp"
+#include "remote/url.hpp"
#include "base/json.hpp"
#include "base/logger.hpp"
#include <map>
+#include <string>
#include <vector>
#include <boost/beast/http.hpp>
using namespace icinga;
-Dictionary::Ptr HttpUtility::FetchRequestParameters(HttpRequest& request)
+Dictionary::Ptr HttpUtility::FetchRequestParameters(const Url::Ptr& url, const std::string& body)
{
Dictionary::Ptr result;
- String body;
- char buffer[1024];
- size_t count;
-
- while ((count = request.ReadBody(buffer, sizeof(buffer))) > 0)
- body += String(buffer, buffer + count);
-
- if (!body.IsEmpty()) {
+ if (!body.empty()) {
Log(LogDebug, "HttpUtility")
- << "Request body: '" << body << "'";
+ << "Request body: '" << body << '\'';
result = JsonDecode(body);
}
result = new Dictionary();
std::map<String, std::vector<String>> query;
- for (const auto& kv : request.RequestUrl->GetQuery()) {
+ for (const auto& kv : url->GetQuery()) {
query[kv.first].emplace_back(kv.second);
}
#include "remote/httprequest.hpp"
#include "remote/httpresponse.hpp"
+#include "remote/url.hpp"
#include "base/dictionary.hpp"
+#include <string>
#include <boost/beast/http.hpp>
namespace icinga
{
public:
- static Dictionary::Ptr FetchRequestParameters(HttpRequest& request);
+ static Dictionary::Ptr FetchRequestParameters(const Url::Ptr& url, const std::string& body);
static void SendJsonBody(HttpResponse& response, const Dictionary::Ptr& params, const Value& val);
static void SendJsonBody(boost::beast::http::response<boost::beast::http::string_body>& response, const Dictionary::Ptr& params, const Value& val);
static Value GetLastParameter(const Dictionary::Ptr& params, const String& key);