mirror of
https://github.com/Icinga/icinga2.git
synced 2025-04-08 17:05:25 +02:00
Quality: Purge old HTTP code in lib/remote
This commit is contained in:
parent
5d0af5c879
commit
f933aafd29
@ -2,7 +2,6 @@
|
||||
|
||||
#include "cli/consolecommand.hpp"
|
||||
#include "config/configcompiler.hpp"
|
||||
#include "remote/apiclient.hpp"
|
||||
#include "remote/consolehandler.hpp"
|
||||
#include "remote/url.hpp"
|
||||
#include "base/configwriter.hpp"
|
||||
@ -721,4 +720,4 @@ Array::Ptr ConsoleCommand::AutoCompleteScript(const String& session, const Strin
|
||||
}
|
||||
|
||||
return suggestions;
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include "perfdata/elasticsearchwriter.hpp"
|
||||
#include "perfdata/elasticsearchwriter-ti.cpp"
|
||||
#include "remote/url.hpp"
|
||||
#include "remote/httprequest.hpp"
|
||||
#include "remote/httpresponse.hpp"
|
||||
#include "icinga/compatutility.hpp"
|
||||
#include "icinga/service.hpp"
|
||||
#include "icinga/checkcommand.hpp"
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include "perfdata/influxdbwriter.hpp"
|
||||
#include "perfdata/influxdbwriter-ti.cpp"
|
||||
#include "remote/url.hpp"
|
||||
#include "remote/httprequest.hpp"
|
||||
#include "remote/httpresponse.hpp"
|
||||
#include "icinga/service.hpp"
|
||||
#include "icinga/macroprocessor.hpp"
|
||||
#include "icinga/icingaapplication.hpp"
|
||||
|
@ -9,7 +9,6 @@ set(remote_SOURCES
|
||||
i2-remote.hpp
|
||||
actionshandler.cpp actionshandler.hpp
|
||||
apiaction.cpp apiaction.hpp
|
||||
apiclient.cpp apiclient.hpp
|
||||
apifunction.cpp apifunction.hpp
|
||||
apilistener.cpp apilistener.hpp apilistener-ti.hpp apilistener-configsync.cpp apilistener-filesync.cpp
|
||||
apilistener-authority.cpp
|
||||
@ -27,10 +26,7 @@ set(remote_SOURCES
|
||||
eventshandler.cpp eventshandler.hpp
|
||||
filterutility.cpp filterutility.hpp
|
||||
httpchunkedencoding.cpp httpchunkedencoding.hpp
|
||||
httpclientconnection.cpp httpclientconnection.hpp
|
||||
httphandler.cpp httphandler.hpp
|
||||
httprequest.cpp httprequest.hpp
|
||||
httpresponse.cpp httpresponse.hpp
|
||||
httpserverconnection.cpp httpserverconnection.hpp
|
||||
httputility.cpp httputility.hpp
|
||||
infohandler.cpp infohandler.hpp
|
||||
|
@ -1,164 +0,0 @@
|
||||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#include "remote/apiclient.hpp"
|
||||
#include "base/base64.hpp"
|
||||
#include "base/json.hpp"
|
||||
#include "base/logger.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include "base/convert.hpp"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
ApiClient::ApiClient(const String& host, const String& port,
|
||||
String user, String password)
|
||||
: m_Connection(new HttpClientConnection(host, port, true)), m_User(std::move(user)), m_Password(std::move(password))
|
||||
{
|
||||
m_Connection->Start();
|
||||
}
|
||||
|
||||
void ApiClient::ExecuteScript(const String& session, const String& command, bool sandboxed,
|
||||
const ExecuteScriptCompletionCallback& callback) const
|
||||
{
|
||||
Url::Ptr url = new Url();
|
||||
url->SetScheme("https");
|
||||
url->SetHost(m_Connection->GetHost());
|
||||
url->SetPort(m_Connection->GetPort());
|
||||
url->SetPath({ "v1", "console", "execute-script" });
|
||||
|
||||
url->SetQuery({
|
||||
{"session", session},
|
||||
{"command", command},
|
||||
{"sandboxed", sandboxed ? "1" : "0"}
|
||||
});
|
||||
|
||||
try {
|
||||
std::shared_ptr<HttpRequest> req = m_Connection->NewRequest();
|
||||
req->RequestMethod = "POST";
|
||||
req->RequestUrl = url;
|
||||
req->AddHeader("Authorization", "Basic " + Base64::Encode(m_User + ":" + m_Password));
|
||||
req->AddHeader("Accept", "application/json");
|
||||
m_Connection->SubmitRequest(req, std::bind(ExecuteScriptHttpCompletionCallback, _1, _2, callback));
|
||||
} catch (const std::exception&) {
|
||||
callback(boost::current_exception(), Empty);
|
||||
}
|
||||
}
|
||||
|
||||
void ApiClient::ExecuteScriptHttpCompletionCallback(HttpRequest& request,
|
||||
HttpResponse& response, const ExecuteScriptCompletionCallback& callback)
|
||||
{
|
||||
Dictionary::Ptr result;
|
||||
|
||||
String body;
|
||||
char buffer[1024];
|
||||
size_t count;
|
||||
|
||||
while ((count = response.ReadBody(buffer, sizeof(buffer))) > 0)
|
||||
body += String(buffer, buffer + count);
|
||||
|
||||
try {
|
||||
if (response.StatusCode < 200 || response.StatusCode > 299) {
|
||||
std::string message = "HTTP request failed; Code: " + Convert::ToString(response.StatusCode) + "; Body: " + body;
|
||||
|
||||
BOOST_THROW_EXCEPTION(ScriptError(message));
|
||||
}
|
||||
|
||||
result = JsonDecode(body);
|
||||
|
||||
Array::Ptr results = result->Get("results");
|
||||
Value result;
|
||||
String errorMessage = "Unexpected result from API.";
|
||||
|
||||
if (results && results->GetLength() > 0) {
|
||||
Dictionary::Ptr resultInfo = results->Get(0);
|
||||
errorMessage = resultInfo->Get("status");
|
||||
|
||||
if (resultInfo->Get("code") >= 200 && resultInfo->Get("code") <= 299) {
|
||||
result = resultInfo->Get("result");
|
||||
} else {
|
||||
DebugInfo di;
|
||||
Dictionary::Ptr debugInfo = resultInfo->Get("debug_info");
|
||||
if (debugInfo) {
|
||||
di.Path = debugInfo->Get("path");
|
||||
di.FirstLine = debugInfo->Get("first_line");
|
||||
di.FirstColumn = debugInfo->Get("first_column");
|
||||
di.LastLine = debugInfo->Get("last_line");
|
||||
di.LastColumn = debugInfo->Get("last_column");
|
||||
}
|
||||
bool incompleteExpression = resultInfo->Get("incomplete_expression");
|
||||
BOOST_THROW_EXCEPTION(ScriptError(errorMessage, di, incompleteExpression));
|
||||
}
|
||||
}
|
||||
|
||||
callback(boost::exception_ptr(), result);
|
||||
} catch (const std::exception&) {
|
||||
callback(boost::current_exception(), Empty);
|
||||
}
|
||||
}
|
||||
|
||||
void ApiClient::AutocompleteScript(const String& session, const String& command, bool sandboxed,
|
||||
const AutocompleteScriptCompletionCallback& callback) const
|
||||
{
|
||||
Url::Ptr url = new Url();
|
||||
url->SetScheme("https");
|
||||
url->SetHost(m_Connection->GetHost());
|
||||
url->SetPort(m_Connection->GetPort());
|
||||
url->SetPath({ "v1", "console", "auto-complete-script" });
|
||||
|
||||
url->SetQuery({
|
||||
{"session", session},
|
||||
{"command", command},
|
||||
{"sandboxed", sandboxed ? "1" : "0"}
|
||||
});
|
||||
|
||||
try {
|
||||
std::shared_ptr<HttpRequest> req = m_Connection->NewRequest();
|
||||
req->RequestMethod = "POST";
|
||||
req->RequestUrl = url;
|
||||
req->AddHeader("Authorization", "Basic " + Base64::Encode(m_User + ":" + m_Password));
|
||||
req->AddHeader("Accept", "application/json");
|
||||
m_Connection->SubmitRequest(req, std::bind(AutocompleteScriptHttpCompletionCallback, _1, _2, callback));
|
||||
} catch (const std::exception&) {
|
||||
callback(boost::current_exception(), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void ApiClient::AutocompleteScriptHttpCompletionCallback(HttpRequest& request,
|
||||
HttpResponse& response, const AutocompleteScriptCompletionCallback& callback)
|
||||
{
|
||||
Dictionary::Ptr result;
|
||||
|
||||
String body;
|
||||
char buffer[1024];
|
||||
size_t count;
|
||||
|
||||
while ((count = response.ReadBody(buffer, sizeof(buffer))) > 0)
|
||||
body += String(buffer, buffer + count);
|
||||
|
||||
try {
|
||||
if (response.StatusCode < 200 || response.StatusCode > 299) {
|
||||
std::string message = "HTTP request failed; Code: " + Convert::ToString(response.StatusCode) + "; Body: " + body;
|
||||
|
||||
BOOST_THROW_EXCEPTION(ScriptError(message));
|
||||
}
|
||||
|
||||
result = JsonDecode(body);
|
||||
|
||||
Array::Ptr results = result->Get("results");
|
||||
Array::Ptr suggestions;
|
||||
String errorMessage = "Unexpected result from API.";
|
||||
|
||||
if (results && results->GetLength() > 0) {
|
||||
Dictionary::Ptr resultInfo = results->Get(0);
|
||||
errorMessage = resultInfo->Get("status");
|
||||
|
||||
if (resultInfo->Get("code") >= 200 && resultInfo->Get("code") <= 299)
|
||||
suggestions = resultInfo->Get("suggestions");
|
||||
else
|
||||
BOOST_THROW_EXCEPTION(ScriptError(errorMessage));
|
||||
}
|
||||
|
||||
callback(boost::exception_ptr(), suggestions);
|
||||
} catch (const std::exception&) {
|
||||
callback(boost::current_exception(), nullptr);
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#ifndef APICLIENT_H
|
||||
#define APICLIENT_H
|
||||
|
||||
#include "remote/httpclientconnection.hpp"
|
||||
#include "base/value.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
class ApiClient : public Object
|
||||
{
|
||||
public:
|
||||
DECLARE_PTR_TYPEDEFS(ApiClient);
|
||||
|
||||
ApiClient(const String& host, const String& port,
|
||||
String user, String password);
|
||||
|
||||
typedef std::function<void(boost::exception_ptr, const Value&)> ExecuteScriptCompletionCallback;
|
||||
void ExecuteScript(const String& session, const String& command, bool sandboxed,
|
||||
const ExecuteScriptCompletionCallback& callback) const;
|
||||
|
||||
typedef std::function<void(boost::exception_ptr, const Array::Ptr&)> AutocompleteScriptCompletionCallback;
|
||||
void AutocompleteScript(const String& session, const String& command, bool sandboxed,
|
||||
const AutocompleteScriptCompletionCallback& callback) const;
|
||||
|
||||
private:
|
||||
HttpClientConnection::Ptr m_Connection;
|
||||
String m_User;
|
||||
String m_Password;
|
||||
|
||||
static void ExecuteScriptHttpCompletionCallback(HttpRequest& request,
|
||||
HttpResponse& response, const ExecuteScriptCompletionCallback& callback);
|
||||
static void AutocompleteScriptHttpCompletionCallback(HttpRequest& request,
|
||||
HttpResponse& response, const AutocompleteScriptCompletionCallback& callback);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* APICLIENT_H */
|
@ -1,159 +0,0 @@
|
||||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#include "remote/httpclientconnection.hpp"
|
||||
#include "base/configtype.hpp"
|
||||
#include "base/objectlock.hpp"
|
||||
#include "base/base64.hpp"
|
||||
#include "base/utility.hpp"
|
||||
#include "base/logger.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include "base/convert.hpp"
|
||||
#include "base/tcpsocket.hpp"
|
||||
#include "base/tlsstream.hpp"
|
||||
#include "base/networkstream.hpp"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
HttpClientConnection::HttpClientConnection(String host, String port, bool tls)
|
||||
: m_Host(std::move(host)), m_Port(std::move(port)), m_Tls(tls)
|
||||
{ }
|
||||
|
||||
void HttpClientConnection::Start()
|
||||
{
|
||||
/* Nothing to do here atm. */
|
||||
}
|
||||
|
||||
void HttpClientConnection::Reconnect()
|
||||
{
|
||||
if (m_Stream)
|
||||
m_Stream->Close();
|
||||
|
||||
m_Context.~StreamReadContext();
|
||||
new (&m_Context) StreamReadContext();
|
||||
|
||||
m_Requests.clear();
|
||||
m_CurrentResponse.reset();
|
||||
|
||||
TcpSocket::Ptr socket = new TcpSocket();
|
||||
socket->Connect(m_Host, m_Port);
|
||||
|
||||
if (m_Tls)
|
||||
m_Stream = new TlsStream(socket, m_Host, RoleClient);
|
||||
else
|
||||
ASSERT(!"Non-TLS HTTP connections not supported.");
|
||||
/* m_Stream = new NetworkStream(socket);
|
||||
* -- does not currently work because the NetworkStream class doesn't support async I/O
|
||||
*/
|
||||
|
||||
/* the stream holds an owning reference to this object through the callback we're registering here */
|
||||
m_Stream->RegisterDataHandler(std::bind(&HttpClientConnection::DataAvailableHandler, HttpClientConnection::Ptr(this), _1));
|
||||
if (m_Stream->IsDataAvailable())
|
||||
DataAvailableHandler(m_Stream);
|
||||
}
|
||||
|
||||
Stream::Ptr HttpClientConnection::GetStream() const
|
||||
{
|
||||
return m_Stream;
|
||||
}
|
||||
|
||||
String HttpClientConnection::GetHost() const
|
||||
{
|
||||
return m_Host;
|
||||
}
|
||||
|
||||
String HttpClientConnection::GetPort() const
|
||||
{
|
||||
return m_Port;
|
||||
}
|
||||
|
||||
bool HttpClientConnection::GetTls() const
|
||||
{
|
||||
return m_Tls;
|
||||
}
|
||||
|
||||
void HttpClientConnection::Disconnect()
|
||||
{
|
||||
Log(LogDebug, "HttpClientConnection", "Http client disconnected");
|
||||
|
||||
m_Stream->Shutdown();
|
||||
}
|
||||
|
||||
bool HttpClientConnection::ProcessMessage()
|
||||
{
|
||||
bool res;
|
||||
|
||||
if (m_Requests.empty()) {
|
||||
m_Stream->Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::pair<std::shared_ptr<HttpRequest>, HttpCompletionCallback>& currentRequest = *m_Requests.begin();
|
||||
HttpRequest& request = *currentRequest.first.get();
|
||||
const HttpCompletionCallback& callback = currentRequest.second;
|
||||
|
||||
if (!m_CurrentResponse)
|
||||
m_CurrentResponse = std::make_shared<HttpResponse>(m_Stream, request);
|
||||
|
||||
std::shared_ptr<HttpResponse> currentResponse = m_CurrentResponse;
|
||||
HttpResponse& response = *currentResponse.get();
|
||||
|
||||
try {
|
||||
res = response.Parse(m_Context, false);
|
||||
} catch (const std::exception&) {
|
||||
callback(request, response);
|
||||
|
||||
m_Stream->Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response.Complete) {
|
||||
callback(request, response);
|
||||
|
||||
m_Requests.pop_front();
|
||||
m_CurrentResponse.reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void HttpClientConnection::DataAvailableHandler(const Stream::Ptr& stream)
|
||||
{
|
||||
ASSERT(stream == m_Stream);
|
||||
|
||||
bool close = false;
|
||||
|
||||
if (!m_Stream->IsEof()) {
|
||||
boost::mutex::scoped_lock lock(m_DataHandlerMutex);
|
||||
|
||||
try {
|
||||
while (ProcessMessage())
|
||||
; /* empty loop body */
|
||||
} catch (const std::exception& ex) {
|
||||
Log(LogWarning, "HttpClientConnection")
|
||||
<< "Error while reading Http response: " << DiagnosticInformation(ex);
|
||||
|
||||
close = true;
|
||||
Disconnect();
|
||||
}
|
||||
} else
|
||||
close = true;
|
||||
|
||||
if (close)
|
||||
m_Stream->Close();
|
||||
}
|
||||
|
||||
std::shared_ptr<HttpRequest> HttpClientConnection::NewRequest()
|
||||
{
|
||||
Reconnect();
|
||||
return std::make_shared<HttpRequest>(m_Stream);
|
||||
}
|
||||
|
||||
void HttpClientConnection::SubmitRequest(const std::shared_ptr<HttpRequest>& request,
|
||||
const HttpCompletionCallback& callback)
|
||||
{
|
||||
m_Requests.emplace_back(request, callback);
|
||||
request->Finish();
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#ifndef HTTPCLIENTCONNECTION_H
|
||||
#define HTTPCLIENTCONNECTION_H
|
||||
|
||||
#include "remote/httprequest.hpp"
|
||||
#include "remote/httpresponse.hpp"
|
||||
#include "base/stream.hpp"
|
||||
#include "base/timer.hpp"
|
||||
#include <deque>
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
/**
|
||||
* An HTTP client connection.
|
||||
*
|
||||
* @ingroup remote
|
||||
*/
|
||||
class HttpClientConnection final : public Object
|
||||
{
|
||||
public:
|
||||
DECLARE_PTR_TYPEDEFS(HttpClientConnection);
|
||||
|
||||
HttpClientConnection(String host, String port, bool tls = true);
|
||||
|
||||
void Start();
|
||||
|
||||
Stream::Ptr GetStream() const;
|
||||
String GetHost() const;
|
||||
String GetPort() const;
|
||||
bool GetTls() const;
|
||||
|
||||
void Disconnect();
|
||||
|
||||
std::shared_ptr<HttpRequest> NewRequest();
|
||||
|
||||
typedef std::function<void(HttpRequest&, HttpResponse&)> HttpCompletionCallback;
|
||||
void SubmitRequest(const std::shared_ptr<HttpRequest>& request, const HttpCompletionCallback& callback);
|
||||
|
||||
private:
|
||||
String m_Host;
|
||||
String m_Port;
|
||||
bool m_Tls;
|
||||
Stream::Ptr m_Stream;
|
||||
std::deque<std::pair<std::shared_ptr<HttpRequest>, HttpCompletionCallback> > m_Requests;
|
||||
std::shared_ptr<HttpResponse> m_CurrentResponse;
|
||||
boost::mutex m_DataHandlerMutex;
|
||||
|
||||
StreamReadContext m_Context;
|
||||
|
||||
void Reconnect();
|
||||
bool ProcessMessage();
|
||||
void DataAvailableHandler(const Stream::Ptr& stream);
|
||||
|
||||
void ProcessMessageAsync(HttpRequest& request);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* HTTPCLIENTCONNECTION_H */
|
@ -5,7 +5,6 @@
|
||||
|
||||
#include "remote/i2-remote.hpp"
|
||||
#include "remote/url.hpp"
|
||||
#include "remote/httpresponse.hpp"
|
||||
#include "remote/httpserverconnection.hpp"
|
||||
#include "remote/apiuser.hpp"
|
||||
#include "base/registry.hpp"
|
||||
|
@ -1,248 +0,0 @@
|
||||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#include "remote/httprequest.hpp"
|
||||
#include "base/logger.hpp"
|
||||
#include "base/application.hpp"
|
||||
#include "base/convert.hpp"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
HttpRequest::HttpRequest(Stream::Ptr stream)
|
||||
: CompleteHeaders(false),
|
||||
CompleteHeaderCheck(false),
|
||||
CompleteBody(false),
|
||||
ProtocolVersion(HttpVersion11),
|
||||
Headers(new Dictionary()),
|
||||
m_Stream(std::move(stream)),
|
||||
m_State(HttpRequestStart)
|
||||
{ }
|
||||
|
||||
bool HttpRequest::ParseHeaders(StreamReadContext& src, bool may_wait)
|
||||
{
|
||||
if (!m_Stream)
|
||||
return false;
|
||||
|
||||
if (m_State != HttpRequestStart && m_State != HttpRequestHeaders)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Invalid HTTP state"));
|
||||
|
||||
String line;
|
||||
StreamReadStatus srs = m_Stream->ReadLine(&line, src, may_wait);
|
||||
|
||||
if (srs != StatusNewItem) {
|
||||
if (src.Size > 8 * 1024)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Line length for HTTP header exceeded"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (line.GetLength() > 8 * 1024) {
|
||||
#ifdef I2_DEBUG /* I2_DEBUG */
|
||||
Log(LogDebug, "HttpRequest")
|
||||
<< "Header size: " << line.GetLength() << " content: '" << line << "'.";
|
||||
#endif /* I2_DEBUG */
|
||||
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Line length for HTTP header exceeded"));
|
||||
}
|
||||
|
||||
if (m_State == HttpRequestStart) {
|
||||
/* ignore trailing new-lines */
|
||||
if (line == "")
|
||||
return true;
|
||||
|
||||
std::vector<String> tokens = line.Split(" ");
|
||||
Log(LogDebug, "HttpRequest")
|
||||
<< "line: " << line << ", tokens: " << tokens.size();
|
||||
if (tokens.size() != 3)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid HTTP request"));
|
||||
|
||||
RequestMethod = tokens[0];
|
||||
RequestUrl = new class Url(tokens[1]);
|
||||
|
||||
if (tokens[2] == "HTTP/1.0")
|
||||
ProtocolVersion = HttpVersion10;
|
||||
else if (tokens[2] == "HTTP/1.1") {
|
||||
ProtocolVersion = HttpVersion11;
|
||||
} else
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Unsupported HTTP version"));
|
||||
|
||||
m_State = HttpRequestHeaders;
|
||||
return true;
|
||||
} else { // m_State = HttpRequestHeaders
|
||||
if (line == "") {
|
||||
m_State = HttpRequestBody;
|
||||
CompleteHeaders = true;
|
||||
return true;
|
||||
|
||||
} else {
|
||||
if (Headers->GetLength() > 128)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Maximum number of HTTP request headers exceeded"));
|
||||
|
||||
String::SizeType pos = line.FindFirstOf(":");
|
||||
if (pos == String::NPos)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid HTTP request"));
|
||||
|
||||
String key = line.SubStr(0, pos).ToLower().Trim();
|
||||
String value = line.SubStr(pos + 1).Trim();
|
||||
Headers->Set(key, value);
|
||||
|
||||
if (key == "x-http-method-override")
|
||||
RequestMethod = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HttpRequest::ParseBody(StreamReadContext& src, bool may_wait)
|
||||
{
|
||||
if (!m_Stream)
|
||||
return false;
|
||||
|
||||
if (m_State != HttpRequestBody)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Invalid HTTP state"));
|
||||
|
||||
/* we're done if the request doesn't contain a message body */
|
||||
if (!Headers->Contains("content-length") && !Headers->Contains("transfer-encoding")) {
|
||||
CompleteBody = true;
|
||||
return true;
|
||||
} else if (!m_Body)
|
||||
m_Body = new FIFO();
|
||||
|
||||
if (Headers->Get("transfer-encoding") == "chunked") {
|
||||
if (!m_ChunkContext)
|
||||
m_ChunkContext = std::make_shared<ChunkReadContext>(std::ref(src));
|
||||
|
||||
char *data;
|
||||
size_t size;
|
||||
StreamReadStatus srs = HttpChunkedEncoding::ReadChunkFromStream(m_Stream, &data, &size, *m_ChunkContext.get(), may_wait);
|
||||
|
||||
if (srs != StatusNewItem)
|
||||
return false;
|
||||
|
||||
m_Body->Write(data, size);
|
||||
|
||||
delete [] data;
|
||||
|
||||
if (size == 0) {
|
||||
CompleteBody = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (src.Eof)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Unexpected EOF in HTTP body"));
|
||||
|
||||
if (src.MustRead) {
|
||||
if (!src.FillFromStream(m_Stream, false)) {
|
||||
src.Eof = true;
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Unexpected EOF in HTTP body"));
|
||||
}
|
||||
|
||||
src.MustRead = false;
|
||||
}
|
||||
|
||||
long length_indicator_signed = Convert::ToLong(Headers->Get("content-length"));
|
||||
|
||||
if (length_indicator_signed < 0)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Content-Length must not be negative."));
|
||||
|
||||
size_t length_indicator = length_indicator_signed;
|
||||
|
||||
if (src.Size < length_indicator) {
|
||||
src.MustRead = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Body->Write(src.Buffer, length_indicator);
|
||||
src.DropData(length_indicator);
|
||||
CompleteBody = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t HttpRequest::ReadBody(char *data, size_t count)
|
||||
{
|
||||
if (!m_Body)
|
||||
return 0;
|
||||
else
|
||||
return m_Body->Read(data, count, true);
|
||||
}
|
||||
|
||||
void HttpRequest::AddHeader(const String& key, const String& value)
|
||||
{
|
||||
ASSERT(m_State == HttpRequestStart || m_State == HttpRequestHeaders);
|
||||
Headers->Set(key.ToLower(), value);
|
||||
}
|
||||
|
||||
void HttpRequest::FinishHeaders()
|
||||
{
|
||||
if (m_State == HttpRequestStart) {
|
||||
String rqline = RequestMethod + " " + RequestUrl->Format(true) + " HTTP/1." + (ProtocolVersion == HttpVersion10 ? "0" : "1") + "\r\n";
|
||||
m_Stream->Write(rqline.CStr(), rqline.GetLength());
|
||||
m_State = HttpRequestHeaders;
|
||||
}
|
||||
|
||||
if (m_State == HttpRequestHeaders) {
|
||||
AddHeader("User-Agent", "Icinga/" + Application::GetAppVersion());
|
||||
|
||||
if (ProtocolVersion == HttpVersion11) {
|
||||
AddHeader("Transfer-Encoding", "chunked");
|
||||
if (!Headers->Contains("Host"))
|
||||
AddHeader("Host", RequestUrl->GetHost() + ":" + RequestUrl->GetPort());
|
||||
}
|
||||
|
||||
ObjectLock olock(Headers);
|
||||
for (const Dictionary::Pair& kv : Headers)
|
||||
{
|
||||
String header = kv.first + ": " + kv.second + "\r\n";
|
||||
m_Stream->Write(header.CStr(), header.GetLength());
|
||||
}
|
||||
|
||||
m_Stream->Write("\r\n", 2);
|
||||
|
||||
m_State = HttpRequestBody;
|
||||
}
|
||||
}
|
||||
|
||||
void HttpRequest::WriteBody(const char *data, size_t count)
|
||||
{
|
||||
ASSERT(m_State == HttpRequestStart || m_State == HttpRequestHeaders || m_State == HttpRequestBody);
|
||||
|
||||
if (ProtocolVersion == HttpVersion10) {
|
||||
if (!m_Body)
|
||||
m_Body = new FIFO();
|
||||
|
||||
m_Body->Write(data, count);
|
||||
} else {
|
||||
FinishHeaders();
|
||||
|
||||
HttpChunkedEncoding::WriteChunkToStream(m_Stream, data, count);
|
||||
}
|
||||
}
|
||||
|
||||
void HttpRequest::Finish()
|
||||
{
|
||||
ASSERT(m_State != HttpRequestEnd);
|
||||
|
||||
if (ProtocolVersion == HttpVersion10) {
|
||||
if (m_Body)
|
||||
AddHeader("Content-Length", Convert::ToString(m_Body->GetAvailableBytes()));
|
||||
|
||||
FinishHeaders();
|
||||
|
||||
while (m_Body && m_Body->IsDataAvailable()) {
|
||||
char buffer[1024];
|
||||
size_t rc = m_Body->Read(buffer, sizeof(buffer), true);
|
||||
m_Stream->Write(buffer, rc);
|
||||
}
|
||||
} else {
|
||||
if (m_State == HttpRequestStart || m_State == HttpRequestHeaders)
|
||||
FinishHeaders();
|
||||
|
||||
WriteBody(nullptr, 0);
|
||||
m_Stream->Write("\r\n", 2);
|
||||
}
|
||||
|
||||
m_State = HttpRequestEnd;
|
||||
}
|
||||
|
@ -1,69 +0,0 @@
|
||||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#ifndef HTTPREQUEST_H
|
||||
#define HTTPREQUEST_H
|
||||
|
||||
#include "remote/i2-remote.hpp"
|
||||
#include "remote/httpchunkedencoding.hpp"
|
||||
#include "remote/url.hpp"
|
||||
#include "base/stream.hpp"
|
||||
#include "base/fifo.hpp"
|
||||
#include "base/dictionary.hpp"
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
enum HttpVersion
|
||||
{
|
||||
HttpVersion10,
|
||||
HttpVersion11
|
||||
};
|
||||
|
||||
enum HttpRequestState
|
||||
{
|
||||
HttpRequestStart,
|
||||
HttpRequestHeaders,
|
||||
HttpRequestBody,
|
||||
HttpRequestEnd
|
||||
};
|
||||
|
||||
/**
|
||||
* An HTTP request.
|
||||
*
|
||||
* @ingroup remote
|
||||
*/
|
||||
struct HttpRequest
|
||||
{
|
||||
public:
|
||||
bool CompleteHeaders;
|
||||
bool CompleteHeaderCheck;
|
||||
bool CompleteBody;
|
||||
|
||||
String RequestMethod;
|
||||
Url::Ptr RequestUrl;
|
||||
HttpVersion ProtocolVersion;
|
||||
|
||||
Dictionary::Ptr Headers;
|
||||
|
||||
HttpRequest(Stream::Ptr stream);
|
||||
|
||||
bool ParseHeaders(StreamReadContext& src, bool may_wait);
|
||||
bool ParseBody(StreamReadContext& src, bool may_wait);
|
||||
size_t ReadBody(char *data, size_t count);
|
||||
|
||||
void AddHeader(const String& key, const String& value);
|
||||
void WriteBody(const char *data, size_t count);
|
||||
void Finish();
|
||||
|
||||
private:
|
||||
Stream::Ptr m_Stream;
|
||||
std::shared_ptr<ChunkReadContext> m_ChunkContext;
|
||||
HttpRequestState m_State;
|
||||
FIFO::Ptr m_Body;
|
||||
|
||||
void FinishHeaders();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* HTTPREQUEST_H */
|
@ -1,259 +0,0 @@
|
||||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#include "remote/httpresponse.hpp"
|
||||
#include "remote/httpchunkedencoding.hpp"
|
||||
#include "base/logger.hpp"
|
||||
#include "base/application.hpp"
|
||||
#include "base/convert.hpp"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
HttpResponse::HttpResponse(Stream::Ptr stream, const HttpRequest& request)
|
||||
: Complete(false), m_State(HttpResponseStart), m_Request(&request), m_Stream(std::move(stream))
|
||||
{ }
|
||||
|
||||
void HttpResponse::SetStatus(int code, const String& message)
|
||||
{
|
||||
ASSERT(code >= 100 && code <= 599);
|
||||
ASSERT(!message.IsEmpty());
|
||||
|
||||
if (m_State != HttpResponseStart) {
|
||||
Log(LogWarning, "HttpResponse", "Tried to set Http response status after headers had already been sent.");
|
||||
return;
|
||||
}
|
||||
|
||||
String status = "HTTP/";
|
||||
|
||||
if (m_Request->ProtocolVersion == HttpVersion10)
|
||||
status += "1.0";
|
||||
else
|
||||
status += "1.1";
|
||||
|
||||
status += " " + Convert::ToString(code) + " " + message + "\r\n";
|
||||
|
||||
m_Stream->Write(status.CStr(), status.GetLength());
|
||||
|
||||
m_State = HttpResponseHeaders;
|
||||
}
|
||||
|
||||
void HttpResponse::AddHeader(const String& key, const String& value)
|
||||
{
|
||||
m_Headers.emplace_back(key + ": " + value + "\r\n");
|
||||
}
|
||||
|
||||
void HttpResponse::FinishHeaders()
|
||||
{
|
||||
if (m_State == HttpResponseHeaders) {
|
||||
if (m_Request->ProtocolVersion == HttpVersion11)
|
||||
AddHeader("Transfer-Encoding", "chunked");
|
||||
|
||||
AddHeader("Server", "Icinga/" + Application::GetAppVersion());
|
||||
|
||||
for (const String& header : m_Headers)
|
||||
m_Stream->Write(header.CStr(), header.GetLength());
|
||||
|
||||
m_Stream->Write("\r\n", 2);
|
||||
m_State = HttpResponseBody;
|
||||
}
|
||||
}
|
||||
|
||||
void HttpResponse::WriteBody(const char *data, size_t count)
|
||||
{
|
||||
ASSERT(m_State == HttpResponseHeaders || m_State == HttpResponseBody);
|
||||
|
||||
if (m_Request->ProtocolVersion == HttpVersion10) {
|
||||
if (!m_Body)
|
||||
m_Body = new FIFO();
|
||||
|
||||
m_Body->Write(data, count);
|
||||
} else {
|
||||
FinishHeaders();
|
||||
|
||||
HttpChunkedEncoding::WriteChunkToStream(m_Stream, data, count);
|
||||
}
|
||||
}
|
||||
|
||||
void HttpResponse::Finish()
|
||||
{
|
||||
ASSERT(m_State != HttpResponseEnd);
|
||||
|
||||
if (m_Request->ProtocolVersion == HttpVersion10) {
|
||||
if (m_Body)
|
||||
AddHeader("Content-Length", Convert::ToString(m_Body->GetAvailableBytes()));
|
||||
|
||||
FinishHeaders();
|
||||
|
||||
while (m_Body && m_Body->IsDataAvailable()) {
|
||||
char buffer[1024];
|
||||
size_t rc = m_Body->Read(buffer, sizeof(buffer), true);
|
||||
m_Stream->Write(buffer, rc);
|
||||
}
|
||||
} else {
|
||||
WriteBody(nullptr, 0);
|
||||
m_Stream->Write("\r\n", 2);
|
||||
}
|
||||
|
||||
m_State = HttpResponseEnd;
|
||||
|
||||
/* Close the connection on
|
||||
* a) HTTP/1.0
|
||||
* b) Connection: close in the sent header.
|
||||
*
|
||||
* Do this here and not in DataAvailableHandler - there might still be incoming data in there.
|
||||
*/
|
||||
if (m_Request->ProtocolVersion == HttpVersion10 || m_Request->Headers->Get("connection") == "close")
|
||||
m_Stream->Shutdown();
|
||||
}
|
||||
|
||||
bool HttpResponse::Parse(StreamReadContext& src, bool may_wait)
|
||||
{
|
||||
if (m_State != HttpResponseBody) {
|
||||
String line;
|
||||
StreamReadStatus srs = m_Stream->ReadLine(&line, src, may_wait);
|
||||
|
||||
if (srs != StatusNewItem)
|
||||
return false;
|
||||
|
||||
if (m_State == HttpResponseStart) {
|
||||
/* ignore trailing new-lines */
|
||||
if (line == "")
|
||||
return true;
|
||||
|
||||
std::vector<String> tokens = line.Split(" ");
|
||||
Log(LogDebug, "HttpRequest")
|
||||
<< "line: " << line << ", tokens: " << tokens.size();
|
||||
if (tokens.size() < 2)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid HTTP response (Status line)"));
|
||||
|
||||
if (tokens[0] == "HTTP/1.0")
|
||||
ProtocolVersion = HttpVersion10;
|
||||
else if (tokens[0] == "HTTP/1.1") {
|
||||
ProtocolVersion = HttpVersion11;
|
||||
} else
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Unsupported HTTP version"));
|
||||
|
||||
StatusCode = Convert::ToLong(tokens[1]);
|
||||
|
||||
if (tokens.size() >= 3)
|
||||
StatusMessage = tokens[2]; // TODO: Join tokens[2..end]
|
||||
|
||||
m_State = HttpResponseHeaders;
|
||||
} else if (m_State == HttpResponseHeaders) {
|
||||
if (!Headers)
|
||||
Headers = new Dictionary();
|
||||
|
||||
if (line == "") {
|
||||
m_State = HttpResponseBody;
|
||||
m_Body = new FIFO();
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
String::SizeType pos = line.FindFirstOf(":");
|
||||
if (pos == String::NPos)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid HTTP request"));
|
||||
String key = line.SubStr(0, pos).ToLower().Trim();
|
||||
|
||||
String value = line.SubStr(pos + 1).Trim();
|
||||
Headers->Set(key, value);
|
||||
}
|
||||
} else {
|
||||
VERIFY(!"Invalid HTTP request state.");
|
||||
}
|
||||
} else if (m_State == HttpResponseBody) {
|
||||
if (Headers->Get("transfer-encoding") == "chunked") {
|
||||
if (!m_ChunkContext)
|
||||
m_ChunkContext = std::make_shared<ChunkReadContext>(std::ref(src));
|
||||
|
||||
char *data;
|
||||
size_t size;
|
||||
StreamReadStatus srs = HttpChunkedEncoding::ReadChunkFromStream(m_Stream, &data, &size, *m_ChunkContext.get(), may_wait);
|
||||
|
||||
if (srs != StatusNewItem)
|
||||
return false;
|
||||
|
||||
Log(LogNotice, "HttpResponse")
|
||||
<< "Read " << size << " bytes";
|
||||
|
||||
m_Body->Write(data, size);
|
||||
|
||||
delete[] data;
|
||||
|
||||
if (size == 0) {
|
||||
Complete = true;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
bool hasLengthIndicator = false;
|
||||
size_t lengthIndicator = 0;
|
||||
Value contentLengthHeader;
|
||||
|
||||
if (Headers->Get("content-length", &contentLengthHeader)) {
|
||||
hasLengthIndicator = true;
|
||||
lengthIndicator = Convert::ToLong(contentLengthHeader);
|
||||
}
|
||||
|
||||
if (!hasLengthIndicator && ProtocolVersion != HttpVersion10 && !Headers->Contains("transfer-encoding")) {
|
||||
Complete = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hasLengthIndicator && src.Eof)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Unexpected EOF in HTTP body"));
|
||||
|
||||
if (src.MustRead) {
|
||||
if (!src.FillFromStream(m_Stream, may_wait))
|
||||
src.Eof = true;
|
||||
|
||||
src.MustRead = false;
|
||||
}
|
||||
|
||||
if (!hasLengthIndicator)
|
||||
lengthIndicator = src.Size;
|
||||
|
||||
if (src.Size < lengthIndicator) {
|
||||
src.MustRead = true;
|
||||
return may_wait;
|
||||
}
|
||||
|
||||
m_Body->Write(src.Buffer, lengthIndicator);
|
||||
src.DropData(lengthIndicator);
|
||||
|
||||
if (!hasLengthIndicator && !src.Eof) {
|
||||
src.MustRead = true;
|
||||
return may_wait;
|
||||
}
|
||||
|
||||
Complete = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t HttpResponse::ReadBody(char *data, size_t count)
|
||||
{
|
||||
if (!m_Body)
|
||||
return 0;
|
||||
else
|
||||
return m_Body->Read(data, count, true);
|
||||
}
|
||||
|
||||
size_t HttpResponse::GetBodySize() const
|
||||
{
|
||||
if (!m_Body)
|
||||
return 0;
|
||||
else
|
||||
return m_Body->GetAvailableBytes();
|
||||
}
|
||||
|
||||
bool HttpResponse::IsPeerConnected() const
|
||||
{
|
||||
return !m_Stream->IsEof();
|
||||
}
|
||||
|
||||
void HttpResponse::RebindRequest(const HttpRequest& request)
|
||||
{
|
||||
m_Request = &request;
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#ifndef HTTPRESPONSE_H
|
||||
#define HTTPRESPONSE_H
|
||||
|
||||
#include "remote/httprequest.hpp"
|
||||
#include "base/stream.hpp"
|
||||
#include "base/fifo.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
enum HttpResponseState
|
||||
{
|
||||
HttpResponseStart,
|
||||
HttpResponseHeaders,
|
||||
HttpResponseBody,
|
||||
HttpResponseEnd
|
||||
};
|
||||
|
||||
/**
|
||||
* An HTTP response.
|
||||
*
|
||||
* @ingroup remote
|
||||
*/
|
||||
struct HttpResponse
|
||||
{
|
||||
public:
|
||||
bool Complete;
|
||||
|
||||
HttpVersion ProtocolVersion;
|
||||
int StatusCode;
|
||||
String StatusMessage;
|
||||
|
||||
Dictionary::Ptr Headers;
|
||||
|
||||
HttpResponse(Stream::Ptr stream, const HttpRequest& request);
|
||||
|
||||
bool Parse(StreamReadContext& src, bool may_wait);
|
||||
size_t ReadBody(char *data, size_t count);
|
||||
size_t GetBodySize() const;
|
||||
|
||||
void SetStatus(int code, const String& message);
|
||||
void AddHeader(const String& key, const String& value);
|
||||
void WriteBody(const char *data, size_t count);
|
||||
void Finish();
|
||||
|
||||
bool IsPeerConnected() const;
|
||||
|
||||
void RebindRequest(const HttpRequest& request);
|
||||
|
||||
private:
|
||||
HttpResponseState m_State;
|
||||
std::shared_ptr<ChunkReadContext> m_ChunkContext;
|
||||
const HttpRequest *m_Request;
|
||||
Stream::Ptr m_Stream;
|
||||
FIFO::Ptr m_Body;
|
||||
std::vector<String> m_Headers;
|
||||
|
||||
void FinishHeaders();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* HTTPRESPONSE_H */
|
@ -37,29 +37,6 @@ Dictionary::Ptr HttpUtility::FetchRequestParameters(const Url::Ptr& url, const s
|
||||
return result;
|
||||
}
|
||||
|
||||
void HttpUtility::SendJsonBody(HttpResponse& response, const Dictionary::Ptr& params, const Value& val)
|
||||
{
|
||||
response.AddHeader("Content-Type", "application/json");
|
||||
|
||||
bool prettyPrint = false;
|
||||
|
||||
if (params)
|
||||
prettyPrint = GetLastParameter(params, "pretty");
|
||||
|
||||
String body = JsonEncode(val, prettyPrint);
|
||||
|
||||
response.WriteBody(body.CStr(), body.GetLength());
|
||||
}
|
||||
|
||||
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.set(http::field::content_length, response.body().size());
|
||||
}
|
||||
|
||||
Value HttpUtility::GetLastParameter(const Dictionary::Ptr& params, const String& key)
|
||||
{
|
||||
Value varr = params->Get(key);
|
||||
@ -75,27 +52,13 @@ Value HttpUtility::GetLastParameter(const Dictionary::Ptr& params, const String&
|
||||
return arr->Get(arr->GetLength() - 1);
|
||||
}
|
||||
|
||||
void HttpUtility::SendJsonError(HttpResponse& response, const Dictionary::Ptr& params,
|
||||
int code, const String& info, const String& diagnosticInformation)
|
||||
void HttpUtility::SendJsonBody(boost::beast::http::response<boost::beast::http::string_body>& response, const Dictionary::Ptr& params, const Value& val)
|
||||
{
|
||||
Dictionary::Ptr result = new Dictionary();
|
||||
response.SetStatus(code, HttpUtility::GetErrorNameByCode(code));
|
||||
result->Set("error", code);
|
||||
namespace http = boost::beast::http;
|
||||
|
||||
bool verbose = false;
|
||||
|
||||
if (params)
|
||||
verbose = HttpUtility::GetLastParameter(params, "verbose");
|
||||
|
||||
if (!info.IsEmpty())
|
||||
result->Set("status", info);
|
||||
|
||||
if (verbose) {
|
||||
if (!diagnosticInformation.IsEmpty())
|
||||
result->Set("diagnostic_information", diagnosticInformation);
|
||||
}
|
||||
|
||||
HttpUtility::SendJsonBody(response, params, result);
|
||||
response.set(http::field::content_type, "application/json");
|
||||
response.body() = JsonEncode(val, params && GetLastParameter(params, "pretty"));
|
||||
response.set(http::field::content_length, response.body().size());
|
||||
}
|
||||
|
||||
void HttpUtility::SendJsonError(boost::beast::http::response<boost::beast::http::string_body>& response,
|
||||
@ -115,32 +78,3 @@ void HttpUtility::SendJsonError(boost::beast::http::response<boost::beast::http:
|
||||
|
||||
HttpUtility::SendJsonBody(response, params, result);
|
||||
}
|
||||
|
||||
String HttpUtility::GetErrorNameByCode(const int code)
|
||||
{
|
||||
switch(code) {
|
||||
case 200:
|
||||
return "OK";
|
||||
case 201:
|
||||
return "Created";
|
||||
case 204:
|
||||
return "No Content";
|
||||
case 304:
|
||||
return "Not Modified";
|
||||
case 400:
|
||||
return "Bad Request";
|
||||
case 401:
|
||||
return "Unauthorized";
|
||||
case 403:
|
||||
return "Forbidden";
|
||||
case 404:
|
||||
return "Not Found";
|
||||
case 409:
|
||||
return "Conflict";
|
||||
case 500:
|
||||
return "Internal Server Error";
|
||||
default:
|
||||
return "Unknown Error Code";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,12 +3,10 @@
|
||||
#ifndef HTTPUTILITY_H
|
||||
#define HTTPUTILITY_H
|
||||
|
||||
#include "remote/httprequest.hpp"
|
||||
#include "remote/httpresponse.hpp"
|
||||
#include "remote/url.hpp"
|
||||
#include "base/dictionary.hpp"
|
||||
#include <string>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
@ -23,17 +21,11 @@ class HttpUtility
|
||||
|
||||
public:
|
||||
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);
|
||||
static void SendJsonError(HttpResponse& response, const Dictionary::Ptr& params, const int code,
|
||||
const String& verbose = String(), const String& diagnosticInformation = String());
|
||||
|
||||
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());
|
||||
|
||||
private:
|
||||
static String GetErrorNameByCode(int code);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user