Revert "New URL parser (#6070)"
This reverts commit 58b7d95a7ec9c576f8a06bbab07f755846b5349a. --- As agreed with @thiago and @cakrit we revert URL parser changes, to buy the time on a more detailed investigation ---
Pavlos Emm. Katsoulakis committed
Jun 7, 2019 at 18:14 UTC
0fca36fd596e49395141561bc42c168a240f51b8
10 files changed
+444
-1056
libnetdata/inlined.h
-28
@@ -31,19 +31,6 @@ static inline uint32_t simple_hash(const char *name) {
31
return hval;
32
}
33
34
-static inline uint32_t simple_nhash(const char *name,size_t len) {
35
- unsigned char *s = (unsigned char *) name;
36
- size_t i;
37
- uint32_t hval = 0x811c9dc5;
38
- i = 0;
39
- do {
40
- hval *= 16777619;
41
- hval ^= (uint32_t) *s++;
42
- } while (++i < len);
43
-
44
- return hval;
45
-}
46
-
34
static inline uint32_t simple_uhash(const char *name) {
35
unsigned char *s = (unsigned char *) name;
36
uint32_t hval = 0x811c9dc5, c;
@@ -55,21 +42,6 @@ static inline uint32_t simple_uhash(const char *name) {
42
return hval;
43
}
44
58
-static inline uint32_t simple_nuhash(const char *name,size_t len) {
59
- unsigned char *s = (unsigned char *) name;
60
- size_t i;
61
- uint32_t hval = 0x811c9dc5, c;
62
-
63
- i = 0;
64
- do {
65
- c = *s++;
66
- if (unlikely(c >= 'A' && c <= 'Z')) c += 'a' - 'A';
67
- hval *= 16777619;
68
- hval ^= c;
69
- } while ( ++i < len);
70
- return hval;
71
-}
72
-
45
static inline int simple_hash_strcmp(const char *name, const char *b, uint32_t *hash) {
46
unsigned char *s = (unsigned char *) name;
47
uint32_t hval = 0x811c9dc5;
libnetdata/url/url.c
-85
@@ -79,88 +79,3 @@ char *url_decode_r(char *to, char *url, size_t size) {
79
80
return to;
81
}
82
-
83
-inline HTTP_VALIDATION url_is_request_complete(char *begin,char *end,size_t length) {
84
- if ( begin == end) {
85
- return HTTP_VALIDATION_INCOMPLETE;
86
- }
87
-
88
- if ( length > 3 ) {
89
- begin = end - 4;
90
- }
91
-
92
- uint32_t counter = 0;
93
- do {
94
- if (*begin == '\r') {
95
- begin++;
96
- if ( begin == end )
97
- {
98
- break;
99
- }
100
-
101
- if (*begin == '\n')
102
- {
103
- counter++;
104
- }
105
- } else if (*begin == '\n') {
106
- begin++;
107
- counter++;
108
- }
109
-
110
- if ( counter == 2) {
111
- break;
112
- }
113
- }
114
- while (begin != end);
115
-
116
- return (counter == 2)?HTTP_VALIDATION_OK:HTTP_VALIDATION_INCOMPLETE;
117
-}
118
-
119
-inline char *url_find_protocol(char *s) {
120
- while(*s) {
121
- // find the next space
122
- while (*s && *s != ' ') s++;
123
-
124
- // is it SPACE + "HTTP/" ?
125
- if(*s && !strncmp(s, " HTTP/", 6)) break;
126
- else s++;
127
- }
128
-
129
- return s;
130
-}
131
-
132
-int url_parse_query_string(struct web_fields *names,struct web_fields *values,char *moveme,char *divisor) {
133
- uint32_t i = 0;
134
- uint32_t max = WEB_FIELDS_MAX;
135
-
136
- do {
137
- if ( i == max) {
138
- error("We are exceeding the maximum number of elements possible(%u) in this query string(%s)",max,moveme);
139
- break;
140
- }
141
- if (divisor) {
142
- names[i].body = moveme;
143
- names[i].length = divisor - moveme;//= - begin
144
-
145
- moveme = ++divisor; //value
146
- values[i].body = moveme;
147
-
148
- (void)divisor;
149
- divisor = strchr(moveme,'&'); //end of value
150
- if (divisor) {
151
- values[i].length = (size_t )(divisor - moveme);
152
- } else{
153
- values[i].length = strlen(moveme);
154
- break;
155
- }
156
-
157
- moveme = divisor;
158
- divisor = strchr(++moveme,'='); //end of value
159
- i++;
160
- } else {
161
- break;
162
- }
163
- } while (moveme);
164
-
165
- return ++i;
166
-}
libnetdata/url/url.h
-22
@@ -25,26 +25,4 @@ extern char *url_decode(char *str);
25
26
extern char *url_decode_r(char *to, char *url, size_t size);
27
28
-#define WEB_FIELDS_MAX 200
29
-struct web_fields{
30
- char *body;
31
- size_t length;
32
-};
33
-// http_request_validate()
34
-// returns:
35
-// = 0 : all good, process the request
36
-// > 0 : request is not supported
37
-// < 0 : request is incomplete - wait for more data
38
-
39
-typedef enum {
40
- HTTP_VALIDATION_OK,
41
- HTTP_VALIDATION_NOT_SUPPORTED,
42
- HTTP_VALIDATION_INCOMPLETE,
43
- HTTP_VALIDATION_REDIRECT
44
-} HTTP_VALIDATION;
45
-
46
-extern HTTP_VALIDATION url_is_request_complete(char *begin,char *end,size_t length);
47
-extern char *url_find_protocol(char *s);
48
-extern int url_parse_query_string(struct web_fields *names,struct web_fields *values,char *moveme,char *divisor);
49
-
28
#endif /* NETDATA_URL_H */
tests/urls/requests.sh
deleted
-207
@@ -1,207 +0,0 @@
1
-#!/bin/bash
2
-# SPDX-License-Identifier: GPL-3.0-or-later
3
-
4
-################################################################################################
5
-#### ####
6
-#### GLOBAL VARIABLES ####
7
-#### ####
8
-################################################################################################
9
-
10
-NETDATA_VARLIB_DIR="@varlibdir_POST@"
11
-
12
-#CT=`date +'%s%N' |cut -b1-13`
13
-# The current time
14
-CT=`date +'%s'`
15
-
16
-# The previous time
17
-PT=$(( $CT - 100))
18
-
19
-# The curl options used to do download
20
-CURLOPTS="-v --create-dirs -o"
21
-
22
-# The output directory where we will store the results and error
23
-OUTDIR="tests"
24
-
25
-################################################################################################
26
-#### ####
27
-#### FUNCTIONS ####
28
-#### ####
29
-################################################################################################
30
-
31
-# Print error message and close script
32
-netdata_print_error(){
33
- echo "Closing due error \"$1\" code \"$2\""
34
- exit 1
35
-}
36
-
37
-# Print the header message of the function
38
-netdata_print_header() {
39
- echo "$1"
40
-}
41
-
42
-# Create the main directory where the results will be stored
43
-netdata_create_directory() {
44
- netdata_print_header "Creating directory $1"
45
- if [ ! -d $1 ]; then
46
- mkdir $1
47
- if [ $? -ne 0 ]; then
48
- netdata_print_error "Cannot create directory" $?
49
- fi
50
- else
51
- echo "Working with directory $OUTDIR"
52
- fi
53
-}
54
-
55
-netdata_test_download(){
56
- grep "HTTP/1.1 200 OK" $1 2>/dev/null 1>/dev/null
57
- if [ $? -ne 0 ]; then
58
- netdata_print_error "Cannot do download of the page $2" $?
59
- fi
60
-}
61
-
62
-# Download information from Netdata
63
-netdata_download_various() {
64
- netdata_print_header "Getting $2"
65
- curl $CURLOPTS $OUTDIR/$3.out "$1/$2" 2> $OUTDIR/$3.err
66
- netdata_test_download $OUTDIR/$3.err "$1/$2"
67
-}
68
-
69
-# Download charts from Netdata
70
-netdata_download_charts() {
71
- curl $CURLOPTS $OUTDIR/charts.out "$1/$2/charts" 2> $OUTDIR/charts.err
72
- netdata_test_download $OUTDIR/charts.err "$1/$2/charts"
73
-
74
- #Rewrite the next
75
- cat tests/charts.out | grep -w "id"| cut -d: -f2 | grep "\"," | sed s/,//g | sort
76
-}
77
-
78
-#Test options for a specific chart
79
-netdata_download_chart() {
80
- NAME=`echo $3| sed s/\"//g`
81
- netdata_print_header "Getting data for $NAME using $4"
82
-
83
- LDIR=$OUTDIR"/"$4
84
-
85
- LURL=$1/$2=$NAME
86
-
87
- NAME=$NAME"_$4"
88
-
89
- curl $CURLOPTS $LDIR/$NAME.out "$LURL" 2> $LDIR/$NAME.err
90
- netdata_test_download $LDIR/$NAME.err $LURL
91
-
92
- UFILES=( "points" "before" "after" )
93
- COUNTER=0
94
- for OPT in "&points=100" "&before=$PT" "&after=$CT" ;
95
- do
96
- LURL="$LURL$OPT"
97
- LFILE=$NAME"_${UFILES[$COUNTER]}";
98
-
99
- curl $CURLOPTS "$LDIR/$LFILE.out" "$LURL" 2> "$LDIR/$LFILE.err"
100
- netdata_test_download $LDIR/$LFILE.err $LURL
101
-
102
- COUNTER=$(($COUNTER + 1))
103
- done
104
-
105
- LURL="$LURL&group="
106
- for OPT in "min" "max" "sum" "median" "stddev" "cv" "ses" "des" "incremental_sum" "average";
107
- do
108
- TURL=$LURL$OPT
109
- TFILE=$NAME"_$OPT";
110
- curl $CURLOPTS "$LDIR/$TFILE.out" "$TURL" 2> "$LDIR/$TFILE.err"
111
- netdata_test_download $LDIR/$TFILE.err $TURL
112
- for MORE in "jsonp" "json" "ssv" "csv" "datatable" "datasource" "tsv" "ssvcomma" "html" "array";
113
- do
114
- TURL=$TURL"&format="$MORE
115
- TFILE=$NAME"_$OPT""_$MORE";
116
- curl $CURLOPTS "$LDIR/$TFILE.out" "$TURL" 2> "$LDIR/$TFILE.err"
117
- netdata_test_download $LDIR/$TFILE.err $TURL
118
- done
119
-
120
- done
121
-
122
- LURL="$LURL$OPT>ime=60"
123
- NFILE=$NAME"_gtime"
124
- curl $CURLOPTS "$LDIR/$NFILE.out" "$TURL" 2> "$LDIR/$NFILE.err"
125
- netdata_test_download $LDIR/$NFILE.err $LURL
126
-
127
- LURL="$LURL$OPT&options=percentage"
128
- NFILE=$NAME"_percentage"
129
- curl $CURLOPTS "$LDIR/$NFILE.out" "$TURL" 2> "$LDIR/$NFILE.err"
130
- netdata_test_download $LDIR/$NFILE.err $LURL
131
-
132
- LURL="$LURL$OPT&options=percentage"
133
- NFILE=$NAME"_percentage"
134
- curl $CURLOPTS "$LDIR/$NFILE.out" "$TURL" 2> "$LDIR/$NFILE.err"
135
- netdata_test_download $LDIR/$NFILE.err $LURL
136
-
137
- LURL="$LURL$OPT&dimensions=system%7Cnice"
138
- NFILE=$NAME"_dimension"
139
- curl $CURLOPTS "$LDIR/$NFILE.out" "$TURL" 2> "$LDIR/$NFILE.err"
140
- netdata_test_download $LDIR/$NFILE.err $LURL
141
-
142
-}
143
-
144
-# Download information from Netdata
145
-netdata_download_allmetrics() {
146
- netdata_print_header "Getting All metrics"
147
- curl $CURLOPTS $OUTDIR/allmetrics.out "$1/$2" 2> $OUTDIR/allmetrics.err
148
- netdata_test_download $OUTDIR/allmetrics.err "$1/$2"
149
-}
150
-
151
-# Download charts from Netdata
152
-
153
-################################################################################################
154
-#### ####
155
-#### MAIN ROUTINE ####
156
-#### ####
157
-################################################################################################
158
-MURL="http://127.0.0.1:19999"
159
-
160
-wget --execute="robots = off" --mirror --convert-links --no-parent http://127.0.0.1:19999
161
-
162
-netdata_create_directory $OUTDIR
163
-
164
-netdata_download_various $MURL "netdata.conf" "netdata.conf"
165
-
166
-netdata_download_various $MURL "api/v1/info" "info"
167
-
168
-netdata_download_various $MURL "api/v1/registry?action=hello" "action"
169
-
170
-netdata_print_header "Getting all the netdata charts"
171
-CHARTS=$( netdata_download_charts "http://127.0.0.1:19999" "api/v1" )
172
-
173
-netdata_download_various $MURL "api/v1/allmetrics?format=json" "allmetrics"
174
-
175
-netdata_download_various $MURL "api/v1/alarms?all" "alarms_all"
176
-
177
-netdata_download_various $MURL "api/v1/alarms?active" "alarms_active"
178
-
179
-netdata_download_various $MURL "api/v1/alarm_log?after&_=$PT" "alarm_log"
180
-
181
-for I in $CHARTS ; do
182
- NAME=`echo $I| sed s/\"//g`
183
- netdata_download_various $MURL "api/v1/alarm_variables?chart=$NAME" "alarm_variables_$NAME"
184
-done
185
-
186
-netdata_create_directory "$OUTDIR/data"
187
-for I in $CHARTS ; do
188
- netdata_download_chart $MURL "api/v1/data?chart" $I "data"
189
-done
190
-
191
-netdata_create_directory "$OUTDIR/badge.svg"
192
-for I in $CHARTS ; do
193
- netdata_download_chart $MURL "api/v1/badge.svg?chart" $I "badge.svg"
194
-done
195
-
196
-if [ -f "${NETDATA_VARLIB_DIR}/netdata.api.key" ] ;then
197
- read -r CORRECT_TOKEN < "${NETDATA_VARLIB_DIR}/netdata.api.key"
198
-else
199
- echo "${NETDATA_VARLIB_DIR}/netdata.api.key not found"
200
- echo "Token not found."
201
- exit 2
202
-fi
203
-curl -H "X-Auth-Token: $TOKEN" "http://127.0.0.1:19999/api/v1/manage/health?cmd=RESET"
204
-
205
-echo "ALL the URLS got 200 as answer!"
206
-
207
-exit 0
web/api/badges/web_buffer_svg.c
+40
-57
@@ -889,7 +889,6 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
889
}
890
891
int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url) {
892
- (void)url;
892
int ret = 400;
893
buffer_flush(w->response.data);
894
@@ -913,54 +912,46 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u
912
int group = RRDR_GROUPING_AVERAGE;
913
uint32_t options = 0x00000000;
914
916
- uint32_t i = 0;
917
- uint32_t end = w->total_params;
918
- char save[WEB_FIELDS_MAX];
919
- char *value;
920
- size_t lvalue;
921
- if(end) {
922
- do {
923
- value = w->param_values[i].body;
924
- lvalue = w->param_values[i].length;
925
- save[i] = value[lvalue];
926
- value[lvalue] = 0x00;
927
-
928
- char *name = w->param_name[i].body;
929
- size_t lname = w->param_name[i].length;
930
-
931
- debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value);
932
-
933
- // name and value are now the parameters
934
- // they are not null and not empty
935
- if(!strncmp(name, "chart",lname)) chart = value;
936
- else if(!strncmp(name, "dimension",lname) || !strncmp(name, "dim",lname) || !strncmp(name, "dimensions",lname) || !strncmp(name, "dims",lname)) {
937
- if(!dimensions)
938
- dimensions = buffer_create(100);
939
-
940
- buffer_strcat(dimensions, "|");
941
- buffer_strcat(dimensions, value);
942
- }
943
- else if(!strncmp(name, "after",lname)) after_str = value;
944
- else if(!strncmp(name, "before",lname)) before_str = value;
945
- else if(!strncmp(name, "points",lname)) points_str = value;
946
- else if(!strncmp(name, "group",lname)) {
947
- group = web_client_api_request_v1_data_group(value, RRDR_GROUPING_AVERAGE);
948
- }
949
- else if(!strncmp(name, "options",lname)) {
950
- options |= web_client_api_request_v1_data_options(value);
951
- }
952
- else if(!strncmp(name, "label",lname)) label = value;
953
- else if(!strncmp(name, "units",lname)) units = value;
954
- else if(!strncmp(name, "label_color",lname)) label_color = value;
955
- else if(!strncmp(name, "value_color",lname)) value_color = value;
956
- else if(!strncmp(name, "multiply",lname)) multiply_str = value;
957
- else if(!strncmp(name, "divide",lname)) divide_str = value;
958
- else if(!strncmp(name, "refresh",lname)) refresh_str = value;
959
- else if(!strncmp(name, "precision",lname)) precision_str = value;
960
- else if(!strncmp(name, "scale",lname)) scale_str = value;
961
- else if(!strncmp(name, "alarm",lname)) alarm = value;
962
-
963
- } while (++i < end );
915
+ while(url) {
916
+ char *value = mystrsep(&url, "&");
917
+ if(!value || !*value) continue;
918
+
919
+ char *name = mystrsep(&value, "=");
920
+ if(!name || !*name) continue;
921
+ if(!value || !*value) continue;
922
+
923
+ debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value);
924
+
925
+ // name and value are now the parameters
926
+ // they are not null and not empty
927
+
928
+ if(!strcmp(name, "chart")) chart = value;
929
+ else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
930
+ if(!dimensions)
931
+ dimensions = buffer_create(100);
932
+
933
+ buffer_strcat(dimensions, "|");
934
+ buffer_strcat(dimensions, value);
935
+ }
936
+ else if(!strcmp(name, "after")) after_str = value;
937
+ else if(!strcmp(name, "before")) before_str = value;
938
+ else if(!strcmp(name, "points")) points_str = value;
939
+ else if(!strcmp(name, "group")) {
940
+ group = web_client_api_request_v1_data_group(value, RRDR_GROUPING_AVERAGE);
941
+ }
942
+ else if(!strcmp(name, "options")) {
943
+ options |= web_client_api_request_v1_data_options(value);
944
+ }
945
+ else if(!strcmp(name, "label")) label = value;
946
+ else if(!strcmp(name, "units")) units = value;
947
+ else if(!strcmp(name, "label_color")) label_color = value;
948
+ else if(!strcmp(name, "value_color")) value_color = value;
949
+ else if(!strcmp(name, "multiply")) multiply_str = value;
950
+ else if(!strcmp(name, "divide")) divide_str = value;
951
+ else if(!strcmp(name, "refresh")) refresh_str = value;
952
+ else if(!strcmp(name, "precision")) precision_str = value;
953
+ else if(!strcmp(name, "scale")) scale_str = value;
954
+ else if(!strcmp(name, "alarm")) alarm = value;
955
}
956
957
if(!chart || !*chart) {
@@ -1146,14 +1137,6 @@ int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *u
1137
}
1138
1139
cleanup:
1149
- if(end) {
1150
- i = 0;
1151
- do {
1152
- value = w->param_values[i].body;
1153
- lvalue = w->param_values[i].length;
1154
- value[lvalue] = save[i];
1155
- } while(++i < end);
1156
- }
1140
buffer_free(dimensions);
1141
return ret;
1142
}
web/api/exporters/allmetrics.c
+38
-41
@@ -18,57 +18,54 @@ struct prometheus_output_options {
18
};
19
20
inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client *w, char *url) {
21
- (void)url;
21
int format = ALLMETRICS_SHELL;
22
const char *prometheus_server = w->client_ip;
23
uint32_t prometheus_backend_options = global_backend_options;
24
PROMETHEUS_OUTPUT_OPTIONS prometheus_output_options = PROMETHEUS_OUTPUT_TIMESTAMPS | ((global_backend_options & BACKEND_OPTION_SEND_NAMES)?PROMETHEUS_OUTPUT_NAMES:0);
25
const char *prometheus_prefix = global_backend_prefix;
26
28
- uint32_t end = w->total_params;
29
- if (end) {
30
- uint32_t i = 0;
31
- do {
32
- char *name = w->param_name[i].body;
33
- size_t lname = w->param_name[i].length;
34
- char *value = w->param_values[i].body;
35
- size_t lvalue = w->param_values[i].length;
27
+ while(url) {
28
+ char *value = mystrsep(&url, "&");
29
+ if (!value || !*value) continue;
30
37
- if(!strncmp(name, "format",lname)) {
38
- if(!strncmp(value, ALLMETRICS_FORMAT_SHELL,lvalue))
39
- format = ALLMETRICS_SHELL;
40
- else if(!strncmp(value, ALLMETRICS_FORMAT_PROMETHEUS,lvalue))
41
- format = ALLMETRICS_PROMETHEUS;
42
- else if(!strncmp(value, ALLMETRICS_FORMAT_PROMETHEUS_ALL_HOSTS,lvalue))
43
- format = ALLMETRICS_PROMETHEUS_ALL_HOSTS;
44
- else if(!strncmp(value, ALLMETRICS_FORMAT_JSON,lvalue))
45
- format = ALLMETRICS_JSON;
46
- else
47
- format = 0;
48
- }
49
- else if(!strncmp(name, "server",lname)) {
50
- prometheus_server = value;
51
- }
52
- else if(!strncmp(name, "prefix",lname)) {
53
- prometheus_prefix = value;
54
- }
55
- else if(!strncmp(name, "data",lname) || !strncmp(name, "source",lname) || !strncmp(name, "data source",lname) || !strncmp(name, "data-source",lname) || !strncmp(name, "data_source",lname) || !strncmp(name, "datasource",lname)) {
56
- prometheus_backend_options = backend_parse_data_source(value, prometheus_backend_options);
57
- }
58
- else {
59
- int i;
60
- for(i = 0; prometheus_output_flags_root[i].name ; i++) {
61
- if(!strncmp(name, prometheus_output_flags_root[i].name,lname)) {
62
- if(!strncmp(value, "yes",lvalue) || !strncmp(value, "1",lvalue) || !strncmp(value, "true",lvalue))
63
- prometheus_output_options |= prometheus_output_flags_root[i].flag;
64
- else
65
- prometheus_output_options &= ~prometheus_output_flags_root[i].flag;
31
+ char *name = mystrsep(&value, "=");
32
+ if(!name || !*name) continue;
33
+ if(!value || !*value) continue;
34
+
35
+ if(!strcmp(name, "format")) {
36
+ if(!strcmp(value, ALLMETRICS_FORMAT_SHELL))
37
+ format = ALLMETRICS_SHELL;
38
+ else if(!strcmp(value, ALLMETRICS_FORMAT_PROMETHEUS))
39
+ format = ALLMETRICS_PROMETHEUS;
40
+ else if(!strcmp(value, ALLMETRICS_FORMAT_PROMETHEUS_ALL_HOSTS))
41
+ format = ALLMETRICS_PROMETHEUS_ALL_HOSTS;
42
+ else if(!strcmp(value, ALLMETRICS_FORMAT_JSON))
43
+ format = ALLMETRICS_JSON;
44
+ else
45
+ format = 0;
46
+ }
47
+ else if(!strcmp(name, "server")) {
48
+ prometheus_server = value;
49
+ }
50
+ else if(!strcmp(name, "prefix")) {
51
+ prometheus_prefix = value;
52
+ }
53
+ else if(!strcmp(name, "data") || !strcmp(name, "source") || !strcmp(name, "data source") || !strcmp(name, "data-source") || !strcmp(name, "data_source") || !strcmp(name, "datasource")) {
54
+ prometheus_backend_options = backend_parse_data_source(value, prometheus_backend_options);
55
+ }
56
+ else {
57
+ int i;
58
+ for(i = 0; prometheus_output_flags_root[i].name ; i++) {
59
+ if(!strcmp(name, prometheus_output_flags_root[i].name)) {
60
+ if(!strcmp(value, "yes") || !strcmp(value, "1") || !strcmp(value, "true"))
61
+ prometheus_output_options |= prometheus_output_flags_root[i].flag;
62
+ else
63
+ prometheus_output_options &= ~prometheus_output_flags_root[i].flag;
64
67
- break;
68
- }
65
+ break;
66
}
67
}
71
- } while( ++i < end);
68
+ }
69
}
70
71
buffer_flush(w->response.data);
web/api/health/health_cmdapi.c
+68
-77
@@ -31,10 +31,13 @@ void free_silencers(SILENCER *t) {
31
return;
32
}
33
34
+
35
+
36
int web_client_api_request_v1_mgmt_health(RRDHOST *host, struct web_client *w, char *url) {
37
int ret = 400;
38
(void) host;
37
- (void)url;
39
+
40
+
41
42
BUFFER *wb = w->response.data;
43
buffer_flush(wb);
@@ -70,86 +73,75 @@ int web_client_api_request_v1_mgmt_health(RRDHOST *host, struct web_client *w, c
73
buffer_strcat(wb, HEALTH_CMDAPI_MSG_AUTHERROR);
74
ret = 403;
75
} else {
73
- uint32_t end = w->total_params;
74
- if (end) {
75
- uint32_t i = 0;
76
- do {
77
- char *key = w->param_name[i].body;
78
- size_t lkey = w->param_name[i].length;
79
- char ksave = key[lkey];
80
- key[lkey] = 0x00;
81
-
82
- char *value = w->param_values[i].body;
83
- size_t lvalue = w->param_values[i].length;
84
- char vsave = value[lvalue];
85
- value[lvalue] = 0x00;
86
-
87
- debug(D_WEB_CLIENT, "%llu: API v1 health query param '%s' with value '%s'", w->id, key, value);
88
-
89
- // name and value are now the parameters
90
- if (!strncmp(key, "cmd",lkey)) {
91
- if (!strcmp(value, HEALTH_CMDAPI_CMD_SILENCEALL)) {
92
- silencers->all_alarms = 1;
93
- silencers->stype = STYPE_SILENCE_NOTIFICATIONS;
94
- buffer_strcat(wb, HEALTH_CMDAPI_MSG_SILENCEALL);
95
- } else if (!strcmp(value, HEALTH_CMDAPI_CMD_DISABLEALL)) {
96
- silencers->all_alarms = 1;
97
- silencers->stype = STYPE_DISABLE_ALARMS;
98
- buffer_strcat(wb, HEALTH_CMDAPI_MSG_DISABLEALL);
99
- } else if (!strcmp(value, HEALTH_CMDAPI_CMD_SILENCE)) {
100
- silencers->stype = STYPE_SILENCE_NOTIFICATIONS;
101
- buffer_strcat(wb, HEALTH_CMDAPI_MSG_SILENCE);
102
- } else if (!strcmp(value, HEALTH_CMDAPI_CMD_DISABLE)) {
103
- silencers->stype = STYPE_DISABLE_ALARMS;
104
- buffer_strcat(wb, HEALTH_CMDAPI_MSG_DISABLE);
105
- } else if (!strcmp(value, HEALTH_CMDAPI_CMD_RESET)) {
106
- silencers->all_alarms = 0;
107
- silencers->stype = STYPE_NONE;
108
- free_silencers(silencers->silencers);
109
- silencers->silencers = NULL;
110
- buffer_strcat(wb, HEALTH_CMDAPI_MSG_RESET);
111
- }
112
- } else {
113
- uint32_t hash = simple_uhash(key);
114
- if (unlikely(silencer == NULL)) {
115
- if (
116
- (hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) ||
117
- (hash == hash_template && !strcasecmp(key, HEALTH_TEMPLATE_KEY)) ||
118
- (hash == hash_chart && !strcasecmp(key, HEALTH_CHART_KEY)) ||
119
- (hash == hash_context && !strcasecmp(key, HEALTH_CONTEXT_KEY)) ||
120
- (hash == hash_host && !strcasecmp(key, HEALTH_HOST_KEY)) ||
121
- (hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY))
122
- ) {
123
- silencer = create_silencer();
124
- }
125
- }
126
-
127
- if (hash == hash_alarm && !strncasecmp(key, HEALTH_ALARM_KEY,lkey)) {
128
- silencer->alarms = strdupz(value);
129
- silencer->alarms_pattern = simple_pattern_create(silencer->alarms, NULL, SIMPLE_PATTERN_EXACT);
130
- } else if (hash == hash_chart && !strncasecmp(key, HEALTH_CHART_KEY,lkey)) {
131
- silencer->charts = strdupz(value);
132
- silencer->charts_pattern = simple_pattern_create(silencer->charts, NULL, SIMPLE_PATTERN_EXACT);
133
- } else if (hash == hash_context && !strncasecmp(key, HEALTH_CONTEXT_KEY,lkey)) {
134
- silencer->contexts = strdupz(value);
135
- silencer->contexts_pattern = simple_pattern_create(silencer->contexts, NULL, SIMPLE_PATTERN_EXACT);
136
- } else if (hash == hash_host && !strncasecmp(key, HEALTH_HOST_KEY,lkey)) {
137
- silencer->hosts = strdupz(value);
138
- silencer->hosts_pattern = simple_pattern_create(silencer->hosts, NULL, SIMPLE_PATTERN_EXACT);
139
- } else if (hash == hash_families && !strncasecmp(key, HEALTH_FAMILIES_KEY,lkey)) {
140
- silencer->families = strdupz(value);
141
- silencer->families_pattern = simple_pattern_create(silencer->families, NULL, SIMPLE_PATTERN_EXACT);
142
- } else {
143
- buffer_strcat(wb, HEALTH_CMDAPI_MSG_INVALID_KEY);
76
+ while (url) {
77
+ char *value = mystrsep(&url, "&");
78
+ if (!value || !*value) continue;
79
+
80
+ char *key = mystrsep(&value, "=");
81
+ if (!key || !*key) continue;
82
+ if (!value || !*value) continue;
83
+
84
+ debug(D_WEB_CLIENT, "%llu: API v1 health query param '%s' with value '%s'", w->id, key, value);
85
+
86
+ // name and value are now the parameters
87
+ if (!strcmp(key, "cmd")) {
88
+ if (!strcmp(value, HEALTH_CMDAPI_CMD_SILENCEALL)) {
89
+ silencers->all_alarms = 1;
90
+ silencers->stype = STYPE_SILENCE_NOTIFICATIONS;
91
+ buffer_strcat(wb, HEALTH_CMDAPI_MSG_SILENCEALL);
92
+ } else if (!strcmp(value, HEALTH_CMDAPI_CMD_DISABLEALL)) {
93
+ silencers->all_alarms = 1;
94
+ silencers->stype = STYPE_DISABLE_ALARMS;
95
+ buffer_strcat(wb, HEALTH_CMDAPI_MSG_DISABLEALL);
96
+ } else if (!strcmp(value, HEALTH_CMDAPI_CMD_SILENCE)) {
97
+ silencers->stype = STYPE_SILENCE_NOTIFICATIONS;
98
+ buffer_strcat(wb, HEALTH_CMDAPI_MSG_SILENCE);
99
+ } else if (!strcmp(value, HEALTH_CMDAPI_CMD_DISABLE)) {
100
+ silencers->stype = STYPE_DISABLE_ALARMS;
101
+ buffer_strcat(wb, HEALTH_CMDAPI_MSG_DISABLE);
102
+ } else if (!strcmp(value, HEALTH_CMDAPI_CMD_RESET)) {
103
+ silencers->all_alarms = 0;
104
+ silencers->stype = STYPE_NONE;
105
+ free_silencers(silencers->silencers);
106
+ silencers->silencers = NULL;
107
+ buffer_strcat(wb, HEALTH_CMDAPI_MSG_RESET);
108
+ }
109
+ } else {
110
+ uint32_t hash = simple_uhash(key);
111
+ if (unlikely(silencer == NULL)) {
112
+ if (
113
+ (hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) ||
114
+ (hash == hash_template && !strcasecmp(key, HEALTH_TEMPLATE_KEY)) ||
115
+ (hash == hash_chart && !strcasecmp(key, HEALTH_CHART_KEY)) ||
116
+ (hash == hash_context && !strcasecmp(key, HEALTH_CONTEXT_KEY)) ||
117
+ (hash == hash_host && !strcasecmp(key, HEALTH_HOST_KEY)) ||
118
+ (hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY))
119
+ ) {
120
+ silencer = create_silencer();
121
}
122
}
146
- key[lkey] = ksave ;
147
- value[lvalue] = vsave ;
123
149
- } while( ++i < end );
124
+ if (hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) {
125
+ silencer->alarms = strdupz(value);
126
+ silencer->alarms_pattern = simple_pattern_create(silencer->alarms, NULL, SIMPLE_PATTERN_EXACT);
127
+ } else if (hash == hash_chart && !strcasecmp(key, HEALTH_CHART_KEY)) {
128
+ silencer->charts = strdupz(value);
129
+ silencer->charts_pattern = simple_pattern_create(silencer->charts, NULL, SIMPLE_PATTERN_EXACT);
130
+ } else if (hash == hash_context && !strcasecmp(key, HEALTH_CONTEXT_KEY)) {
131
+ silencer->contexts = strdupz(value);
132
+ silencer->contexts_pattern = simple_pattern_create(silencer->contexts, NULL, SIMPLE_PATTERN_EXACT);
133
+ } else if (hash == hash_host && !strcasecmp(key, HEALTH_HOST_KEY)) {
134
+ silencer->hosts = strdupz(value);
135
+ silencer->hosts_pattern = simple_pattern_create(silencer->hosts, NULL, SIMPLE_PATTERN_EXACT);
136
+ } else if (hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY)) {
137
+ silencer->families = strdupz(value);
138
+ silencer->families_pattern = simple_pattern_create(silencer->families, NULL, SIMPLE_PATTERN_EXACT);
139
+ } else {
140
+ buffer_strcat(wb, HEALTH_CMDAPI_MSG_INVALID_KEY);
141
+ }
142
+ }
143
144
}
152
-
145
if (likely(silencer)) {
146
// Add the created instance to the linked list in silencers
147
silencer->next = silencers->silencers;
@@ -168,7 +160,6 @@ int web_client_api_request_v1_mgmt_health(RRDHOST *host, struct web_client *w, c
160
ret = 200;
161
}
162
}
171
-
163
w->response.data = wb;
164
buffer_no_cacheable(w->response.data);
165
return ret;
web/api/web_api_v1.c
+138
-174
@@ -195,18 +195,14 @@ inline uint32_t web_client_api_request_v1_data_google_format(char *name) {
195
196
197
inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, char *url) {
198
- (void)url;
198
int all = 0;
199
201
- uint32_t end = w->total_params;
202
- if(end) {
203
- uint32_t i = 0;
204
- do {
205
- char *value = w->param_values[i].body;
200
+ while(url) {
201
+ char *value = mystrsep(&url, "&");
202
+ if (!value || !*value) continue;
203
207
- if(!strncmp(value, "all",3)) all = 1;
208
- else if(!strncmp(value, "active",6)) all = 0;
209
- } while(++i < end);
204
+ if(!strcmp(value, "all")) all = 1;
205
+ else if(!strcmp(value, "active")) all = 0;
206
}
207
208
buffer_flush(w->response.data);
@@ -217,24 +213,17 @@ inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w,
213
}
214
215
inline int web_client_api_request_v1_alarm_log(RRDHOST *host, struct web_client *w, char *url) {
220
- (void)url;
216
uint32_t after = 0;
217
223
- uint32_t end = w->total_params;
224
- if(end) {
225
- uint32_t i = 0;
226
- do {
227
- char *value = w->param_values[i].body;
228
- size_t lvalue = w->param_values[i].length;
229
- char save = value[lvalue];
230
- value[lvalue] = 0x00;
231
-
232
- char *name = w->param_name[i].body;
233
- size_t lname = w->param_name[i].length;
234
-
235
- if(!strncmp(name, "after",lname)) after = (uint32_t)strtoul(value, NULL, 0);
236
- value[lvalue] = save;
237
- } while (++i < end);
218
+ while(url) {
219
+ char *value = mystrsep(&url, "&");
220
+ if (!value || !*value) continue;
221
+
222
+ char *name = mystrsep(&value, "=");
223
+ if(!name || !*name) continue;
224
+ if(!value || !*value) continue;
225
+
226
+ if(!strcmp(name, "after")) after = (uint32_t)strtoul(value, NULL, 0);
227
}
228
229
buffer_flush(w->response.data);
@@ -244,29 +233,27 @@ inline int web_client_api_request_v1_alarm_log(RRDHOST *host, struct web_client
233
}
234
235
inline int web_client_api_request_single_chart(RRDHOST *host, struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf)) {
247
- (void)url;
236
int ret = 400;
237
char *chart = NULL;
238
239
buffer_flush(w->response.data);
240
253
- uint32_t i = 0;
254
- uint32_t end = w->total_params;
255
- if(end) {
256
- do {
257
- char *name = w->param_name[i].body;
258
- size_t nlength = w->param_name[i].length;
259
- char *value = w->param_values[i].body;
260
-
261
- // name and value are now the parameters
262
- // they are not null and not empty
263
-
264
- if(!strncmp(name, "chart",nlength)) chart = value;
265
- //else {
266
- /// buffer_sprintf(w->response.data, "Unknown parameter '%s' in request.", name);
267
- // goto cleanup;
268
- //}
269
- } while (++i < end);
241
+ while(url) {
242
+ char *value = mystrsep(&url, "&");
243
+ if(!value || !*value) continue;
244
+
245
+ char *name = mystrsep(&value, "=");
246
+ if(!name || !*name) continue;
247
+ if(!value || !*value) continue;
248
+
249
+ // name and value are now the parameters
250
+ // they are not null and not empty
251
+
252
+ if(!strcmp(name, "chart")) chart = value;
253
+ //else {
254
+ /// buffer_sprintf(w->response.data, "Unknown parameter '%s' in request.", name);
255
+ // goto cleanup;
256
+ //}
257
}
258
259
if(!chart || !*chart) {
@@ -320,7 +307,6 @@ void fix_google_param(char *s) {
307
308
// returns the HTTP code
309
inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, char *url) {
323
- (void)url;
310
debug(D_WEB_CLIENT, "%llu: API v1 data with URL '%s'", w->id, url);
311
312
int ret = 400;
@@ -347,82 +333,75 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
333
uint32_t format = DATASOURCE_JSON;
334
uint32_t options = 0x00000000;
335
350
- uint32_t end = w->total_params;
351
- char save[WEB_FIELDS_MAX];
352
- char *value ;
353
- size_t lvalue;
354
- if(end) {
355
- uint32_t i = 0;
356
- do {
357
- char *name = w->param_name[i].body;
358
- size_t lname = w->param_name[i].length;
359
- value = w->param_values[i].body;
360
- lvalue = w->param_values[i].length;
361
- save[i] = value[lvalue];
362
- value[lvalue] = 0x00;
363
-
364
- debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value);
365
-
366
- // name and value are now the parameters
367
- // they are not null and not empty
368
-
369
- if(!strncmp(name, "chart",lname)) chart = value;
370
- else if(!strncmp(name, "dimension",lname) || !strncmp(name, "dim",lname) || !strncmp(name, "dimensions",lname) || !strncmp(name, "dims",lname)) {
371
- if(!dimensions) dimensions = buffer_create(100);
372
- buffer_strcat(dimensions, "|");
373
- buffer_strcat(dimensions, value);
374
- }
375
- else if(!strncmp(name, "after",lname)) after_str = value;
376
- else if(!strncmp(name, "before",lname)) before_str = value;
377
- else if(!strncmp(name, "points",lname)) points_str = value;
378
- else if(!strncmp(name, "gtime",lname)) group_time_str = value;
379
- else if(!strncmp(name, "group",lname)) {
380
- group = web_client_api_request_v1_data_group(value, RRDR_GROUPING_AVERAGE);
381
- }
382
- else if(!strncmp(name, "format",lname)) {
383
- format = web_client_api_request_v1_data_format(value);
384
- }
385
- else if(!strncmp(name, "options",lname)) {
386
- options |= web_client_api_request_v1_data_options(value);
387
- }
388
- else if(!strncmp(name, "callback",lname)) {
389
- responseHandler = value;
390
- }
391
- else if(!strncmp(name, "filename",lname)) {
392
- outFileName = value;
393
- }
394
- else if(!strncmp(name, "tqx",lname)) {
395
- // parse Google Visualization API options
396
- // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source
397
- char *tqx_name, *tqx_value;
398
-
399
- while(value) {
400
- tqx_value = mystrsep(&value, ";");
401
- if(!tqx_value || !*tqx_value) continue;
402
-
403
- tqx_name = mystrsep(&tqx_value, ":");
404
- if(!tqx_name || !*tqx_name) continue;
405
- if(!tqx_value || !*tqx_value) continue;
406
-
407
- if(!strcmp(tqx_name, "version"))
408
- google_version = tqx_value;
409
- else if(!strcmp(tqx_name, "reqId"))
410
- google_reqId = tqx_value;
411
- else if(!strcmp(tqx_name, "sig")) {
412
- google_sig = tqx_value;
413
- google_timestamp = strtoul(google_sig, NULL, 0);
414
- }
415
- else if(!strcmp(tqx_name, "out")) {
416
- google_out = tqx_value;
417
- format = web_client_api_request_v1_data_google_format(google_out);
418
- }
419
- else if(!strcmp(tqx_name, "responseHandler"))
420
- responseHandler = tqx_value;
421
- else if(!strcmp(tqx_name, "outFileName"))
422
- outFileName = tqx_value;
336
+ while(url) {
337
+ char *value = mystrsep(&url, "&");
338
+ if(!value || !*value) continue;
339
+
340
+ char *name = mystrsep(&value, "=");
341
+ if(!name || !*name) continue;
342
+ if(!value || !*value) continue;
343
+
344
+ debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value);
345
+
346
+ // name and value are now the parameters
347
+ // they are not null and not empty
348
+
349
+ if(!strcmp(name, "chart")) chart = value;
350
+ else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) {
351
+ if(!dimensions) dimensions = buffer_create(100);
352
+ buffer_strcat(dimensions, "|");
353
+ buffer_strcat(dimensions, value);
354
+ }
355
+ else if(!strcmp(name, "after")) after_str = value;
356
+ else if(!strcmp(name, "before")) before_str = value;
357
+ else if(!strcmp(name, "points")) points_str = value;
358
+ else if(!strcmp(name, "gtime")) group_time_str = value;
359
+ else if(!strcmp(name, "group")) {
360
+ group = web_client_api_request_v1_data_group(value, RRDR_GROUPING_AVERAGE);
361
+ }
362
+ else if(!strcmp(name, "format")) {
363
+ format = web_client_api_request_v1_data_format(value);
364
+ }
365
+ else if(!strcmp(name, "options")) {
366
+ options |= web_client_api_request_v1_data_options(value);
367
+ }
368
+ else if(!strcmp(name, "callback")) {
369
+ responseHandler = value;
370
+ }
371
+ else if(!strcmp(name, "filename")) {
372
+ outFileName = value;
373
+ }
374
+ else if(!strcmp(name, "tqx")) {
375
+ // parse Google Visualization API options
376
+ // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source
377
+ char *tqx_name, *tqx_value;
378
+
379
+ while(value) {
380
+ tqx_value = mystrsep(&value, ";");
381
+ if(!tqx_value || !*tqx_value) continue;
382
+
383
+ tqx_name = mystrsep(&tqx_value, ":");
384
+ if(!tqx_name || !*tqx_name) continue;
385
+ if(!tqx_value || !*tqx_value) continue;
386
+
387
+ if(!strcmp(tqx_name, "version"))
388
+ google_version = tqx_value;
389
+ else if(!strcmp(tqx_name, "reqId"))
390
+ google_reqId = tqx_value;
391
+ else if(!strcmp(tqx_name, "sig")) {
392
+ google_sig = tqx_value;
393
+ google_timestamp = strtoul(google_sig, NULL, 0);
394
+ }
395
+ else if(!strcmp(tqx_name, "out")) {
396
+ google_out = tqx_value;
397
+ format = web_client_api_request_v1_data_google_format(google_out);
398
}
399
+ else if(!strcmp(tqx_name, "responseHandler"))
400
+ responseHandler = tqx_value;
401
+ else if(!strcmp(tqx_name, "outFileName"))
402
+ outFileName = tqx_value;
403
}
425
- } while (++i < end);
404
+ }
405
}
406
407
// validate the google parameters given
@@ -509,14 +488,6 @@ inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, c
488
buffer_strcat(w->response.data, ");");
489
490
cleanup:
512
- if(end) {
513
- uint32_t i = 0;
514
- do {
515
- value = w->param_values[i].body;
516
- lvalue = w->param_values[i].length;
517
- value[lvalue] = save[i];
518
- } while ( ++i < end );
519
- }
491
buffer_free(dimensions);
492
return ret;
493
}
@@ -580,33 +551,26 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *
551
int redirects = 0;
552
*/
553
583
- uint32_t i = 0;
584
- uint32_t end = w->total_params;
585
- if (!end) {
586
- goto nothing;
587
- }
554
+ while(url) {
555
+ char *value = mystrsep(&url, "&");
556
+ if (!value || !*value) continue;
557
589
- do {
590
- char *name = w->param_name[i].body;
591
- size_t nlength = w->param_name[i].length;
592
- char *value = w->param_values[i].body;
593
- size_t vlength = w->param_values[i].length;
558
+ char *name = mystrsep(&value, "=");
559
+ if (!name || !*name) continue;
560
+ if (!value || !*value) continue;
561
562
debug(D_WEB_CLIENT, "%llu: API v1 registry query param '%s' with value '%s'", w->id, name, value);
563
597
- //uint32_t hash = simple_hash(name);
598
- uint32_t hash = simple_nhash(name,nlength);
564
+ uint32_t hash = simple_hash(name);
565
600
- //if(hash == hash_action && !strcmp(name, "action")) {
601
- if(hash == hash_action && !strncmp(name, "action",nlength)) {
602
- //uint32_t vhash = simple_hash(value);
603
- uint32_t vhash = simple_nhash(value,vlength);
566
+ if(hash == hash_action && !strcmp(name, "action")) {
567
+ uint32_t vhash = simple_hash(value);
568
605
- if(vhash == hash_access && !strncmp(value, "access",vlength)) action = 'A';
606
- else if(vhash == hash_hello && !strncmp(value, "hello",vlength)) action = 'H';
607
- else if(vhash == hash_delete && !strncmp(value, "delete",vlength)) action = 'D';
608
- else if(vhash == hash_search && !strncmp(value, "search",vlength)) action = 'S';
609
- else if(vhash == hash_switch && !strncmp(value, "switch",vlength)) action = 'W';
569
+ if(vhash == hash_access && !strcmp(value, "access")) action = 'A';
570
+ else if(vhash == hash_hello && !strcmp(value, "hello")) action = 'H';
571
+ else if(vhash == hash_delete && !strcmp(value, "delete")) action = 'D';
572
+ else if(vhash == hash_search && !strcmp(value, "search")) action = 'S';
573
+ else if(vhash == hash_switch && !strcmp(value, "switch")) action = 'W';
574
#ifdef NETDATA_INTERNAL_CHECKS
575
else error("unknown registry action '%s'", value);
576
#endif /* NETDATA_INTERNAL_CHECKS */
@@ -615,34 +579,33 @@ inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *
579
else if(hash == hash_redirects && !strcmp(name, "redirects"))
580
redirects = atoi(value);
581
*/
618
- else if(hash == hash_machine && !strncmp(name, "machine",nlength))
582
+ else if(hash == hash_machine && !strcmp(name, "machine"))
583
machine_guid = value;
584
621
- else if(hash == hash_url && !strncmp(name, "url",nlength))
585
+ else if(hash == hash_url && !strcmp(name, "url"))
586
machine_url = value;
587
588
else if(action == 'A') {
625
- if(hash == hash_name && !strncmp(name, "name",nlength))
589
+ if(hash == hash_name && !strcmp(name, "name"))
590
url_name = value;
591
}
592
else if(action == 'D') {
629
- if(hash == hash_delete_url && !strncmp(name, "delete_url",nlength))
593
+ if(hash == hash_delete_url && !strcmp(name, "delete_url"))
594
delete_url = value;
595
}
596
else if(action == 'S') {
633
- if(hash == hash_for && !strncmp(name, "for",nlength))
597
+ if(hash == hash_for && !strcmp(name, "for"))
598
search_machine_guid = value;
599
}
600
else if(action == 'W') {
637
- if(hash == hash_to && !strncmp(name, "to",nlength))
601
+ if(hash == hash_to && !strcmp(name, "to"))
602
to_person_guid = value;
603
}
604
#ifdef NETDATA_INTERNAL_CHECKS
605
else error("unused registry URL parameter '%s' with value '%s'", name, value);
606
#endif /* NETDATA_INTERNAL_CHECKS */
643
- } while (++i < end );
607
+ }
608
645
-nothing:
609
if(unlikely(respect_web_browser_do_not_track_policy && web_client_has_donottrack(w))) {
610
buffer_flush(w->response.data);
611
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.");
@@ -834,27 +797,28 @@ inline int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char *
797
}
798
799
// get the command
800
+ char *tok = mystrsep(&url, "?");
801
+ if(tok && *tok) {
802
+ debug(D_WEB_CLIENT, "%llu: Searching for API v1 command '%s'.", w->id, tok);
803
+ uint32_t hash = simple_hash(tok);
804
838
- char *cmd = w->command.body;
839
- size_t length = w->command.length;
840
- uint32_t hash = simple_nhash(cmd,length);
841
-
842
- for(i = 0; api_commands[i].command ;i++) {
843
- if(unlikely(hash == api_commands[i].hash && !strncmp(cmd, api_commands[i].command,length))) {
844
- if(unlikely(api_commands[i].acl != WEB_CLIENT_ACL_NOCHECK) && !(w->acl & api_commands[i].acl))
845
- return web_client_permission_denied(w);
805
+ for(i = 0; api_commands[i].command ;i++) {
806
+ if(unlikely(hash == api_commands[i].hash && !strcmp(tok, api_commands[i].command))) {
807
+ if(unlikely(api_commands[i].acl != WEB_CLIENT_ACL_NOCHECK) && !(w->acl & api_commands[i].acl))
808
+ return web_client_permission_denied(w);
809
847
- return api_commands[i].callback(host, w, url);
810
+ return api_commands[i].callback(host, w, url);
811
+ }
812
}
849
- }
850
-
851
- char copyme[256];
852
- length = w->path.length;
853
- memcpy(copyme,w->path.body,length);
854
- copyme[length] = 0x00;
813
856
- buffer_flush(w->response.data);
857
- buffer_strcat(w->response.data, "Unsupported v1 API command: ");
858
- buffer_strcat_htmlescape(w->response.data, copyme);
859
- return 404;
814
+ buffer_flush(w->response.data);
815
+ buffer_strcat(w->response.data, "Unsupported v1 API command: ");
816
+ buffer_strcat_htmlescape(w->response.data, tok);
817
+ return 404;
818
+ }
819
+ else {
820
+ buffer_flush(w->response.data);
821
+ buffer_sprintf(w->response.data, "Which API v1 command?");
822
+ return 400;
823
+ }
824
}
web/server/web_client.c
+160
-353
@@ -143,7 +143,7 @@ void web_client_request_done(struct web_client *w) {
143
debug(D_WEB_CLIENT, "%llu: Closing filecopy input file descriptor %d.", w->id, w->ifd);
144
145
if(web_server_mode != WEB_SERVER_MODE_STATIC_THREADED) {
146
- if (w->ifd != -1) {
146
+ if (w->ifd != -1){
147
close(w->ifd);
148
}
149
}
@@ -352,7 +352,7 @@ int mysendfile(struct web_client *w, char *filename) {
352
// if the filename contains "strange" characters, refuse to serve it
353
char *s;
354
for(s = filename; *s ;s++) {
355
- if(!isalnum(*s) && *s != '/' && *s != '.' && *s != '-' && *s != '_') {
355
+ if( !isalnum(*s) && *s != '/' && *s != '.' && *s != '-' && *s != '_') {
356
debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
357
w->response.data->contenttype = CT_TEXT_HTML;
358
buffer_sprintf(w->response.data, "Filename contains invalid characters: ");
@@ -594,26 +594,15 @@ int web_client_api_request(RRDHOST *host, struct web_client *w, char *url)
594
{
595
// get the api version
596
char *tok = mystrsep(&url, "/");
597
- (void)tok;
598
- char *body = w->version.body;
599
- size_t length = w->version.length;
600
- if(body) {
601
- //if(tok && *tok) {
602
- //debug(D_WEB_CLIENT, "%llu: Searching for API version '%s'.", w->id, tok);
603
- debug(D_WEB_CLIENT, "%llu: Searching for API version'.", w->id);
604
- //if(strcmp(tok, "v1") == 0)
605
- if(strncmp(body, "v1",length) == 0) {
597
+ if(tok && *tok) {
598
+ debug(D_WEB_CLIENT, "%llu: Searching for API version '%s'.", w->id, tok);
599
+ if(strcmp(tok, "v1") == 0)
600
return web_client_api_request_v1(host, w, url);
607
- } else {
608
- char response[NETDATA_WEB_REQUEST_URL_SIZE];
609
- strncpy(response,w->version.body,length);
610
- response[length] = 0x00;
601
+ else {
602
buffer_flush(w->response.data);
612
-
603
w->response.data->contenttype = CT_TEXT_HTML;
604
buffer_strcat(w->response.data, "Unsupported API version: ");
615
- buffer_strcat_htmlescape(w->response.data, response);
616
- //buffer_strcat_htmlescape(w->response.data, tok);
605
+ buffer_strcat_htmlescape(w->response.data, tok);
606
return 404;
607
}
608
}
@@ -802,7 +791,7 @@ static inline char *http_header_parse(struct web_client *w, char *s, int parse_u
791
} else if(hash == hash_authorization&& !strcasecmp(s, "X-Auth-Token")) {
792
w->auth_bearer_token = strdupz(v);
793
}
805
- else if(hash == hash_host && !strcasecmp(s, "Host")) {
794
+ else if(hash == hash_host && !strcasecmp(s, "Host")){
795
strncpyz(w->host, v, (ve - v));
796
}
797
#ifdef NETDATA_WITH_ZLIB
@@ -823,67 +812,76 @@ static inline char *http_header_parse(struct web_client *w, char *s, int parse_u
812
return ve;
813
}
814
826
-static inline HTTP_VALIDATION web_client_is_complete(char *begin,char *end,size_t length){
827
- if ( begin == end){
828
- return HTTP_VALIDATION_INCOMPLETE;
829
- }
815
+// http_request_validate()
816
+// returns:
817
+// = 0 : all good, process the request
818
+// > 0 : request is not supported
819
+// < 0 : request is incomplete - wait for more data
820
831
- if ( length > 3 ){
832
- begin = end - 4;
833
- }
821
+typedef enum {
822
+ HTTP_VALIDATION_OK,
823
+ HTTP_VALIDATION_NOT_SUPPORTED,
824
+#ifdef ENABLE_HTTPS
825
+ HTTP_VALIDATION_INCOMPLETE,
826
+ HTTP_VALIDATION_REDIRECT
827
+#else
828
+ HTTP_VALIDATION_INCOMPLETE
829
+#endif
830
+} HTTP_VALIDATION;
831
835
- uint32_t counter = 0;
836
- do{
837
- if (*begin == '\r'){
838
- begin++;
839
- if ( begin == end )
840
- {
841
- break;
842
- }
832
+static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
833
+ char *s = (char *)buffer_tostring(w->response.data), *encoded_url = NULL;
834
+
835
+ size_t last_pos = w->header_parse_last_size;
836
+ if(last_pos > 4) last_pos -= 4; // allow searching for \r\n\r\n
837
+ else last_pos = 0;
838
844
- if (*begin == '\n')
845
- {
846
- counter++;
839
+ w->header_parse_tries++;
840
+ w->header_parse_last_size = buffer_strlen(w->response.data);
841
+
842
+ if(w->header_parse_tries > 1) {
843
+ if(w->header_parse_last_size < last_pos)
844
+ last_pos = 0;
845
+
846
+ if(strstr(&s[last_pos], "\r\n\r\n") == NULL) {
847
+ if(w->header_parse_tries > 10) {
848
+ info("Disabling slow client after %zu attempts to read the request (%zu bytes received)", w->header_parse_tries, buffer_strlen(w->response.data));
849
+ w->header_parse_tries = 0;
850
+ w->header_parse_last_size = 0;
851
+ web_client_disable_wait_receive(w);
852
+ return HTTP_VALIDATION_NOT_SUPPORTED;
853
}
848
- } else if (*begin == '\n') {
849
- begin++;
850
- counter++;
851
- }
854
853
- if ( counter == 2){
854
- break;
855
+ return HTTP_VALIDATION_INCOMPLETE;
856
}
857
}
857
- while(begin != end);
858
859
- return (counter == 2)?HTTP_VALIDATION_OK:HTTP_VALIDATION_INCOMPLETE;
860
-}
861
-
862
-static inline char *web_client_parse_method(struct web_client *w,char *s) {
859
+ // is is a valid request?
860
if(!strncmp(s, "GET ", 4)) {
864
- s = &s[4];
861
+ encoded_url = s = &s[4];
862
w->mode = WEB_CLIENT_MODE_NORMAL;
863
}
864
else if(!strncmp(s, "OPTIONS ", 8)) {
868
- s = &s[8];
865
+ encoded_url = s = &s[8];
866
w->mode = WEB_CLIENT_MODE_OPTIONS;
867
}
868
else if(!strncmp(s, "STREAM ", 7)) {
869
#ifdef ENABLE_HTTPS
873
- if ((w->ssl.flags) && (netdata_use_ssl_on_stream & NETDATA_SSL_FORCE)) {
870
+ if ( (w->ssl.flags) && (netdata_use_ssl_on_stream & NETDATA_SSL_FORCE)){
871
w->header_parse_tries = 0;
872
w->header_parse_last_size = 0;
873
web_client_disable_wait_receive(w);
874
char hostname[256];
875
char *copyme = strstr(s,"hostname=");
879
- if (copyme) {
876
+ if ( copyme ){
877
copyme += 9;
878
char *end = strchr(copyme,'&');
882
- if(end) {
879
+ if(end){
880
size_t length = end - copyme;
881
memcpy(hostname,copyme,length);
882
hostname[length] = 0X00;
886
- } else {
883
+ }
884
+ else{
885
memcpy(hostname,"not available",13);
886
hostname[13] = 0x00;
887
}
@@ -893,205 +891,30 @@ static inline char *web_client_parse_method(struct web_client *w,char *s) {
891
hostname[13] = 0x00;
892
}
893
error("The server is configured to always use encrypt connection, please enable the SSL on slave with hostname '%s'.",hostname);
896
- return NULL;
894
+ return HTTP_VALIDATION_NOT_SUPPORTED;
895
}
896
#endif
899
- s = &s[7];
897
+
898
+ encoded_url = s = &s[7];
899
w->mode = WEB_CLIENT_MODE_STREAM;
900
}
901
else {
903
- s = NULL;
904
- }
905
-
906
- return s;
907
-}
908
-
909
-static inline char *web_client_find_protocol(struct web_client *w,char *s) {
910
- s = url_find_protocol(s);
911
-
912
- w->protocol.body = s+1;
913
- char *end = strchr(s+6,'\n');
914
- if (end) {
915
- w->protocol.length = end - w->protocol.body ;
916
- }
917
-
918
- return s;
919
-}
920
-
921
-static inline void web_client_parse_headers(struct web_client *w,char *s) {
922
- while(*s) {
923
- // find a line feed
924
- while(*s && *s++ != '\r');
925
-
926
- // did we reach the end?
927
- if(unlikely(!*s)) break;
928
-
929
- if (*s == '\n') {
930
- s++;
931
- }
932
-
933
- s = http_header_parse(w, s,
934
- (w->mode == WEB_CLIENT_MODE_STREAM) // parse user agent
935
- );
936
-
937
- }
938
-}
939
-
940
-int web_client_parse_request(struct web_client *w,char *divisor) {
941
- if(!divisor) {
942
- w->total_params = 0;
943
- return 0;
944
- }
945
-
946
- uint32_t i = url_parse_query_string(w->param_name,w->param_values,w->query_string.body+1,divisor);
947
- w->total_params = i;
948
-
949
- return i;
950
-}
951
-
952
-static inline void web_client_set_directory(struct web_client *w,char *begin,char *enddir,char *endcmd) {
953
- if (enddir) {
954
- w->directory.body = begin;
955
- w->directory.length = enddir - begin;
956
-
957
- if (!strncmp(w->directory.body,"api",w->directory.length)) {
958
- begin = enddir + 1;
959
- enddir = strchr(begin,'/');
960
- if(enddir) {
961
- w->version.body = begin;
962
- w->version.length = enddir - begin;
963
-
964
- enddir++;
965
- w->command.body = enddir;
966
- w->command.length = (size_t) (endcmd - enddir);
967
- }
968
- }
969
- }
970
- else{
971
- w->directory.body = begin;
972
- w->directory.length = w->path.length - 1;
973
- w->version.body = NULL;
974
- w->version.length = 0;
975
- w->command.body = NULL;
976
- w->command.length = 0;
977
- }
978
-}
979
-
980
-static inline void web_client_set_without_query_string(struct web_client *w) {
981
- w->query_string.body = NULL;
982
- w->query_string.length = 0;
983
-
984
- char *test = w->path.body+1;
985
- if (!strncmp(test,"api/v1/",7) ) {
986
- test += 7;
987
- if (!strncmp(test,"info",4)) {
988
- w->command.length = 4;
989
- }
990
- else if (!strncmp(test,"charts",6)) {
991
- w->command.length = 6;
992
- }
993
- else {
994
- test = NULL;
995
- w->command.length = 0;
996
- }
997
- }else{
998
- w->command.length = w->path.length;
999
- }
1000
- w->command.body = test;
1001
- w->total_params = 0;
1002
-}
1003
-
1004
-static inline void web_client_split_path_query(struct web_client *w) {
1005
- w->path.body = w->decoded_url;
1006
- w->decoded_length = strlen(w->decoded_url);
1007
- char *moveme = strchr(w->path.body,'?');
1008
- char *enddir;
1009
- if (moveme) {
1010
- w->path.length = moveme - w->path.body;
1011
- w->query_string.body = moveme;
1012
- w->query_string.length = w->decoded_length - w->path.length;
1013
-
1014
- enddir = strchr(w->path.body+1,'/');
1015
- char *begin = w->path.body+1;
1016
- web_client_set_directory(w,begin,enddir,moveme);
1017
- if (w->query_string.body) {
1018
- enddir = strchr(moveme,'=');
1019
- if (!web_client_parse_request(w,enddir) ) {
1020
- moveme++;
1021
- size_t length = strlen(moveme);
1022
- w->param_name[0].body = moveme;
1023
- w->param_name[0].length = length;
1024
- w->param_values[0].body = moveme;
1025
- w->param_values[0].length = length;
1026
-
1027
- w->total_params = 1;
1028
- }
1029
- }
1030
- } else {
1031
- w->path.length = w->decoded_length;
1032
-
1033
- enddir = strchr(w->path.body+1,'/');
1034
- w->directory.body = w->path.body + 1;
1035
- if(enddir) {
1036
- w->directory.length = (size_t)(enddir - w->directory.body);
1037
- enddir++;
1038
-
1039
- w->version.body = enddir;
1040
- enddir = strchr(++enddir,'/');
1041
- if(enddir) {
1042
- w->version.length = (size_t)(enddir - w->version.body);
1043
-
1044
- enddir++;
1045
- w->command.body = enddir;
1046
- w->command.length = (size_t)(moveme - enddir);
1047
- } else{
1048
- w->version.length = strlen(w->version.body);
1049
- }
1050
-
1051
- }else {
1052
- w->directory.length = w->decoded_length - 1;
1053
- }
1054
- web_client_set_without_query_string(w);
1055
- }
1056
-}
1057
-
1058
-static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
1059
- char *s = (char *)buffer_tostring(w->response.data), *encoded_url = NULL;
1060
- size_t status;
1061
-
1062
- w->header_parse_tries++;
1063
- w->header_parse_last_size = buffer_strlen(w->response.data);
1064
- status = w->header_parse_last_size;
1065
-
1066
- // make sure we have complete request
1067
- // complete requests contain: \r\n\r\n
1068
- status = url_is_request_complete(s,&s[status],status);
1069
- if (w->header_parse_tries > 10) {
1070
- if (status == HTTP_VALIDATION_INCOMPLETE) {
1071
- info("Disabling slow client after %zu attempts to read the request (%zu bytes received)", w->header_parse_tries, buffer_strlen(w->response.data));
1072
- w->header_parse_tries = 0;
1073
- w->header_parse_last_size = 0;
1074
- web_client_disable_wait_receive(w);
1075
- return HTTP_VALIDATION_NOT_SUPPORTED;
1076
- }
1077
- } else{
1078
- if (status == HTTP_VALIDATION_INCOMPLETE) {
1079
- web_client_enable_wait_receive(w);
1080
- return HTTP_VALIDATION_INCOMPLETE;
1081
- }
1082
- }
1083
- //Parse the method used to communicate
1084
- s = web_client_parse_method(w,s);
1085
- if (!s) {
902
w->header_parse_tries = 0;
903
w->header_parse_last_size = 0;
904
web_client_disable_wait_receive(w);
905
return HTTP_VALIDATION_NOT_SUPPORTED;
906
}
907
1092
- encoded_url = s;
908
+ // find the SPACE + "HTTP/"
909
+ while(*s) {
910
+ // find the next space
911
+ while (*s && *s != ' ') s++;
912
+
913
+ // is it SPACE + "HTTP/" ?
914
+ if(*s && !strncmp(s, " HTTP/", 6)) break;
915
+ else s++;
916
+ }
917
1094
- s = web_client_find_protocol(w,s);
918
// incomplete requests
919
if(unlikely(!*s)) {
920
web_client_enable_wait_receive(w);
@@ -1101,40 +924,64 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
924
// we have the end of encoded_url - remember it
925
char *ue = s;
926
1104
- *ue = '\0';
1105
- url_decode_r(w->decoded_url, encoded_url, NETDATA_WEB_REQUEST_URL_SIZE + 1);
927
+ // make sure we have complete request
928
+ // complete requests contain: \r\n\r\n
929
+ while(*s) {
930
+ // find a line feed
931
+ while(*s && *s++ != '\r');
932
+
933
+ // did we reach the end?
934
+ if(unlikely(!*s)) break;
935
1107
- web_client_split_path_query(w);
1108
- *ue = ' ';
1109
- web_client_parse_headers(w,s);
936
+ // is it \r\n ?
937
+ if(likely(*s++ == '\n')) {
938
1111
- // copy the URL - we are going to overwrite parts of it
1112
- // TODO -- ideally we we should avoid copying buffers around
1113
- strncpyz(w->last_url, w->decoded_url, NETDATA_WEB_REQUEST_URL_SIZE);
939
+ // is it again \r\n ? (header end)
940
+ if(unlikely(*s == '\r' && s[1] == '\n')) {
941
+ // a valid complete HTTP request found
942
943
+ *ue = '\0';
944
+ url_decode_r(w->decoded_url, encoded_url, NETDATA_WEB_REQUEST_URL_SIZE + 1);
945
+ *ue = ' ';
946
+
947
+ // copy the URL - we are going to overwrite parts of it
948
+ // TODO -- ideally we we should avoid copying buffers around
949
+ strncpyz(w->last_url, w->decoded_url, NETDATA_WEB_REQUEST_URL_SIZE);
950
#ifdef ENABLE_HTTPS
1116
- if ((!web_client_check_unix(w)) && (netdata_srv_ctx) ) {
1117
- if ((w->ssl.conn) && ((w->ssl.flags & NETDATA_SSL_NO_HANDSHAKE) && (netdata_use_ssl_on_http & NETDATA_SSL_FORCE) && (w->mode != WEB_CLIENT_MODE_STREAM)) ) {
1118
- w->header_parse_tries = 0;
1119
- w->header_parse_last_size = 0;
1120
- web_client_disable_wait_receive(w);
1121
- return HTTP_VALIDATION_REDIRECT;
951
+ if ( (!web_client_check_unix(w)) && (netdata_srv_ctx) ) {
952
+ if ((w->ssl.conn) && ((w->ssl.flags & NETDATA_SSL_NO_HANDSHAKE) && (netdata_use_ssl_on_http & NETDATA_SSL_FORCE) && (w->mode != WEB_CLIENT_MODE_STREAM)) ) {
953
+ w->header_parse_tries = 0;
954
+ w->header_parse_last_size = 0;
955
+ web_client_disable_wait_receive(w);
956
+ return HTTP_VALIDATION_REDIRECT;
957
+ }
958
+ }
959
+#endif
960
+
961
+ w->header_parse_tries = 0;
962
+ w->header_parse_last_size = 0;
963
+ web_client_disable_wait_receive(w);
964
+ return HTTP_VALIDATION_OK;
965
+ }
966
+
967
+ // another header line
968
+ s = http_header_parse(w, s,
969
+ (w->mode == WEB_CLIENT_MODE_STREAM) // parse user agent
970
+ );
971
}
972
}
1124
-#endif
973
1126
- w->header_parse_tries = 0;
1127
- w->header_parse_last_size = 0;
1128
- web_client_disable_wait_receive(w);
1129
- return HTTP_VALIDATION_OK;
974
+ // incomplete request
975
+ web_client_enable_wait_receive(w);
976
+ return HTTP_VALIDATION_INCOMPLETE;
977
}
978
979
static inline ssize_t web_client_send_data(struct web_client *w,const void *buf,size_t len, int flags)
980
{
981
ssize_t bytes;
982
#ifdef ENABLE_HTTPS
1136
- if ((!web_client_check_unix(w)) && (netdata_srv_ctx)) {
1137
- if ((w->ssl.conn) && (!w->ssl.flags)) {
983
+ if ( (!web_client_check_unix(w)) && (netdata_srv_ctx) ) {
984
+ if ( ( w->ssl.conn ) && ( !w->ssl.flags ) ){
985
bytes = SSL_write(w->ssl.conn,buf, len) ;
986
} else {
987
bytes = send(w->ofd,buf, len , flags);
@@ -1255,7 +1102,7 @@ static inline void web_client_send_http_header(struct web_client *w) {
1102
buffer_sprintf(w->response.header_output,
1103
"Cache-Control: %s\r\n"
1104
"Expires: %s\r\n",
1258
- (w->response.data->options & WB_CONTENT_NO_CACHEABLE)?"no-cache":"public",
1105
+ (w->response.data->options & WB_CONTENT_NO_CACHEABLE)?"no-cache, no-store, must-revalidate\r\nPragma: no-cache":"public",
1106
edate);
1107
}
1108
@@ -1296,8 +1143,8 @@ static inline void web_client_send_http_header(struct web_client *w) {
1143
size_t count = 0;
1144
ssize_t bytes;
1145
#ifdef ENABLE_HTTPS
1299
- if ((!web_client_check_unix(w)) && (netdata_srv_ctx)) {
1300
- if ((w->ssl.conn) && (!w->ssl.flags)) {
1146
+ if ( (!web_client_check_unix(w)) && (netdata_srv_ctx) ) {
1147
+ if ( ( w->ssl.conn ) && ( !w->ssl.flags ) ){
1148
while((bytes = SSL_write(w->ssl.conn, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output))) < 0) {
1149
count++;
1150
if(count > 100 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
@@ -1366,52 +1213,21 @@ static inline int web_client_switch_host(RRDHOST *host, struct web_client *w, ch
1213
return 400;
1214
}
1215
1369
- char *tok = strchr(url,'/');
1370
- if (tok) {
1371
- w->switch_host = 1;
1372
- debug(D_WEB_CLIENT, "%llu: Searching for host with name '%s'.", w->id, url);
1216
+ char *tok = mystrsep(&url, "/");
1217
+ if(tok && *tok) {
1218
+ debug(D_WEB_CLIENT, "%llu: Searching for host with name '%s'.", w->id, tok);
1219
1220
// copy the URL, we need it to serve files
1221
w->last_url[0] = '/';
1376
- if(*(tok+1) != ' ') {
1377
- strncpyz(&w->last_url[1], tok+1, NETDATA_WEB_REQUEST_URL_SIZE - 1);
1378
- char *enddir;
1379
- if (w->total_params) {
1380
- enddir = strchr(tok+1,'/');
1381
- if (enddir) {
1382
- char *moveme = strchr(enddir,'?');
1383
- if (moveme) {
1384
- web_client_set_directory(w,tok+1,enddir,moveme);
1385
- }
1386
- }
1387
- else {
1388
- w->directory.body = tok;
1389
- w->directory.length = strlen(tok);
1390
- }
1391
- } else {
1392
- enddir = strchr(tok+1,'/');
1393
- if(enddir) {
1394
- w->directory.body = tok + 1;
1395
- w->directory.length = enddir - tok - 1;
1396
- } else {
1397
- if (!strlen(tok + 1)) {
1398
- w->directory.body = tok;
1399
- w->directory.length = 1;
1400
- }
1401
- }
1402
- }
1403
- }
1404
- else {
1405
- w->last_url[1] = '\0';
1406
- }
1407
- *tok = 0x00;
1408
- uint32_t hash = simple_hash(url);
1222
+ if(url && *url) strncpyz(&w->last_url[1], url, NETDATA_WEB_REQUEST_URL_SIZE - 1);
1223
+ else w->last_url[1] = '\0';
1224
+
1225
+ uint32_t hash = simple_hash(tok);
1226
1410
- host = rrdhost_find_by_hostname(url, hash);
1411
- if(!host) host = rrdhost_find_by_guid(url, hash);
1412
- *tok = '/';
1227
+ host = rrdhost_find_by_hostname(tok, hash);
1228
+ if(!host) host = rrdhost_find_by_guid(tok, hash);
1229
1414
- if(host) return web_client_process_url(host, w, tok);
1230
+ if(host) return web_client_process_url(host, w, url);
1231
}
1232
1233
buffer_flush(w->response.data);
@@ -1442,21 +1258,20 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch
1258
#endif
1259
}
1260
1445
- if (w->path.length > 1) {
1446
- char *cmp = w->directory.body;
1447
- size_t len = w->directory.length;
1448
- uint32_t hash = simple_nhash(cmp,len);
1449
- debug(D_WEB_CLIENT, "%llu: Processing command '%s'.", w->id, w->command.body);
1261
+ char *tok = mystrsep(&url, "/?");
1262
+ if(likely(tok && *tok)) {
1263
+ uint32_t hash = simple_hash(tok);
1264
+ debug(D_WEB_CLIENT, "%llu: Processing command '%s'.", w->id, tok);
1265
1451
- if(unlikely(hash == hash_api && strncmp(cmp, "api",len) == 0)) { // current API
1266
+ if(unlikely(hash == hash_api && strcmp(tok, "api") == 0)) { // current API
1267
debug(D_WEB_CLIENT_ACCESS, "%llu: API request ...", w->id);
1268
return check_host_and_call(host, w, url, web_client_api_request);
1269
}
1455
- else if(unlikely(hash == hash_host && strncmp(cmp, "host",len) == 0)) { // host switching
1270
+ else if(unlikely(hash == hash_host && strcmp(tok, "host") == 0)) { // host switching
1271
debug(D_WEB_CLIENT_ACCESS, "%llu: host switch request ...", w->id);
1457
- return web_client_switch_host(host, w, cmp+5);
1272
+ return web_client_switch_host(host, w, url);
1273
}
1459
- else if(unlikely(hash == hash_netdata_conf && strncmp(cmp, "netdata.conf",len) == 0)) { // current API
1274
+ else if(unlikely(hash == hash_netdata_conf && strcmp(tok, "netdata.conf") == 0)) { // netdata.conf
1275
if(unlikely(!web_client_can_access_netdataconf(w)))
1276
return web_client_permission_denied(w);
1277
@@ -1467,7 +1282,7 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch
1282
return 200;
1283
}
1284
#ifdef NETDATA_INTERNAL_CHECKS
1470
- else if(unlikely(hash == hash_exit && strncmp(cmp, "exit",len) == 0)) {
1285
+ else if(unlikely(hash == hash_exit && strcmp(tok, "exit") == 0)) {
1286
if(unlikely(!web_client_can_access_netdataconf(w)))
1287
return web_client_permission_denied(w);
1288
@@ -1483,50 +1298,47 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch
1298
netdata_cleanup_and_exit(0);
1299
return 200;
1300
}
1486
- else if(unlikely(hash == hash_debug && strncmp(cmp, "debug",len) == 0)) {
1301
+ else if(unlikely(hash == hash_debug && strcmp(tok, "debug") == 0)) {
1302
if(unlikely(!web_client_can_access_netdataconf(w)))
1303
return web_client_permission_denied(w);
1304
1305
buffer_flush(w->response.data);
1306
1307
// get the name of the data to show
1493
- char *tok = mystrsep(&url, "/?");
1494
- if(likely(tok && *tok)) {
1495
- tok = mystrsep(&url, "&");
1496
- if(tok && *tok) {
1497
- debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
1498
-
1499
- // do we have such a data set?
1500
- RRDSET *st = rrdset_find_byname(host, tok);
1501
- if(!st) st = rrdset_find(host, tok);
1502
- if(!st) {
1503
- w->response.data->contenttype = CT_TEXT_HTML;
1504
- buffer_strcat(w->response.data, "Chart is not found: ");
1505
- buffer_strcat_htmlescape(w->response.data, tok);
1506
- debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok);
1507
- return 404;
1508
- }
1509
-
1510
- debug_flags |= D_RRD_STATS;
1511
-
1512
- if(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))
1513
- rrdset_flag_clear(st, RRDSET_FLAG_DEBUG);
1514
- else
1515
- rrdset_flag_set(st, RRDSET_FLAG_DEBUG);
1516
-
1308
+ tok = mystrsep(&url, "&");
1309
+ if(tok && *tok) {
1310
+ debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
1311
+
1312
+ // do we have such a data set?
1313
+ RRDSET *st = rrdset_find_byname(host, tok);
1314
+ if(!st) st = rrdset_find(host, tok);
1315
+ if(!st) {
1316
w->response.data->contenttype = CT_TEXT_HTML;
1518
- buffer_sprintf(w->response.data, "Chart has now debug %s: ", rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?"enabled":"disabled");
1317
+ buffer_strcat(w->response.data, "Chart is not found: ");
1318
buffer_strcat_htmlescape(w->response.data, tok);
1520
- debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?"enabled":"disabled");
1521
- return 200;
1319
+ debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok);
1320
+ return 404;
1321
}
1322
+
1323
+ debug_flags |= D_RRD_STATS;
1324
+
1325
+ if(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))
1326
+ rrdset_flag_clear(st, RRDSET_FLAG_DEBUG);
1327
+ else
1328
+ rrdset_flag_set(st, RRDSET_FLAG_DEBUG);
1329
+
1330
+ w->response.data->contenttype = CT_TEXT_HTML;
1331
+ buffer_sprintf(w->response.data, "Chart has now debug %s: ", rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?"enabled":"disabled");
1332
+ buffer_strcat_htmlescape(w->response.data, tok);
1333
+ debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?"enabled":"disabled");
1334
+ return 200;
1335
}
1336
1337
buffer_flush(w->response.data);
1338
buffer_strcat(w->response.data, "debug which chart?\r\n");
1339
return 400;
1340
}
1529
- else if(unlikely(hash == hash_mirror && strncmp(cmp, "mirror",len) == 0)) {
1341
+ else if(unlikely(hash == hash_mirror && strcmp(tok, "mirror") == 0)) {
1342
if(unlikely(!web_client_can_access_netdataconf(w)))
1343
return web_client_permission_denied(w);
1344
@@ -1543,17 +1355,12 @@ static inline int web_client_process_url(RRDHOST *host, struct web_client *w, ch
1355
#endif /* NETDATA_INTERNAL_CHECKS */
1356
}
1357
1546
- w->switch_host = 0;
1547
- char *tok = mystrsep(&url, "/?");
1548
- (void)tok;
1549
-
1358
char filename[FILENAME_MAX+1];
1359
url = filename;
1360
strncpyz(filename, w->last_url, FILENAME_MAX);
1361
tok = mystrsep(&url, "?");
1362
buffer_flush(w->response.data);
1555
-
1556
- return mysendfile(w, (w->path.length > 1)?tok:"/");
1363
+ return mysendfile(w, (tok && *tok)?tok:"/");
1364
}
1365
1366
void web_client_process_request(struct web_client *w) {
@@ -2005,8 +1812,8 @@ ssize_t web_client_receive(struct web_client *w)
1812
buffer_need_bytes(w->response.data, NETDATA_WEB_REQUEST_RECEIVE_SIZE);
1813
1814
#ifdef ENABLE_HTTPS
2008
- if ((!web_client_check_unix(w)) && (netdata_srv_ctx)) {
2009
- if ((w->ssl.conn) && (!w->ssl.flags)) {
1815
+ if ( (!web_client_check_unix(w)) && (netdata_srv_ctx) ) {
1816
+ if ( ( w->ssl.conn ) && (!w->ssl.flags)) {
1817
bytes = SSL_read(w->ssl.conn, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1));
1818
}else {
1819
bytes = recv(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1), MSG_DONTWAIT);
web/server/web_client.h
-12
@@ -128,18 +128,6 @@ struct web_client {
128
char client_port[NI_MAXSERV+1];
129
130
char decoded_url[NETDATA_WEB_REQUEST_URL_SIZE + 1]; // we decode the URL in this buffer
131
- size_t decoded_length;
132
- struct web_fields path;
133
- struct web_fields directory;
134
- struct web_fields query_string;
135
- struct web_fields version;
136
- struct web_fields command;
137
- struct web_fields protocol;
138
- struct web_fields param_name[WEB_FIELDS_MAX];
139
- struct web_fields param_values[WEB_FIELDS_MAX];
140
- uint32_t total_params;
141
- int switch_host;
142
-
131
char last_url[NETDATA_WEB_REQUEST_URL_SIZE+1]; // we keep a copy of the decoded URL here
132
char host[256];
133