mirror of https://github.com/Icinga/icinga2.git
HttpServerConnection: actually handle requests
This commit is contained in:
parent
7fe0431ada
commit
9ae1d732af
|
@ -5,6 +5,7 @@
|
|||
#include "base/singleton.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
|
@ -44,11 +45,17 @@ void HttpHandler::Register(const Url::Ptr& url, const HttpHandler::Ptr& handler)
|
|||
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");
|
||||
|
@ -81,7 +88,7 @@ void HttpHandler::ProcessRequest(const ApiUser::Ptr& user, HttpRequest& request,
|
|||
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;
|
||||
|
@ -89,16 +96,15 @@ void HttpHandler::ProcessRequest(const ApiUser::Ptr& user, HttpRequest& request,
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
#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
|
||||
{
|
||||
|
@ -22,10 +24,20 @@ class HttpHandler : public Object
|
|||
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;
|
||||
|
|
|
@ -321,7 +321,20 @@ void ProcessRequest(
|
|||
{
|
||||
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);
|
||||
|
|
|
@ -1,28 +1,23 @@
|
|||
/* 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);
|
||||
}
|
||||
|
@ -31,7 +26,7 @@ Dictionary::Ptr HttpUtility::FetchRequestParameters(HttpRequest& request)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
|
||||
#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
|
||||
|
@ -20,7 +22,7 @@ class HttpUtility
|
|||
{
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue