3 inline int web_client_api_request_v1_data_group(char *name, int def) {
4 if(!strcmp(name, "average"))
7 else if(!strcmp(name, "min"))
10 else if(!strcmp(name, "max"))
13 else if(!strcmp(name, "sum"))
16 else if(!strcmp(name, "incremental-sum"))
17 return GROUP_INCREMENTAL_SUM;
22 inline uint32_t web_client_api_request_v1_data_options(char *o) {
23 uint32_t ret = 0x00000000;
26 while(o && *o && (tok = mystrsep(&o, ", |"))) {
29 if(!strcmp(tok, "nonzero"))
30 ret |= RRDR_OPTION_NONZERO;
31 else if(!strcmp(tok, "flip") || !strcmp(tok, "reversed") || !strcmp(tok, "reverse"))
32 ret |= RRDR_OPTION_REVERSED;
33 else if(!strcmp(tok, "jsonwrap"))
34 ret |= RRDR_OPTION_JSON_WRAP;
35 else if(!strcmp(tok, "min2max"))
36 ret |= RRDR_OPTION_MIN2MAX;
37 else if(!strcmp(tok, "ms") || !strcmp(tok, "milliseconds"))
38 ret |= RRDR_OPTION_MILLISECONDS;
39 else if(!strcmp(tok, "abs") || !strcmp(tok, "absolute") || !strcmp(tok, "absolute_sum") || !strcmp(tok, "absolute-sum"))
40 ret |= RRDR_OPTION_ABSOLUTE;
41 else if(!strcmp(tok, "seconds"))
42 ret |= RRDR_OPTION_SECONDS;
43 else if(!strcmp(tok, "null2zero"))
44 ret |= RRDR_OPTION_NULL2ZERO;
45 else if(!strcmp(tok, "objectrows"))
46 ret |= RRDR_OPTION_OBJECTSROWS;
47 else if(!strcmp(tok, "google_json"))
48 ret |= RRDR_OPTION_GOOGLE_JSON;
49 else if(!strcmp(tok, "percentage"))
50 ret |= RRDR_OPTION_PERCENTAGE;
51 else if(!strcmp(tok, "unaligned"))
52 ret |= RRDR_OPTION_NOT_ALIGNED;
58 inline uint32_t web_client_api_request_v1_data_format(char *name) {
59 if(!strcmp(name, DATASOURCE_FORMAT_DATATABLE_JSON)) // datatable
60 return DATASOURCE_DATATABLE_JSON;
62 else if(!strcmp(name, DATASOURCE_FORMAT_DATATABLE_JSONP)) // datasource
63 return DATASOURCE_DATATABLE_JSONP;
65 else if(!strcmp(name, DATASOURCE_FORMAT_JSON)) // json
66 return DATASOURCE_JSON;
68 else if(!strcmp(name, DATASOURCE_FORMAT_JSONP)) // jsonp
69 return DATASOURCE_JSONP;
71 else if(!strcmp(name, DATASOURCE_FORMAT_SSV)) // ssv
72 return DATASOURCE_SSV;
74 else if(!strcmp(name, DATASOURCE_FORMAT_CSV)) // csv
75 return DATASOURCE_CSV;
77 else if(!strcmp(name, DATASOURCE_FORMAT_TSV) || !strcmp(name, "tsv-excel")) // tsv
78 return DATASOURCE_TSV;
80 else if(!strcmp(name, DATASOURCE_FORMAT_HTML)) // html
81 return DATASOURCE_HTML;
83 else if(!strcmp(name, DATASOURCE_FORMAT_JS_ARRAY)) // array
84 return DATASOURCE_JS_ARRAY;
86 else if(!strcmp(name, DATASOURCE_FORMAT_SSV_COMMA)) // ssvcomma
87 return DATASOURCE_SSV_COMMA;
89 else if(!strcmp(name, DATASOURCE_FORMAT_CSV_JSON_ARRAY)) // csvjsonarray
90 return DATASOURCE_CSV_JSON_ARRAY;
92 return DATASOURCE_JSON;
95 inline uint32_t web_client_api_request_v1_data_google_format(char *name) {
96 if(!strcmp(name, "json"))
97 return DATASOURCE_DATATABLE_JSONP;
99 else if(!strcmp(name, "html"))
100 return DATASOURCE_HTML;
102 else if(!strcmp(name, "csv"))
103 return DATASOURCE_CSV;
105 else if(!strcmp(name, "tsv-excel"))
106 return DATASOURCE_TSV;
108 return DATASOURCE_JSON;
112 inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, char *url) {
116 char *value = mystrsep(&url, "?&");
117 if (!value || !*value) continue;
119 if(!strcmp(value, "all")) all = 1;
120 else if(!strcmp(value, "active")) all = 0;
123 buffer_flush(w->response.data);
124 w->response.data->contenttype = CT_APPLICATION_JSON;
125 health_alarms2json(host, w->response.data, all);
129 inline int web_client_api_request_v1_alarm_log(RRDHOST *host, struct web_client *w, char *url) {
133 char *value = mystrsep(&url, "?&");
134 if (!value || !*value) continue;
136 char *name = mystrsep(&value, "=");
137 if(!name || !*name) continue;
138 if(!value || !*value) continue;
140 if(!strcmp(name, "after")) after = (uint32_t)strtoul(value, NULL, 0);
143 buffer_flush(w->response.data);
144 w->response.data->contenttype = CT_APPLICATION_JSON;
145 health_alarm_log2json(host, w->response.data, after);
149 inline int web_client_api_request_single_chart(RRDHOST *host, struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf)) {
153 buffer_flush(w->response.data);
156 char *value = mystrsep(&url, "?&");
157 if(!value || !*value) continue;
159 char *name = mystrsep(&value, "=");
160 if(!name || !*name) continue;
161 if(!value || !*value) continue;
163 // name and value are now the parameters
164 // they are not null and not empty
166 if(!strcmp(name, "chart")) chart = value;
168 /// buffer_sprintf(w->response.data, "Unknown parameter '%s' in request.", name);
173 if(!chart || !*chart) {
174 buffer_sprintf(w->response.data, "No chart id is given at the request.");
178 RRDSET *st = rrdset_find(host, chart);
179 if(!st) st = rrdset_find_byname(host, chart);
181 buffer_strcat(w->response.data, "Chart is not found: ");
182 buffer_strcat_htmlescape(w->response.data, chart);
187 w->response.data->contenttype = CT_APPLICATION_JSON;
188 st->last_accessed_time = now_realtime_sec();
189 callback(st, w->response.data);
196 inline int web_client_api_request_v1_alarm_variables(RRDHOST *host, struct web_client *w, char *url) {
197 return web_client_api_request_single_chart(host, w, url, health_api_v1_chart_variables2json);
200 inline int web_client_api_request_v1_charts(RRDHOST *host, struct web_client *w, char *url) {
203 buffer_flush(w->response.data);
204 w->response.data->contenttype = CT_APPLICATION_JSON;
205 rrd_stats_api_v1_charts(host, w->response.data);
209 inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client *w, char *url) {
210 int format = ALLMETRICS_SHELL;
213 char *value = mystrsep(&url, "?&");
214 if (!value || !*value) continue;
216 char *name = mystrsep(&value, "=");
217 if(!name || !*name) continue;
218 if(!value || !*value) continue;
220 if(!strcmp(name, "format")) {
221 if(!strcmp(value, ALLMETRICS_FORMAT_SHELL))
222 format = ALLMETRICS_SHELL;
223 else if(!strcmp(value, ALLMETRICS_FORMAT_PROMETHEUS))
224 format = ALLMETRICS_PROMETHEUS;
230 buffer_flush(w->response.data);
231 buffer_no_cacheable(w->response.data);
234 case ALLMETRICS_SHELL:
235 w->response.data->contenttype = CT_TEXT_PLAIN;
236 rrd_stats_api_v1_charts_allmetrics_shell(host, w->response.data);
239 case ALLMETRICS_PROMETHEUS:
240 w->response.data->contenttype = CT_PROMETHEUS;
241 rrd_stats_api_v1_charts_allmetrics_prometheus(host, w->response.data);
245 w->response.data->contenttype = CT_TEXT_PLAIN;
246 buffer_strcat(w->response.data, "Which format? Only '" ALLMETRICS_FORMAT_SHELL "' and '" ALLMETRICS_FORMAT_PROMETHEUS "' is currently supported.");
251 inline int web_client_api_request_v1_chart(RRDHOST *host, struct web_client *w, char *url) {
252 return web_client_api_request_single_chart(host, w, url, rrd_stats_api_v1_chart);
255 int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url) {
257 buffer_flush(w->response.data);
259 BUFFER *dimensions = NULL;
261 const char *chart = NULL
265 , *multiply_str = NULL
269 , *label_color = NULL
270 , *value_color = NULL
271 , *refresh_str = NULL
272 , *precision_str = NULL
275 int group = GROUP_AVERAGE;
276 uint32_t options = 0x00000000;
279 char *value = mystrsep(&url, "/?&");
280 if(!value || !*value) continue;
282 char *name = mystrsep(&value, "=");
283 if(!name || !*name) continue;
284 if(!value || !*value) continue;
286 debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value);
288 // name and value are now the parameters
289 // they are not null and not empty
291 if(!strcmp(name, "chart")) chart = value;
292 else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
294 dimensions = buffer_create(100);
296 buffer_strcat(dimensions, "|");
297 buffer_strcat(dimensions, value);
299 else if(!strcmp(name, "after")) after_str = value;
300 else if(!strcmp(name, "before")) before_str = value;
301 else if(!strcmp(name, "points")) points_str = value;
302 else if(!strcmp(name, "group")) {
303 group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE);
305 else if(!strcmp(name, "options")) {
306 options |= web_client_api_request_v1_data_options(value);
308 else if(!strcmp(name, "label")) label = value;
309 else if(!strcmp(name, "units")) units = value;
310 else if(!strcmp(name, "label_color")) label_color = value;
311 else if(!strcmp(name, "value_color")) value_color = value;
312 else if(!strcmp(name, "multiply")) multiply_str = value;
313 else if(!strcmp(name, "divide")) divide_str = value;
314 else if(!strcmp(name, "refresh")) refresh_str = value;
315 else if(!strcmp(name, "precision")) precision_str = value;
316 else if(!strcmp(name, "alarm")) alarm = value;
319 if(!chart || !*chart) {
320 buffer_no_cacheable(w->response.data);
321 buffer_sprintf(w->response.data, "No chart id is given at the request.");
325 RRDSET *st = rrdset_find(host, chart);
326 if(!st) st = rrdset_find_byname(host, chart);
328 buffer_no_cacheable(w->response.data);
329 buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1);
333 st->last_accessed_time = now_realtime_sec();
337 rc = rrdcalc_find(st, alarm);
339 buffer_no_cacheable(w->response.data);
340 buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1);
346 long long multiply = (multiply_str && *multiply_str )?str2l(multiply_str):1;
347 long long divide = (divide_str && *divide_str )?str2l(divide_str):1;
348 long long before = (before_str && *before_str )?str2l(before_str):0;
349 long long after = (after_str && *after_str )?str2l(after_str):-st->update_every;
350 int points = (points_str && *points_str )?str2i(points_str):1;
351 int precision = (precision_str && *precision_str)?str2i(precision_str):-1;
353 if(!multiply) multiply = 1;
354 if(!divide) divide = 1;
357 if(refresh_str && *refresh_str) {
358 if(!strcmp(refresh_str, "auto")) {
359 if(rc) refresh = rc->update_every;
360 else if(options & RRDR_OPTION_NOT_ALIGNED)
361 refresh = st->update_every;
363 refresh = (int)(before - after);
364 if(refresh < 0) refresh = -refresh;
368 refresh = str2i(refresh_str);
369 if(refresh < 0) refresh = -refresh;
375 char *s = (char *)alarm;
377 if(*s == '_') *s = ' ';
382 else if(dimensions) {
383 const char *dim = buffer_tostring(dimensions);
384 if(*dim == '|') dim++;
397 else if(options & RRDR_OPTION_PERCENTAGE)
403 debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', alarm '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'"
407 , (dimensions)?buffer_tostring(dimensions):""
417 buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
418 w->response.data->expires = now_realtime_sec() + refresh;
420 else buffer_no_cacheable(w->response.data);
424 case RRDCALC_STATUS_CRITICAL:
428 case RRDCALC_STATUS_WARNING:
429 value_color = "orange";
432 case RRDCALC_STATUS_CLEAR:
433 value_color = "brightgreen";
436 case RRDCALC_STATUS_UNDEFINED:
437 value_color = "lightgrey";
440 case RRDCALC_STATUS_UNINITIALIZED:
441 value_color = "#000";
445 value_color = "grey";
450 buffer_svg(w->response.data,
452 (isnan(rc->value)||isinf(rc->value)) ? rc->value : rc->value * multiply / divide,
460 time_t latest_timestamp = 0;
461 int value_is_null = 1;
462 calculated_number n = NAN;
465 // if the collected value is too old, don't calculate its value
466 if (rrdset_last_entry_t(st) >= (now_realtime_sec() - (st->update_every * st->gap_when_lost_iterations_above)))
467 ret = rrdset2value_api_v1(st, w->response.data, &n, (dimensions) ? buffer_tostring(dimensions) : NULL
468 , points, after, before, group, options, NULL, &latest_timestamp, &value_is_null);
470 // if the value cannot be calculated, show empty badge
472 buffer_no_cacheable(w->response.data);
477 else if (refresh > 0) {
478 buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh);
479 w->response.data->expires = now_realtime_sec() + refresh;
481 else buffer_no_cacheable(w->response.data);
484 buffer_svg(w->response.data,
486 (value_is_null)?NAN:(n * multiply / divide),
494 buffer_free(dimensions);
498 // returns the HTTP code
499 inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, char *url) {
500 debug(D_WEB_CLIENT, "%llu: API v1 data with URL '%s'", w->id, url);
503 BUFFER *dimensions = NULL;
505 buffer_flush(w->response.data);
507 char *google_version = "0.6",
510 *google_out = "json",
511 *responseHandler = NULL,
514 time_t last_timestamp_in_data = 0, google_timestamp = 0;
519 , *points_str = NULL;
521 int group = GROUP_AVERAGE;
522 uint32_t format = DATASOURCE_JSON;
523 uint32_t options = 0x00000000;
526 char *value = mystrsep(&url, "?&");
527 if(!value || !*value) continue;
529 char *name = mystrsep(&value, "=");
530 if(!name || !*name) continue;
531 if(!value || !*value) continue;
533 debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value);
535 // name and value are now the parameters
536 // they are not null and not empty
538 if(!strcmp(name, "chart")) chart = value;
539 else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
540 if(!dimensions) dimensions = buffer_create(100);
541 buffer_strcat(dimensions, "|");
542 buffer_strcat(dimensions, value);
544 else if(!strcmp(name, "after")) after_str = value;
545 else if(!strcmp(name, "before")) before_str = value;
546 else if(!strcmp(name, "points")) points_str = value;
547 else if(!strcmp(name, "group")) {
548 group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE);
550 else if(!strcmp(name, "format")) {
551 format = web_client_api_request_v1_data_format(value);
553 else if(!strcmp(name, "options")) {
554 options |= web_client_api_request_v1_data_options(value);
556 else if(!strcmp(name, "callback")) {
557 responseHandler = value;
559 else if(!strcmp(name, "filename")) {
562 else if(!strcmp(name, "tqx")) {
563 // parse Google Visualization API options
564 // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source
565 char *tqx_name, *tqx_value;
568 tqx_value = mystrsep(&value, ";");
569 if(!tqx_value || !*tqx_value) continue;
571 tqx_name = mystrsep(&tqx_value, ":");
572 if(!tqx_name || !*tqx_name) continue;
573 if(!tqx_value || !*tqx_value) continue;
575 if(!strcmp(tqx_name, "version"))
576 google_version = tqx_value;
577 else if(!strcmp(tqx_name, "reqId"))
578 google_reqId = tqx_value;
579 else if(!strcmp(tqx_name, "sig")) {
580 google_sig = tqx_value;
581 google_timestamp = strtoul(google_sig, NULL, 0);
583 else if(!strcmp(tqx_name, "out")) {
584 google_out = tqx_value;
585 format = web_client_api_request_v1_data_google_format(google_out);
587 else if(!strcmp(tqx_name, "responseHandler"))
588 responseHandler = tqx_value;
589 else if(!strcmp(tqx_name, "outFileName"))
590 outFileName = tqx_value;
595 if(!chart || !*chart) {
596 buffer_sprintf(w->response.data, "No chart id is given at the request.");
600 RRDSET *st = rrdset_find(host, chart);
601 if(!st) st = rrdset_find_byname(host, chart);
603 buffer_strcat(w->response.data, "Chart is not found: ");
604 buffer_strcat_htmlescape(w->response.data, chart);
608 st->last_accessed_time = now_realtime_sec();
610 long long before = (before_str && *before_str)?str2l(before_str):0;
611 long long after = (after_str && *after_str) ?str2l(after_str):0;
612 int points = (points_str && *points_str)?str2i(points_str):0;
614 debug(D_WEB_CLIENT, "%llu: API command 'data' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', format '%u', options '0x%08x'"
617 , (dimensions)?buffer_tostring(dimensions):""
626 if(outFileName && *outFileName) {
627 buffer_sprintf(w->response.header, "Content-Disposition: attachment; filename=\"%s\"\r\n", outFileName);
628 debug(D_WEB_CLIENT, "%llu: generating outfilename header: '%s'", w->id, outFileName);
631 if(format == DATASOURCE_DATATABLE_JSONP) {
632 if(responseHandler == NULL)
633 responseHandler = "google.visualization.Query.setResponse";
635 debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSON/JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
636 w->id, google_version, google_reqId, google_sig, google_out, responseHandler, outFileName
639 buffer_sprintf(w->response.data,
640 "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:",
641 responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
643 else if(format == DATASOURCE_JSONP) {
644 if(responseHandler == NULL)
645 responseHandler = "callback";
647 buffer_strcat(w->response.data, responseHandler);
648 buffer_strcat(w->response.data, "(");
651 ret = rrdset2anything_api_v1(st, w->response.data, dimensions, format, points, after, before, group, options
652 , &last_timestamp_in_data);
654 if(format == DATASOURCE_DATATABLE_JSONP) {
655 if(google_timestamp < last_timestamp_in_data)
656 buffer_strcat(w->response.data, "});");
659 // the client already has the latest data
660 buffer_flush(w->response.data);
661 buffer_sprintf(w->response.data,
662 "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
663 responseHandler, google_version, google_reqId);
666 else if(format == DATASOURCE_JSONP)
667 buffer_strcat(w->response.data, ");");
670 buffer_free(dimensions);
674 inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *w, char *url) {
675 static uint32_t hash_action = 0, hash_access = 0, hash_hello = 0, hash_delete = 0, hash_search = 0,
676 hash_switch = 0, hash_machine = 0, hash_url = 0, hash_name = 0, hash_delete_url = 0, hash_for = 0,
677 hash_to = 0 /*, hash_redirects = 0 */;
679 if(unlikely(!hash_action)) {
680 hash_action = simple_hash("action");
681 hash_access = simple_hash("access");
682 hash_hello = simple_hash("hello");
683 hash_delete = simple_hash("delete");
684 hash_search = simple_hash("search");
685 hash_switch = simple_hash("switch");
686 hash_machine = simple_hash("machine");
687 hash_url = simple_hash("url");
688 hash_name = simple_hash("name");
689 hash_delete_url = simple_hash("delete_url");
690 hash_for = simple_hash("for");
691 hash_to = simple_hash("to");
693 hash_redirects = simple_hash("redirects");
697 char person_guid[GUID_LEN + 1] = "";
699 debug(D_WEB_CLIENT, "%llu: API v1 registry with URL '%s'", w->id, url);
702 // The browser may send multiple cookies with our id
704 char *cookie = strstr(w->response.data->buffer, NETDATA_REGISTRY_COOKIE_NAME "=");
706 strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME)], 36);
709 char *machine_guid = NULL,
712 *search_machine_guid = NULL,
714 *to_person_guid = NULL;
720 char *value = mystrsep(&url, "?&");
721 if (!value || !*value) continue;
723 char *name = mystrsep(&value, "=");
724 if (!name || !*name) continue;
725 if (!value || !*value) continue;
727 debug(D_WEB_CLIENT, "%llu: API v1 registry query param '%s' with value '%s'", w->id, name, value);
729 uint32_t hash = simple_hash(name);
731 if(hash == hash_action && !strcmp(name, "action")) {
732 uint32_t vhash = simple_hash(value);
734 if(vhash == hash_access && !strcmp(value, "access")) action = 'A';
735 else if(vhash == hash_hello && !strcmp(value, "hello")) action = 'H';
736 else if(vhash == hash_delete && !strcmp(value, "delete")) action = 'D';
737 else if(vhash == hash_search && !strcmp(value, "search")) action = 'S';
738 else if(vhash == hash_switch && !strcmp(value, "switch")) action = 'W';
739 #ifdef NETDATA_INTERNAL_CHECKS
740 else error("unknown registry action '%s'", value);
741 #endif /* NETDATA_INTERNAL_CHECKS */
744 else if(hash == hash_redirects && !strcmp(name, "redirects"))
745 redirects = atoi(value);
747 else if(hash == hash_machine && !strcmp(name, "machine"))
748 machine_guid = value;
750 else if(hash == hash_url && !strcmp(name, "url"))
753 else if(action == 'A') {
754 if(hash == hash_name && !strcmp(name, "name"))
757 else if(action == 'D') {
758 if(hash == hash_delete_url && !strcmp(name, "delete_url"))
761 else if(action == 'S') {
762 if(hash == hash_for && !strcmp(name, "for"))
763 search_machine_guid = value;
765 else if(action == 'W') {
766 if(hash == hash_to && !strcmp(name, "to"))
767 to_person_guid = value;
769 #ifdef NETDATA_INTERNAL_CHECKS
770 else error("unused registry URL parameter '%s' with value '%s'", name, value);
771 #endif /* NETDATA_INTERNAL_CHECKS */
774 if(respect_web_browser_do_not_track_policy && w->donottrack) {
775 buffer_flush(w->response.data);
776 buffer_sprintf(w->response.data, "Your web browser is sending 'DNT: 1' (Do Not Track). The registry requires persistent cookies on your browser to work.");
780 if(action == 'A' && (!machine_guid || !machine_url || !url_name)) {
781 error("Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')",
782 machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", url_name?url_name:"UNSET");
783 buffer_flush(w->response.data);
784 buffer_strcat(w->response.data, "Invalid registry Access request.");
787 else if(action == 'D' && (!machine_guid || !machine_url || !delete_url)) {
788 error("Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')",
789 machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET");
790 buffer_flush(w->response.data);
791 buffer_strcat(w->response.data, "Invalid registry Delete request.");
794 else if(action == 'S' && (!machine_guid || !machine_url || !search_machine_guid)) {
795 error("Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')",
796 machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET");
797 buffer_flush(w->response.data);
798 buffer_strcat(w->response.data, "Invalid registry Search request.");
801 else if(action == 'W' && (!machine_guid || !machine_url || !to_person_guid)) {
802 error("Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')",
803 machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET");
804 buffer_flush(w->response.data);
805 buffer_strcat(w->response.data, "Invalid registry Switch request.");
811 w->tracking_required = 1;
812 return registry_request_access_json(host, w, person_guid, machine_guid, machine_url, url_name, now_realtime_sec());
815 w->tracking_required = 1;
816 return registry_request_delete_json(host, w, person_guid, machine_guid, machine_url, delete_url, now_realtime_sec());
819 w->tracking_required = 1;
820 return registry_request_search_json(host, w, person_guid, machine_guid, machine_url, search_machine_guid, now_realtime_sec());
823 w->tracking_required = 1;
824 return registry_request_switch_json(host, w, person_guid, machine_guid, machine_url, to_person_guid, now_realtime_sec());
827 return registry_request_hello_json(host, w);
830 buffer_flush(w->response.data);
831 buffer_strcat(w->response.data, "Invalid registry request - you need to set an action: hello, access, delete, search");
836 inline int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char *url) {
837 static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0, hash_alarms = 0, hash_alarm_log = 0, hash_alarm_variables = 0, hash_raw = 0;
839 if(unlikely(hash_data == 0)) {
840 hash_data = simple_hash("data");
841 hash_chart = simple_hash("chart");
842 hash_charts = simple_hash("charts");
843 hash_registry = simple_hash("registry");
844 hash_badge = simple_hash("badge.svg");
845 hash_alarms = simple_hash("alarms");
846 hash_alarm_log = simple_hash("alarm_log");
847 hash_alarm_variables = simple_hash("alarm_variables");
848 hash_raw = simple_hash("allmetrics");
852 char *tok = mystrsep(&url, "/?&");
854 debug(D_WEB_CLIENT, "%llu: Searching for API v1 command '%s'.", w->id, tok);
855 uint32_t hash = simple_hash(tok);
857 if(hash == hash_data && !strcmp(tok, "data"))
858 return web_client_api_request_v1_data(host, w, url);
860 else if(hash == hash_chart && !strcmp(tok, "chart"))
861 return web_client_api_request_v1_chart(host, w, url);
863 else if(hash == hash_charts && !strcmp(tok, "charts"))
864 return web_client_api_request_v1_charts(host, w, url);
866 else if(hash == hash_registry && !strcmp(tok, "registry"))
867 return web_client_api_request_v1_registry(host, w, url);
869 else if(hash == hash_badge && !strcmp(tok, "badge.svg"))
870 return web_client_api_request_v1_badge(host, w, url);
872 else if(hash == hash_alarms && !strcmp(tok, "alarms"))
873 return web_client_api_request_v1_alarms(host, w, url);
875 else if(hash == hash_alarm_log && !strcmp(tok, "alarm_log"))
876 return web_client_api_request_v1_alarm_log(host, w, url);
878 else if(hash == hash_alarm_variables && !strcmp(tok, "alarm_variables"))
879 return web_client_api_request_v1_alarm_variables(host, w, url);
881 else if(hash == hash_raw && !strcmp(tok, "allmetrics"))
882 return web_client_api_request_v1_allmetrics(host, w, url);
885 buffer_flush(w->response.data);
886 buffer_strcat(w->response.data, "Unsupported v1 API command: ");
887 buffer_strcat_htmlescape(w->response.data, tok);
892 buffer_flush(w->response.data);
893 buffer_sprintf(w->response.data, "Which API v1 command?");