1
1
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
2
3
3
#include " remote/objectqueryhandler.hpp"
4
+ #include " base/generator.hpp"
5
+ #include " base/json.hpp"
4
6
#include " remote/httputility.hpp"
5
7
#include " remote/filterutility.hpp"
6
8
#include " base/serializer.hpp"
9
11
#include < boost/algorithm/string/case_conv.hpp>
10
12
#include < set>
11
13
#include < unordered_map>
14
+ #include < memory>
12
15
13
16
using namespace icinga ;
14
17
@@ -144,6 +147,16 @@ bool ObjectQueryHandler::HandleRequest(
144
147
return true ;
145
148
}
146
149
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
+
147
160
bool allJoins = HttpUtility::GetLastParameter (params, " all_joins" );
148
161
149
162
params->Set (" type" , type->GetName ());
@@ -165,9 +178,6 @@ bool ObjectQueryHandler::HandleRequest(
165
178
return true ;
166
179
}
167
180
168
- ArrayData results;
169
- results.reserve (objs.size ());
170
-
171
181
std::set<String> joinAttrs;
172
182
std::set<String> userJoinAttrs;
173
183
@@ -193,14 +203,21 @@ bool ObjectQueryHandler::HandleRequest(
193
203
std::unordered_map<Type*, std::pair<bool , std::unique_ptr<Expression>>> typePermissions;
194
204
std::unordered_map<Object*, bool > objectAccessAllowed;
195
205
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
+
197
215
DictionaryData result1{
198
216
{ " name" , obj->GetName () },
199
217
{ " type" , obj->GetReflectionType ()->GetName () }
200
218
};
201
219
202
220
DictionaryData metaAttrs;
203
-
204
221
if (umetas) {
205
222
ObjectLock olock (umetas);
206
223
for (String meta : umetas) {
@@ -216,9 +233,6 @@ bool ObjectQueryHandler::HandleRequest(
216
233
}
217
234
} else if (meta == " location" ) {
218
235
metaAttrs.emplace_back (" location" , obj->GetSourceLocation ());
219
- } else {
220
- HttpUtility::SendJsonError (response, params, 400 , " Invalid field specified for meta: " + meta);
221
- return true ;
222
236
}
223
237
}
224
238
}
@@ -228,8 +242,12 @@ bool ObjectQueryHandler::HandleRequest(
228
242
try {
229
243
result1.emplace_back (" attrs" , SerializeObjectAttrs (obj, String (), uattrs, false , false ));
230
244
} 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
+ };
233
251
}
234
252
235
253
DictionaryData joins;
@@ -238,18 +256,8 @@ bool ObjectQueryHandler::HandleRequest(
238
256
Object::Ptr joinedObj;
239
257
int fid = type->GetFieldId (joinAttr);
240
258
241
- if (fid < 0 ) {
242
- HttpUtility::SendJsonError (response, params, 400 , " Invalid field specified for join: " + joinAttr);
243
- return true ;
244
- }
245
-
246
259
Field field = type->GetFieldInfo (fid);
247
260
248
- if (!(field.Attributes & FANavigation)) {
249
- HttpUtility::SendJsonError (response, params, 400 , " Not a joinable field: " + joinAttr);
250
- return true ;
251
- }
252
-
253
261
joinedObj = obj->NavigateField (fid);
254
262
255
263
if (!joinedObj)
@@ -303,22 +311,29 @@ bool ObjectQueryHandler::HandleRequest(
303
311
try {
304
312
joins.emplace_back (prefix, SerializeObjectAttrs (joinedObj, prefix, ujoins, true , allJoins));
305
313
} 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
+ };
308
320
}
309
321
}
310
322
311
323
result1.emplace_back (" joins" , new Dictionary (std::move (joins)));
312
324
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
+ };
319
327
320
328
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);
322
337
323
338
return true ;
324
339
}
0 commit comments