Skip to content

Commit 88c16d4

Browse files
Refactor ObjectQueryHandler to use new JSON stream encoder
1 parent 0cf491e commit 88c16d4

File tree

1 file changed

+44
-29
lines changed

1 file changed

+44
-29
lines changed

lib/remote/objectqueryhandler.cpp

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
22

33
#include "remote/objectqueryhandler.hpp"
4+
#include "base/generator.hpp"
5+
#include "base/json.hpp"
46
#include "remote/httputility.hpp"
57
#include "remote/filterutility.hpp"
68
#include "base/serializer.hpp"
@@ -9,6 +11,7 @@
911
#include <boost/algorithm/string/case_conv.hpp>
1012
#include <set>
1113
#include <unordered_map>
14+
#include <memory>
1215

1316
using namespace icinga;
1417

@@ -144,6 +147,16 @@ bool ObjectQueryHandler::HandleRequest(
144147
return true;
145148
}
146149

150+
if(umetas){
151+
ObjectLock olock(umetas);
152+
for (String meta : umetas) {
153+
if (!(meta == "used_by" || meta == "location")) {
154+
HttpUtility::SendJsonError(response, params, 400, "Invalid field specified for meta: " + meta);
155+
return true;
156+
}
157+
}
158+
}
159+
147160
bool allJoins = HttpUtility::GetLastParameter(params, "all_joins");
148161

149162
params->Set("type", type->GetName());
@@ -165,9 +178,6 @@ bool ObjectQueryHandler::HandleRequest(
165178
return true;
166179
}
167180

168-
ArrayData results;
169-
results.reserve(objs.size());
170-
171181
std::set<String> joinAttrs;
172182
std::set<String> userJoinAttrs;
173183

@@ -193,14 +203,21 @@ bool ObjectQueryHandler::HandleRequest(
193203
std::unordered_map<Type*, std::pair<bool, std::unique_ptr<Expression>>> typePermissions;
194204
std::unordered_map<Object*, bool> objectAccessAllowed;
195205

196-
for (ConfigObject::Ptr obj : objs) {
206+
auto it = objs.begin();
207+
auto generatorFunc = [&]() -> std::optional<Value> {
208+
if (it == objs.end()) {
209+
return std::nullopt;
210+
}
211+
212+
ConfigObject::Ptr obj = *it;
213+
++it;
214+
197215
DictionaryData result1{
198216
{ "name", obj->GetName() },
199217
{ "type", obj->GetReflectionType()->GetName() }
200218
};
201219

202220
DictionaryData metaAttrs;
203-
204221
if (umetas) {
205222
ObjectLock olock(umetas);
206223
for (String meta : umetas) {
@@ -216,9 +233,6 @@ bool ObjectQueryHandler::HandleRequest(
216233
}
217234
} else if (meta == "location") {
218235
metaAttrs.emplace_back("location", obj->GetSourceLocation());
219-
} else {
220-
HttpUtility::SendJsonError(response, params, 400, "Invalid field specified for meta: " + meta);
221-
return true;
222236
}
223237
}
224238
}
@@ -228,8 +242,12 @@ bool ObjectQueryHandler::HandleRequest(
228242
try {
229243
result1.emplace_back("attrs", SerializeObjectAttrs(obj, String(), uattrs, false, false));
230244
} catch (const ScriptError& ex) {
231-
HttpUtility::SendJsonError(response, params, 400, ex.what());
232-
return true;
245+
return new Dictionary{
246+
{"type", type->GetName()},
247+
{"name", obj->GetName()},
248+
{"code", 400},
249+
{"status", ex.what()}
250+
};
233251
}
234252

235253
DictionaryData joins;
@@ -238,18 +256,8 @@ bool ObjectQueryHandler::HandleRequest(
238256
Object::Ptr joinedObj;
239257
int fid = type->GetFieldId(joinAttr);
240258

241-
if (fid < 0) {
242-
HttpUtility::SendJsonError(response, params, 400, "Invalid field specified for join: " + joinAttr);
243-
return true;
244-
}
245-
246259
Field field = type->GetFieldInfo(fid);
247260

248-
if (!(field.Attributes & FANavigation)) {
249-
HttpUtility::SendJsonError(response, params, 400, "Not a joinable field: " + joinAttr);
250-
return true;
251-
}
252-
253261
joinedObj = obj->NavigateField(fid);
254262

255263
if (!joinedObj)
@@ -303,22 +311,29 @@ bool ObjectQueryHandler::HandleRequest(
303311
try {
304312
joins.emplace_back(prefix, SerializeObjectAttrs(joinedObj, prefix, ujoins, true, allJoins));
305313
} catch (const ScriptError& ex) {
306-
HttpUtility::SendJsonError(response, params, 400, ex.what());
307-
return true;
314+
return new Dictionary{
315+
{"type", type->GetName()},
316+
{"name", obj->GetName()},
317+
{"code", 400},
318+
{"status", ex.what()}
319+
};
308320
}
309321
}
310322

311323
result1.emplace_back("joins", new Dictionary(std::move(joins)));
312324

313-
results.push_back(new Dictionary(std::move(result1)));
314-
}
315-
316-
Dictionary::Ptr result = new Dictionary({
317-
{ "results", new Array(std::move(results)) }
318-
});
325+
return new Dictionary{std::move(result1)};
326+
};
319327

320328
response.result(http::status::ok);
321-
HttpUtility::SendJsonBody(response, params, result);
329+
response.set(http::field::content_type, "application/json");
330+
response.StartStreaming();
331+
332+
Dictionary::Ptr results = new Dictionary{{"results", new ValueGenerator{generatorFunc}}};
333+
results->Freeze();
334+
335+
bool pretty = HttpUtility::GetLastParameter(params, "pretty");
336+
response.GetJsonEncoder(pretty).Encode(results, &yc);
322337

323338
return true;
324339
}

0 commit comments

Comments
 (0)