Utf8 Badge Fix And URL Parser International Support (initial) (#6426)
#### Summary Fixes #3117 Additionally it adds support for UTF-8 in URL parser (as it should). Label sizes now are updated by browser with JavaScript (although guess is still calculated by verdana11_widths with minor improvements) #### Component Name API/Badges, LibNetData/URL #### Additional Information It was found that not only verdana11_widths need to be updated but the url parser replaces international characters with spaces (one space per each byte of multibyte character). Therefore I update both to support international chars.
Timo committed
Jul 24, 2019 at 14:32 UTC
19f1bd14debbc3654f156d05e44b792efc45d3d3
8 files changed
+226
-164
CMakeLists.txt
+1
@@ -320,6 +320,7 @@ set(LIBNETDATA_FILES
320
libnetdata/json/jsmn.h
321
libnetdata/health/health.c
322
libnetdata/health/health.h
323
+ libnetdata/string/utf8.h
324
libnetdata/socket/security.c
325
libnetdata/socket/security.h)
326
Makefile.am
+1
@@ -167,6 +167,7 @@ LIBNETDATA_FILES = \
167
libnetdata/json/jsmn.h \
168
libnetdata/health/health.c \
169
libnetdata/health/health.h \
170
+ libnetdata/string/utf8.h \
171
$(NULL)
172
173
APPS_PLUGIN_FILES = \
libnetdata/libnetdata.h
+1
@@ -313,5 +313,6 @@ extern char *netdata_configured_host_prefix;
313
#include "url/url.h"
314
#include "json/json.h"
315
#include "health/health.h"
316
+#include "string/utf8.h"
317
318
#endif // NETDATA_LIB_H
libnetdata/string/utf8.h
new
+9
@@ -0,0 +1,9 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#ifndef NETDATA_STRING_UTF8_H
4
+#define NETDATA_STRING_UTF8_H 1
5
+
6
+#define IS_UTF8_BYTE(x) (x & 0x80)
7
+#define IS_UTF8_STARTBYTE(x) (IS_UTF8_BYTE(x)&&(x & 0x40))
8
+
9
+#endif /* NETDATA_STRING_UTF8_H */
libnetdata/url/url.c
+141
-3
@@ -52,6 +52,125 @@ char *url_decode(char *str) {
52
return url_decode_r(buf, str, size);
53
}
54
55
+//decode %XX character or return 0 if cannot
56
+char url_percent_escape_decode(char *s) {
57
+ if(likely(s[1] && s[2]))
58
+ return from_hex(s[1]) << 4 | from_hex(s[2]);
59
+ return 0;
60
+}
61
+
62
+//this (utf8 string related) should be moved in separate file in future
63
+char url_utf8_get_byte_length(char c) {
64
+ if(!IS_UTF8_BYTE(c))
65
+ return 1;
66
+
67
+ char length = 0;
68
+ while(likely(c & 0x80)) {
69
+ length++;
70
+ c <<= 1;
71
+ }
72
+ //4 byte is max size for UTF-8 char
73
+ //10XX XXXX is not valid character -> check length == 1
74
+ if(length > 4 || length == 1)
75
+ return -1;
76
+
77
+ return length;
78
+}
79
+
80
+//decode % encoded UTF-8 characters and copy them to *d
81
+//return count of bytes written to *d
82
+char url_decode_multibyte_utf8(char *s, char *d, char *d_end) {
83
+ char first_byte = url_percent_escape_decode(s);
84
+
85
+ if(unlikely(!first_byte || !IS_UTF8_STARTBYTE(first_byte)))
86
+ return 0;
87
+
88
+ char byte_length = url_utf8_get_byte_length(first_byte);
89
+
90
+ if(unlikely(byte_length <= 0 || d+byte_length >= d_end))
91
+ return 0;
92
+
93
+ char to_read = byte_length;
94
+ while(to_read > 0) {
95
+ char c = url_percent_escape_decode(s);
96
+
97
+ if(unlikely( !IS_UTF8_BYTE(c) ))
98
+ return 0;
99
+ if((to_read != byte_length) && IS_UTF8_STARTBYTE(c))
100
+ return 0;
101
+
102
+ *d++ = c;
103
+ s+=3;
104
+ to_read--;
105
+ }
106
+
107
+ return byte_length;
108
+}
109
+
110
+/*
111
+ * The utf8_check() function scans the '\0'-terminated string starting
112
+ * at s. It returns a pointer to the first byte of the first malformed
113
+ * or overlong UTF-8 sequence found, or NULL if the string contains
114
+ * only correct UTF-8. It also spots UTF-8 sequences that could cause
115
+ * trouble if converted to UTF-16, namely surrogate characters
116
+ * (U+D800..U+DFFF) and non-Unicode positions (U+FFFE..U+FFFF). This
117
+ * routine is very likely to find a malformed sequence if the input
118
+ * uses any other encoding than UTF-8. It therefore can be used as a
119
+ * very effective heuristic for distinguishing between UTF-8 and other
120
+ * encodings.
121
+ *
122
+ * Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/> -- 2005-03-30
123
+ * License: http://www.cl.cam.ac.uk/~mgk25/short-license.html
124
+ */
125
+
126
+unsigned char *utf8_check(unsigned char *s)
127
+{
128
+ while (*s)
129
+ {
130
+ if (*s < 0x80)
131
+ /* 0xxxxxxx */
132
+ s++;
133
+ else if ((s[0] & 0xe0) == 0xc0)
134
+ {
135
+ /* 110XXXXx 10xxxxxx */
136
+ if ((s[1] & 0xc0) != 0x80 ||
137
+ (s[0] & 0xfe) == 0xc0) /* overlong? */
138
+ return s;
139
+ else
140
+ s += 2;
141
+ }
142
+ else if ((s[0] & 0xf0) == 0xe0)
143
+ {
144
+ /* 1110XXXX 10Xxxxxx 10xxxxxx */
145
+ if ((s[1] & 0xc0) != 0x80 ||
146
+ (s[2] & 0xc0) != 0x80 ||
147
+ (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || /* overlong? */
148
+ (s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || /* surrogate? */
149
+ (s[0] == 0xef && s[1] == 0xbf &&
150
+ (s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */
151
+ return s;
152
+ else
153
+ s += 3;
154
+ }
155
+ else if ((s[0] & 0xf8) == 0xf0)
156
+ {
157
+ /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */
158
+ if ((s[1] & 0xc0) != 0x80 ||
159
+ (s[2] & 0xc0) != 0x80 ||
160
+ (s[3] & 0xc0) != 0x80 ||
161
+ (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || /* overlong? */
162
+ (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) /* > U+10FFFF? */
163
+ return s;
164
+ else
165
+ s += 4;
166
+ }
167
+ else
168
+ return s;
169
+ }
170
+
171
+ return NULL;
172
+}
173
+
174
char *url_decode_r(char *to, char *url, size_t size) {
175
char *s = url, // source
176
*d = to, // destination
@@ -59,12 +178,24 @@ char *url_decode_r(char *to, char *url, size_t size) {
178
179
while(*s && d < e) {
180
if(unlikely(*s == '%')) {
62
- if(likely(s[1] && s[2])) {
63
- char t = from_hex(s[1]) << 4 | from_hex(s[2]);
181
+ char t = url_percent_escape_decode(s);
182
+ if(IS_UTF8_BYTE(t)) {
183
+ char bytes_written = url_decode_multibyte_utf8(s, d, e);
184
+ if(likely(bytes_written)){
185
+ d += bytes_written;
186
+ s += (bytes_written * 3)-1;
187
+ }
188
+ else {
189
+ goto fail_cleanup;
190
+ }
191
+ }
192
+ else if(likely(t) && isprint(t)) {
193
// avoid HTTP header injection
65
- *d++ = (char)((isprint(t))? t : ' ');
194
+ *d++ = t;
195
s += 2;
196
}
197
+ else
198
+ goto fail_cleanup;
199
}
200
else if(unlikely(*s == '+'))
201
*d++ = ' ';
@@ -77,5 +208,12 @@ char *url_decode_r(char *to, char *url, size_t size) {
208
209
*d = '\0';
210
211
+ if(unlikely( utf8_check(to) )) //NULL means sucess here
212
+ return NULL;
213
+
214
return to;
215
+
216
+fail_cleanup:
217
+ *d = '\0';
218
+ return NULL;
219
}
web/api/badges/web_buffer_svg.c
+58
-158
@@ -11,7 +11,7 @@
11
* https://github.com/badges/shields/blob/master/measure-text.js
12
*/
13
14
-static double verdana11_widths[256] = {
14
+static double verdana11_widths[128] = {
15
[0] = 0.0,
16
[1] = 0.0,
17
[2] = 0.0,
@@ -139,157 +139,36 @@ static double verdana11_widths[256] = {
139
[124] = 4.9951171875, // |
140
[125] = 6.982421875, // }
141
[126] = 9.001953125, // ~
142
- [127] = 0.0,
143
- [128] = 0.0,
144
- [129] = 0.0,
145
- [130] = 0.0,
146
- [131] = 0.0,
147
- [132] = 0.0,
148
- [133] = 0.0,
149
- [134] = 0.0,
150
- [135] = 0.0,
151
- [136] = 0.0,
152
- [137] = 0.0,
153
- [138] = 0.0,
154
- [139] = 0.0,
155
- [140] = 0.0,
156
- [141] = 0.0,
157
- [142] = 0.0,
158
- [143] = 0.0,
159
- [144] = 0.0,
160
- [145] = 0.0,
161
- [146] = 0.0,
162
- [147] = 0.0,
163
- [148] = 0.0,
164
- [149] = 0.0,
165
- [150] = 0.0,
166
- [151] = 0.0,
167
- [152] = 0.0,
168
- [153] = 0.0,
169
- [154] = 0.0,
170
- [155] = 0.0,
171
- [156] = 0.0,
172
- [157] = 0.0,
173
- [158] = 0.0,
174
- [159] = 0.0,
175
- [160] = 0.0,
176
- [161] = 0.0,
177
- [162] = 0.0,
178
- [163] = 0.0,
179
- [164] = 0.0,
180
- [165] = 0.0,
181
- [166] = 0.0,
182
- [167] = 0.0,
183
- [168] = 0.0,
184
- [169] = 0.0,
185
- [170] = 0.0,
186
- [171] = 0.0,
187
- [172] = 0.0,
188
- [173] = 0.0,
189
- [174] = 0.0,
190
- [175] = 0.0,
191
- [176] = 0.0,
192
- [177] = 0.0,
193
- [178] = 0.0,
194
- [179] = 0.0,
195
- [180] = 0.0,
196
- [181] = 0.0,
197
- [182] = 0.0,
198
- [183] = 0.0,
199
- [184] = 0.0,
200
- [185] = 0.0,
201
- [186] = 0.0,
202
- [187] = 0.0,
203
- [188] = 0.0,
204
- [189] = 0.0,
205
- [190] = 0.0,
206
- [191] = 0.0,
207
- [192] = 0.0,
208
- [193] = 0.0,
209
- [194] = 0.0,
210
- [195] = 0.0,
211
- [196] = 0.0,
212
- [197] = 0.0,
213
- [198] = 0.0,
214
- [199] = 0.0,
215
- [200] = 0.0,
216
- [201] = 0.0,
217
- [202] = 0.0,
218
- [203] = 0.0,
219
- [204] = 0.0,
220
- [205] = 0.0,
221
- [206] = 0.0,
222
- [207] = 0.0,
223
- [208] = 0.0,
224
- [209] = 0.0,
225
- [210] = 0.0,
226
- [211] = 0.0,
227
- [212] = 0.0,
228
- [213] = 0.0,
229
- [214] = 0.0,
230
- [215] = 0.0,
231
- [216] = 0.0,
232
- [217] = 0.0,
233
- [218] = 0.0,
234
- [219] = 0.0,
235
- [220] = 0.0,
236
- [221] = 0.0,
237
- [222] = 0.0,
238
- [223] = 0.0,
239
- [224] = 0.0,
240
- [225] = 0.0,
241
- [226] = 0.0,
242
- [227] = 0.0,
243
- [228] = 0.0,
244
- [229] = 0.0,
245
- [230] = 0.0,
246
- [231] = 0.0,
247
- [232] = 0.0,
248
- [233] = 0.0,
249
- [234] = 0.0,
250
- [235] = 0.0,
251
- [236] = 0.0,
252
- [237] = 0.0,
253
- [238] = 0.0,
254
- [239] = 0.0,
255
- [240] = 0.0,
256
- [241] = 0.0,
257
- [242] = 0.0,
258
- [243] = 0.0,
259
- [244] = 0.0,
260
- [245] = 0.0,
261
- [246] = 0.0,
262
- [247] = 0.0,
263
- [248] = 0.0,
264
- [249] = 0.0,
265
- [250] = 0.0,
266
- [251] = 0.0,
267
- [252] = 0.0,
268
- [253] = 0.0,
269
- [254] = 0.0,
270
- [255] = 0.0
142
+ [127] = 0.0
143
};
144
145
// find the width of the string using the verdana 11points font
274
-// re-write the string in place, skiping zero-length characters
275
-static inline double verdana11_width(char *s) {
146
+static inline double verdana11_width(const char *s, float em_size) {
147
double w = 0.0;
277
- char *d = s;
148
149
while(*s) {
280
- double t = verdana11_widths[(unsigned char)*s];
281
- if(t == 0.0)
150
+ // if UTF8 multibyte char found and guess it's width equal 1em
151
+ // as label width will be updated with JavaScript this is not so important
152
+
153
+ // TODO: maybe move UTF8 functions from url.c to separate util in libnetdata
154
+ // then use url_utf8_get_byte_length etc.
155
+ if(IS_UTF8_STARTBYTE(*s)) {
156
s++;
157
+ while(IS_UTF8_BYTE(*s) && !IS_UTF8_STARTBYTE(*s)){
158
+ s++;
159
+ }
160
+ w += em_size;
161
+ }
162
else {
284
- w += t + VERDANA_KERNING;
285
- if(d != s)
286
- *d++ = *s++;
287
- else
288
- d = ++s;
163
+ if(likely(!(*s & 0x80))){ // Byte 1XXX XXXX is not valid in UTF8
164
+ double t = verdana11_widths[(unsigned char)*s];
165
+ if(t != 0.0)
166
+ w += t + VERDANA_KERNING;
167
+ }
168
+ s++;
169
}
170
}
171
292
- *d = '\0';
172
w -= VERDANA_KERNING;
173
w += VERDANA_PADDING;
174
return w;
@@ -810,8 +689,7 @@ static inline void calc_colorz(const char *color, char *final, size_t len, calcu
689
#define COLOR_STRING_SIZE 100
690
691
void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, int scale, uint32_t options) {
813
- char label_buffer[LABEL_STRING_SIZE + 1]
814
- , value_color_buffer[COLOR_STRING_SIZE + 1]
692
+ char value_color_buffer[COLOR_STRING_SIZE + 1]
693
, value_string[VALUE_STRING_SIZE + 1]
694
, label_escaped[LABEL_STRING_SIZE + 1]
695
, value_escaped[VALUE_STRING_SIZE + 1]
@@ -831,14 +709,11 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
709
calc_colorz(value_color, value_color_buffer, COLOR_STRING_SIZE, value);
710
format_value_and_unit(value_string, VALUE_STRING_SIZE, (options & RRDR_OPTION_DISPLAY_ABS)?calculated_number_fabs(value):value, units, precision);
711
834
- // we need to copy the label, since verdana11_width may write to it
835
- strncpyz(label_buffer, label, LABEL_STRING_SIZE);
836
-
837
- label_width = verdana11_width(label_buffer) + (BADGE_HORIZONTAL_PADDING * 2);
838
- value_width = verdana11_width(value_string) + (BADGE_HORIZONTAL_PADDING * 2);
712
+ label_width = verdana11_width(label, font_size) + (BADGE_HORIZONTAL_PADDING * 2);
713
+ value_width = verdana11_width(value_string, font_size) + (BADGE_HORIZONTAL_PADDING * 2);
714
total_width = label_width + value_width;
715
841
- escape_xmlz(label_escaped, label_buffer, LABEL_STRING_SIZE);
716
+ escape_xmlz(label_escaped, label, LABEL_STRING_SIZE);
717
escape_xmlz(value_escaped, value_string, VALUE_STRING_SIZE);
718
escape_xmlz(label_color_escaped, color_map(label_color), COLOR_STRING_SIZE);
719
escape_xmlz(value_color_escaped, color_map(value_color_buffer), COLOR_STRING_SIZE);
@@ -862,19 +737,43 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
737
"<stop offset=\"1\" stop-opacity=\".1\"/>"
738
"</linearGradient>"
739
"<mask id=\"round\">"
865
- "<rect width=\"%0.2f\" height=\"%0.2f\" rx=\"%0.2f\" fill=\"#fff\"/>"
740
+ "<rect class=\"bdge-ttl-width\" width=\"%0.2f\" height=\"%0.2f\" rx=\"%0.2f\" fill=\"#fff\"/>"
741
"</mask>"
742
"<g mask=\"url(#round)\">"
868
- "<rect width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>"
869
- "<rect x=\"%0.2f\" width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>"
870
- "<rect width=\"%0.2f\" height=\"%0.2f\" fill=\"url(#smooth)\"/>"
743
+ "<rect class=\"bdge-rect-lbl\" width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>"
744
+ "<rect class=\"bdge-rect-val\" x=\"%0.2f\" width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>"
745
+ "<rect class=\"bdge-ttl-width\" width=\"%0.2f\" height=\"%0.2f\" fill=\"url(#smooth)\"/>"
746
"</g>"
747
"<g fill=\"#fff\" text-anchor=\"middle\" font-family=\"DejaVu Sans,Verdana,Geneva,sans-serif\" font-size=\"%0.2f\">"
873
- "<text x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\">%s</text>"
874
- "<text x=\"%0.2f\" y=\"%0.0f\">%s</text>"
875
- "<text x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\">%s</text>"
876
- "<text x=\"%0.2f\" y=\"%0.0f\">%s</text>"
748
+ "<text class=\"bdge-lbl-lbl\" x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\">%s</text>"
749
+ "<text class=\"bdge-lbl-lbl\" x=\"%0.2f\" y=\"%0.0f\">%s</text>"
750
+ "<text class=\"bdge-lbl-val\" x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\">%s</text>"
751
+ "<text class=\"bdge-lbl-val\" x=\"%0.2f\" y=\"%0.0f\">%s</text>"
752
"</g>"
753
+ "<script type=\"text/javascript\">"
754
+ "var bdg_horiz_padding = %d;"
755
+ "function netdata_bdge_each(list, attr, value){"
756
+ "Array.prototype.forEach.call(list, function(el){"
757
+ "el.setAttribute(attr, value);"
758
+ "});"
759
+ "};"
760
+ "var this_svg = document.currentScript.closest(\"svg\");"
761
+ "var elem_lbl = this_svg.getElementsByClassName(\"bdge-lbl-lbl\");"
762
+ "var elem_val = this_svg.getElementsByClassName(\"bdge-lbl-val\");"
763
+ "var lbl_size = elem_lbl[0].getBBox();"
764
+ "var val_size = elem_val[0].getBBox();"
765
+ "var width_total = lbl_size.width + bdg_horiz_padding*2;"
766
+ "this_svg.getElementsByClassName(\"bdge-rect-lbl\")[0].setAttribute(\"width\", width_total);"
767
+ "netdata_bdge_each(elem_lbl, \"x\", (lbl_size.width / 2) + bdg_horiz_padding);"
768
+ "netdata_bdge_each(elem_val, \"x\", width_total + (val_size.width / 2) + bdg_horiz_padding);"
769
+ "var val_rect = this_svg.getElementsByClassName(\"bdge-rect-val\")[0];"
770
+ "val_rect.setAttribute(\"width\", val_size.width + bdg_horiz_padding*2);"
771
+ "val_rect.setAttribute(\"x\", width_total);"
772
+ "width_total += val_size.width + bdg_horiz_padding*2;"
773
+ "var width_update_elems = this_svg.getElementsByClassName(\"bdge-ttl-width\");"
774
+ "netdata_bdge_each(width_update_elems, \"width\", width_total);"
775
+ "this_svg.setAttribute(\"width\", width_total);"
776
+ "</script>"
777
"</svg>",
778
total_width, height,
779
total_width, height, round_corner,
@@ -885,7 +784,8 @@ void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const ch
784
label_width / 2, ceil(height - text_offset), label_escaped,
785
label_width / 2, ceil(height - text_offset - 1.0), label_escaped,
786
label_width + value_width / 2 -1, ceil(height - text_offset), value_escaped,
888
- label_width + value_width / 2 -1, ceil(height - text_offset - 1.0), value_escaped);
787
+ label_width + value_width / 2 -1, ceil(height - text_offset - 1.0), value_escaped,
788
+ BADGE_HORIZONTAL_PADDING );
789
}
790
791
int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url) {
web/server/web_client.c
+12
-3
@@ -821,6 +821,7 @@ static inline char *http_header_parse(struct web_client *w, char *s, int parse_u
821
typedef enum {
822
HTTP_VALIDATION_OK,
823
HTTP_VALIDATION_NOT_SUPPORTED,
824
+ HTTP_VALIDATION_MALFORMED_URL,
825
#ifdef ENABLE_HTTPS
826
HTTP_VALIDATION_INCOMPLETE,
827
HTTP_VALIDATION_REDIRECT
@@ -941,7 +942,8 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
942
// a valid complete HTTP request found
943
944
*ue = '\0';
944
- url_decode_r(w->decoded_url, encoded_url, NETDATA_WEB_REQUEST_URL_SIZE + 1);
945
+ if(!url_decode_r(w->decoded_url, encoded_url, NETDATA_WEB_REQUEST_URL_SIZE + 1))
946
+ return HTTP_VALIDATION_MALFORMED_URL;
947
*ue = ' ';
948
949
// copy the URL - we are going to overwrite parts of it
@@ -1424,7 +1426,7 @@ void web_client_process_request(struct web_client *w) {
1426
1427
buffer_flush(w->response.data);
1428
buffer_sprintf(w->response.data, "Received request is too big (%zu bytes).\r\n", w->response.data->len);
1427
- w->response.code = 400;
1429
+ w->response.code = HTTP_RESPONSE_BAD_REQUEST;
1430
}
1431
else {
1432
// wait for more data
@@ -1441,12 +1443,19 @@ void web_client_process_request(struct web_client *w) {
1443
break;
1444
}
1445
#endif
1446
+ case HTTP_VALIDATION_MALFORMED_URL:
1447
+ debug(D_WEB_CLIENT_ACCESS, "%llu: URL parsing failed (malformed URL). Cannot understand '%s'.", w->id, w->response.data->buffer);
1448
+
1449
+ buffer_flush(w->response.data);
1450
+ buffer_strcat(w->response.data, "URL not valid. I don't understand you...\r\n");
1451
+ w->response.code = HTTP_RESPONSE_BAD_REQUEST;
1452
+ break;
1453
case HTTP_VALIDATION_NOT_SUPPORTED:
1454
debug(D_WEB_CLIENT_ACCESS, "%llu: Cannot understand '%s'.", w->id, w->response.data->buffer);
1455
1456
buffer_flush(w->response.data);
1457
buffer_strcat(w->response.data, "I don't understand you...\r\n");
1449
- w->response.code = 400;
1458
+ w->response.code = HTTP_RESPONSE_BAD_REQUEST;
1459
break;
1460
}
1461
web/server/web_client.h
+3
@@ -11,6 +11,9 @@ extern int web_enable_gzip,
11
web_gzip_strategy;
12
#endif /* NETDATA_WITH_ZLIB */
13
14
+//HTTP_CODES 4XX
15
+#define HTTP_RESPONSE_BAD_REQUEST 400
16
+
17
extern int respect_web_browser_do_not_track_policy;
18
extern char *web_x_frame_options;
19