summaryrefslogtreecommitdiffstats
path: root/web/server/web_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'web/server/web_client.c')
-rw-r--r--web/server/web_client.c147
1 files changed, 103 insertions, 44 deletions
diff --git a/web/server/web_client.c b/web/server/web_client.c
index 537152660..f0856fb17 100644
--- a/web/server/web_client.c
+++ b/web/server/web_client.c
@@ -199,6 +199,7 @@ void web_client_request_done(struct web_client *w) {
w->response.zstream.total_in = 0;
w->response.zstream.total_out = 0;
w->response.zinitialized = 0;
+ w->flags &= ~WEB_CLIENT_CHUNKED_TRANSFER;
}
#endif // NETDATA_WITH_ZLIB
}
@@ -501,6 +502,7 @@ void web_client_enable_deflate(struct web_client *w, int gzip) {
w->response.zsent = 0;
w->response.zoutput = 1;
w->response.zinitialized = 1;
+ w->flags |= WEB_CLIENT_CHUNKED_TRANSFER;
debug(D_DEFLATE, "%llu: Initialized compression.", w->id);
}
@@ -733,7 +735,8 @@ const char *web_response_code_to_string(int code) {
}
static inline char *http_header_parse(struct web_client *w, char *s, int parse_useragent) {
- static uint32_t hash_origin = 0, hash_connection = 0, hash_donottrack = 0, hash_useragent = 0, hash_authorization = 0, hash_host = 0;
+ static uint32_t hash_origin = 0, hash_connection = 0, hash_donottrack = 0, hash_useragent = 0,
+ hash_authorization = 0, hash_host = 0, hash_forwarded_proto = 0, hash_forwarded_host = 0;
#ifdef NETDATA_WITH_ZLIB
static uint32_t hash_accept_encoding = 0;
#endif
@@ -748,6 +751,8 @@ static inline char *http_header_parse(struct web_client *w, char *s, int parse_u
hash_useragent = simple_uhash("User-Agent");
hash_authorization = simple_uhash("X-Auth-Token");
hash_host = simple_uhash("Host");
+ hash_forwarded_proto = simple_uhash("X-Forwarded-Proto");
+ hash_forwarded_host = simple_uhash("X-Forwarded-Host");
}
char *e = s;
@@ -809,6 +814,15 @@ static inline char *http_header_parse(struct web_client *w, char *s, int parse_u
}
}
#endif /* NETDATA_WITH_ZLIB */
+#ifdef ENABLE_HTTPS
+ else if(hash == hash_forwarded_proto && !strcasecmp(s, "X-Forwarded-Proto")) {
+ if(strcasestr(v, "https"))
+ w->ssl.flags |= NETDATA_SSL_PROXY_HTTPS;
+ }
+#endif
+ else if(hash == hash_forwarded_host && !strcasecmp(s, "X-Forwarded-Host")){
+ strncpyz(w->forwarded_host, v, ((size_t)(ve - v) < sizeof(w->server_host)-1 ? (size_t)(ve - v) : sizeof(w->server_host)-1));
+ }
*e = ':';
*ve = '\r';
@@ -850,7 +864,7 @@ static inline char *web_client_valid_method(struct web_client *w, char *s) {
copyme += 9;
char *end = strchr(copyme,'&');
if(end){
- size_t length = end - copyme;
+ size_t length = MIN(255, end - copyme);
memcpy(hostname,copyme,length);
hostname[length] = 0X00;
}
@@ -863,7 +877,7 @@ static inline char *web_client_valid_method(struct web_client *w, char *s) {
memcpy(hostname,"not available",13);
hostname[13] = 0x00;
}
- error("The server is configured to always use encrypt connection, please enable the SSL on slave with hostname '%s'.",hostname);
+ error("The server is configured to always use encrypted connections, please enable the SSL on child with hostname '%s'.",hostname);
s = NULL;
}
#endif
@@ -1074,6 +1088,10 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
if ((w->ssl.conn) && ((w->ssl.flags & NETDATA_SSL_NO_HANDSHAKE) && (web_client_is_using_ssl_force(w) || web_client_is_using_ssl_default(w)) && (w->mode != WEB_CLIENT_MODE_STREAM)) ) {
w->header_parse_tries = 0;
w->header_parse_last_size = 0;
+ // The client will be redirected for Netdata and we are preserving the original request.
+ *ue = '\0';
+ strncpyz(w->last_url, encoded_url, NETDATA_WEB_REQUEST_URL_SIZE);
+ *ue = ' ';
web_client_disable_wait_receive(w);
return HTTP_VALIDATION_REDIRECT;
}
@@ -1118,7 +1136,7 @@ static inline ssize_t web_client_send_data(struct web_client *w,const void *buf,
return bytes;
}
-static inline void web_client_send_http_header(struct web_client *w) {
+void web_client_build_http_header(struct web_client *w) {
if(unlikely(w->response.code != HTTP_RESP_OK))
buffer_no_cacheable(w->response.data);
@@ -1148,39 +1166,30 @@ static inline void web_client_send_http_header(struct web_client *w) {
strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", tm);
}
- char headerbegin[8328];
if (w->response.code == HTTP_RESP_MOVED_PERM) {
- memcpy(headerbegin,"\r\nLocation: https://",20);
- size_t headerlength = strlen(w->server_host);
- memcpy(&headerbegin[20],w->server_host,headerlength);
- headerlength += 20;
- size_t tmp = strlen(w->last_url);
- memcpy(&headerbegin[headerlength],w->last_url,tmp);
- headerlength += tmp;
- memcpy(&headerbegin[headerlength],"\r\n",2);
- headerlength += 2;
- headerbegin[headerlength] = 0x00;
+ buffer_sprintf(w->response.header_output,
+ "HTTP/1.1 %d %s\r\n"
+ "Location: https://%s%s\r\n",
+ w->response.code, code_msg,
+ w->server_host,
+ w->last_url);
}else {
- memcpy(headerbegin,"\r\n",2);
- headerbegin[2]=0x00;
- }
-
- buffer_sprintf(w->response.header_output,
- "HTTP/1.1 %d %s\r\n"
- "Connection: %s\r\n"
- "Server: NetData Embedded HTTP Server %s\r\n"
- "Access-Control-Allow-Origin: %s\r\n"
- "Access-Control-Allow-Credentials: true\r\n"
- "Content-Type: %s\r\n"
- "Date: %s%s"
- , w->response.code, code_msg
- , web_client_has_keepalive(w)?"keep-alive":"close"
- , VERSION
- , w->origin
- , content_type_string
- , date
- , headerbegin
- );
+ buffer_sprintf(w->response.header_output,
+ "HTTP/1.1 %d %s\r\n"
+ "Connection: %s\r\n"
+ "Server: NetData Embedded HTTP Server %s\r\n"
+ "Access-Control-Allow-Origin: %s\r\n"
+ "Access-Control-Allow-Credentials: true\r\n"
+ "Content-Type: %s\r\n"
+ "Date: %s\r\n",
+ w->response.code,
+ code_msg,
+ web_client_has_keepalive(w)?"keep-alive":"close",
+ VERSION,
+ w->origin,
+ content_type_string,
+ date);
+ }
if(unlikely(web_x_frame_options))
buffer_sprintf(w->response.header_output, "X-Frame-Options: %s\r\n", web_x_frame_options);
@@ -1233,12 +1242,11 @@ static inline void web_client_send_http_header(struct web_client *w) {
buffer_strcat(w->response.header_output, buffer_tostring(w->response.header));
// headers related to the transfer method
- if(likely(w->response.zoutput)) {
- buffer_strcat(w->response.header_output,
- "Content-Encoding: gzip\r\n"
- "Transfer-Encoding: chunked\r\n"
- );
- }
+ if(likely(w->response.zoutput))
+ buffer_strcat(w->response.header_output, "Content-Encoding: gzip\r\n");
+
+ if(likely(w->flags & WEB_CLIENT_CHUNKED_TRANSFER))
+ buffer_strcat(w->response.header_output, "Transfer-Encoding: chunked\r\n");
else {
if(likely((w->response.data->len || w->response.rlen))) {
// we know the content length, put it
@@ -1252,6 +1260,10 @@ static inline void web_client_send_http_header(struct web_client *w) {
// end of HTTP header
buffer_strcat(w->response.header_output, "\r\n");
+}
+
+static inline void web_client_send_http_header(struct web_client *w) {
+ web_client_build_http_header(w);
// sent the HTTP header
debug(D_WEB_DATA, "%llu: Sending response HTTP header of size %zu: '%s'"
@@ -1339,8 +1351,23 @@ static inline int web_client_switch_host(RRDHOST *host, struct web_client *w, ch
if(tok && *tok) {
debug(D_WEB_CLIENT, "%llu: Searching for host with name '%s'.", w->id, tok);
+ if(!url) { //no delim found
+ debug(D_WEB_CLIENT, "%llu: URL doesn't end with / generating redirect.", w->id);
+ char *protocol, *url_host;
+#ifdef ENABLE_HTTPS
+ protocol = ((w->ssl.conn && !w->ssl.flags) || w->ssl.flags & NETDATA_SSL_PROXY_HTTPS) ? "https" : "http";
+#else
+ protocol = "http";
+#endif
+ url_host = (!w->forwarded_host[0])?w->server_host:w->forwarded_host;
+ buffer_sprintf(w->response.header, "Location: %s://%s%s/\r\n", protocol, url_host, w->last_url);
+ buffer_strcat(w->response.data, "Permanent redirect");
+ return HTTP_RESP_REDIR_PERM;
+ }
+
// copy the URL, we need it to serve files
w->last_url[0] = '/';
+
if(url && *url) strncpyz(&w->last_url[1], url, NETDATA_WEB_REQUEST_URL_SIZE - 1);
else w->last_url[1] = '\0';
@@ -1349,7 +1376,32 @@ static inline int web_client_switch_host(RRDHOST *host, struct web_client *w, ch
host = rrdhost_find_by_hostname(tok, hash);
if(!host) host = rrdhost_find_by_guid(tok, hash);
- if(host) return web_client_process_url(host, w, url);
+#ifdef ENABLE_DBENGINE
+ int release_host = 0;
+ if (!host) {
+ host = sql_create_host_by_uuid(tok);
+ if (likely(host)) {
+ rrdhost_flag_set(host, RRDHOST_FLAG_ARCHIVED);
+ release_host = 1;
+ }
+ }
+ if(host) {
+ int rc = web_client_process_url(host, w, url);
+ if (release_host) {
+ freez(host->hostname);
+ freez((char *) host->os);
+ freez((char *) host->tags);
+ freez((char *) host->timezone);
+ freez(host->program_name);
+ freez(host->program_version);
+ freez(host->registry_hostname);
+ freez(host);
+ }
+ return rc;
+ }
+#else
+ if (host) return web_client_process_url(host, w, url);
+#endif
}
buffer_flush(w->response.data);
@@ -1499,7 +1551,7 @@ void web_client_process_request(struct web_client *w) {
return;
}
- w->response.code = rrdpush_receiver_thread_spawn(localhost, w, w->decoded_url);
+ w->response.code = rrdpush_receiver_thread_spawn(w, w->decoded_url);
return;
case WEB_CLIENT_MODE_OPTIONS:
@@ -1558,7 +1610,14 @@ void web_client_process_request(struct web_client *w) {
{
buffer_flush(w->response.data);
w->response.data->contenttype = CT_TEXT_HTML;
- buffer_strcat(w->response.data, "<!DOCTYPE html><!-- SPDX-License-Identifier: GPL-3.0-or-later --><html><body onload=\"window.location.href ='https://'+ window.location.hostname + ':' + window.location.port + window.location.pathname\">Redirecting to safety connection, case your browser does not support redirection, please click <a onclick=\"window.location.href ='https://'+ window.location.hostname + ':' + window.location.port + window.location.pathname\">here</a>.</body></html>");
+ buffer_strcat(w->response.data,
+ "<!DOCTYPE html><!-- SPDX-License-Identifier: GPL-3.0-or-later --><html>"
+ "<body onload=\"window.location.href ='https://'+ window.location.hostname +"
+ " ':' + window.location.port + window.location.pathname + window.location.search\">"
+ "Redirecting to safety connection, case your browser does not support redirection, please"
+ " click <a onclick=\"window.location.href ='https://'+ window.location.hostname + ':' "
+ " + window.location.port + window.location.pathname + window.location.search\">here</a>."
+ "</body></html>");
w->response.code = HTTP_RESP_MOVED_PERM;
break;
}