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