1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2 
3 #include "remote/httputility.hpp"
4 #include "remote/url.hpp"
5 #include "base/json.hpp"
6 #include "base/logger.hpp"
7 #include <map>
8 #include <string>
9 #include <vector>
10 #include <boost/beast/http.hpp>
11 
12 using namespace icinga;
13 
FetchRequestParameters(const Url::Ptr & url,const std::string & body)14 Dictionary::Ptr HttpUtility::FetchRequestParameters(const Url::Ptr& url, const std::string& body)
15 {
16 	Dictionary::Ptr result;
17 
18 	if (!body.empty()) {
19 		Log(LogDebug, "HttpUtility")
20 			<< "Request body: '" << body << '\'';
21 
22 		result = JsonDecode(body);
23 	}
24 
25 	if (!result)
26 		result = new Dictionary();
27 
28 	std::map<String, std::vector<String>> query;
29 	for (const auto& kv : url->GetQuery()) {
30 		query[kv.first].emplace_back(kv.second);
31 	}
32 
33 	for (auto& kv : query) {
34 		result->Set(kv.first, Array::FromVector(kv.second));
35 	}
36 
37 	return result;
38 }
39 
GetLastParameter(const Dictionary::Ptr & params,const String & key)40 Value HttpUtility::GetLastParameter(const Dictionary::Ptr& params, const String& key)
41 {
42 	Value varr = params->Get(key);
43 
44 	if (!varr.IsObjectType<Array>())
45 		return varr;
46 
47 	Array::Ptr arr = varr;
48 
49 	if (arr->GetLength() == 0)
50 		return Empty;
51 	else
52 		return arr->Get(arr->GetLength() - 1);
53 }
54 
SendJsonBody(boost::beast::http::response<boost::beast::http::string_body> & response,const Dictionary::Ptr & params,const Value & val)55 void HttpUtility::SendJsonBody(boost::beast::http::response<boost::beast::http::string_body>& response, const Dictionary::Ptr& params, const Value& val)
56 {
57 	namespace http = boost::beast::http;
58 
59 	response.set(http::field::content_type, "application/json");
60 	response.body() = JsonEncode(val, params && GetLastParameter(params, "pretty"));
61 	response.content_length(response.body().size());
62 }
63 
SendJsonError(boost::beast::http::response<boost::beast::http::string_body> & response,const Dictionary::Ptr & params,int code,const String & info,const String & diagnosticInformation)64 void HttpUtility::SendJsonError(boost::beast::http::response<boost::beast::http::string_body>& response,
65 	const Dictionary::Ptr& params, int code, const String& info, const String& diagnosticInformation)
66 {
67 	Dictionary::Ptr result = new Dictionary({ { "error", code } });
68 
69 	if (!info.IsEmpty()) {
70 		result->Set("status", info);
71 	}
72 
73 	if (params && HttpUtility::GetLastParameter(params, "verbose") && !diagnosticInformation.IsEmpty()) {
74 		result->Set("diagnostic_information", diagnosticInformation);
75 	}
76 
77 	response.result(code);
78 
79 	HttpUtility::SendJsonBody(response, params, result);
80 }
81