Add reverse proxy error documents

This commit is contained in:
2021-11-07 19:48:09 +01:00
parent 61c645eca8
commit b37757fc73
8 changed files with 217 additions and 28 deletions

View File

@ -17,7 +17,7 @@ compile:
@mkdir -p bin @mkdir -p bin
$(CC) src/lib/*.c -o bin/libnecrondaserver.so --shared -fPIC $(CFLAGS) $(LIBS) $(CC) src/lib/*.c -o bin/libnecrondaserver.so --shared -fPIC $(CFLAGS) $(LIBS)
$(CC) src/necronda-server.c -o bin/necronda-server $(CFLAGS) $(LIBS) \ $(CC) src/necronda-server.c -o bin/necronda-server $(CFLAGS) $(LIBS) \
-Lbin -lnecronda-server -Wl,-rpath=$(shell pwd)/bin -Lbin -lnecrondaserver -Wl,-rpath=$(shell pwd)/bin
compile-prod: compile-prod:
@mkdir -p bin @mkdir -p bin

View File

@ -55,7 +55,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
long ret; long ret;
int client_keep_alive; int client_keep_alive;
char buf0[1024], buf1[1024]; char buf0[1024], buf1[1024];
char msg_buf[4096], msg_pre_buf[4096], err_msg[256]; char msg_buf[8192], msg_pre_buf_1[4096], msg_pre_buf_2[4096], err_msg[256];
char buffer[CHUNK_SIZE]; char buffer[CHUNK_SIZE];
err_msg[0] = 0; err_msg[0] = 0;
char host[256], *host_ptr, *hdr_connection; char host[256], *host_ptr, *hdr_connection;
@ -70,10 +70,8 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
fastcgi_conn fcgi_conn = {.socket = 0, .req_id = 0}; fastcgi_conn fcgi_conn = {.socket = 0, .req_id = 0};
http_status custom_status; http_status custom_status;
http_res res; http_res res = {.version = "1.1", .status = http_get_status(501), .hdr.field_num = 0};
sprintf(res.version, "1.1"); http_status_ctx ctx = {.status = 0, .origin = NONE};
res.status = http_get_status(501);
res.hdr.field_num = 0;
clock_gettime(CLOCK_MONOTONIC, &begin); clock_gettime(CLOCK_MONOTONIC, &begin);
@ -460,9 +458,24 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
http_remove_header_field(&res.hdr, "Date", HTTP_REMOVE_ALL); http_remove_header_field(&res.hdr, "Date", HTTP_REMOVE_ALL);
http_remove_header_field(&res.hdr, "Server", HTTP_REMOVE_ALL); http_remove_header_field(&res.hdr, "Server", HTTP_REMOVE_ALL);
ret = rev_proxy_init(&req, &res, conf, client, &custom_status, err_msg); ret = rev_proxy_init(&req, &res, &ctx, conf, client, &custom_status, err_msg);
use_rev_proxy = (ret == 0); use_rev_proxy = (ret == 0);
if (use_rev_proxy && res.status->code >= 400 && res.status->code < 600) {
const char *content_type = http_get_header_field(&res.hdr, "Content-Type");
const char *content_length_f = http_get_header_field(&res.hdr, "Content-Length");
if (content_type != NULL && content_length_f != NULL && strncmp(content_type, "text/html", 9) == 0) {
long content_len = strtol(content_length_f, NULL, 10);
if (content_len <= 1000) {
ctx.status = res.status->code;
ctx.origin = SERVER;
use_rev_proxy = 0;
rev_proxy_void();
}
}
}
/* /*
char *content_encoding = http_get_header_field(&res.hdr, "Content-Encoding"); char *content_encoding = http_get_header_field(&res.hdr, "Content-Encoding");
if (use_rev_proxy && content_encoding == NULL) { if (use_rev_proxy && content_encoding == NULL) {
@ -499,25 +512,53 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
if (http_get_header_field(&res.hdr, "Accept-Ranges") == NULL) { if (http_get_header_field(&res.hdr, "Accept-Ranges") == NULL) {
http_add_header_field(&res.hdr, "Accept-Ranges", "none"); http_add_header_field(&res.hdr, "Accept-Ranges", "none");
} }
if (!use_fastcgi && !use_rev_proxy && file == NULL && if (!use_fastcgi && file == NULL && ((res.status->code >= 400 && res.status->code < 600) || err_msg[0] != 0)) {
((res.status->code >= 400 && res.status->code < 600) || err_msg[0] != 0)) {
http_remove_header_field(&res.hdr, "Date", HTTP_REMOVE_ALL); http_remove_header_field(&res.hdr, "Date", HTTP_REMOVE_ALL);
http_remove_header_field(&res.hdr, "Server", HTTP_REMOVE_ALL); http_remove_header_field(&res.hdr, "Server", HTTP_REMOVE_ALL);
http_remove_header_field(&res.hdr, "Cache-Control", HTTP_REMOVE_ALL);
http_remove_header_field(&res.hdr, "Content-Type", HTTP_REMOVE_ALL);
http_remove_header_field(&res.hdr, "Content-Encoding", HTTP_REMOVE_ALL);
http_add_header_field(&res.hdr, "Date", http_get_date(buf0, sizeof(buf0))); http_add_header_field(&res.hdr, "Date", http_get_date(buf0, sizeof(buf0)));
http_add_header_field(&res.hdr, "Server", SERVER_STR); http_add_header_field(&res.hdr, "Server", SERVER_STR);
http_add_header_field(&res.hdr, "Cache-Control", "no-cache");
http_add_header_field(&res.hdr, "Content-Type", "text/html; charset=UTF-8");
// TODO list Locations on 3xx Redirects // TODO list Locations on 3xx Redirects
const http_doc_info *info = http_get_status_info(res.status); const http_doc_info *info = http_get_status_info(res.status);
const http_status_msg *http_msg = http_get_error_msg(res.status); const http_status_msg *http_msg = http_get_error_msg(res.status);
sprintf(msg_pre_buf, info->doc, res.status->code, res.status->msg, char *rev_proxy_doc = "";
if (conf->type == CONFIG_TYPE_REVERSE_PROXY) {
const http_status *status = http_get_status(ctx.status);
char stat_str[4];
sprintf(stat_str, "%03i", ctx.status);
sprintf(msg_pre_buf_2, http_rev_proxy_document,
" success",
(ctx.origin == CLIENT_REQ) ? " error" : " success",
(ctx.origin == INTERNAL) ? " error" : " success",
(ctx.origin == SERVER_REQ) ? " error" : (ctx.status == 0 ? "" : " success"),
(ctx.origin == CLIENT_RES) ? " error" : " success",
(ctx.origin == SERVER) ? " error" : (ctx.status == 0 ? "" : " success"),
(ctx.origin == SERVER_RES) ? " error" : (ctx.status == 0 ? "" : " success"),
(ctx.origin == INTERNAL) ? " error" : " success",
(ctx.origin == INTERNAL || ctx.origin == SERVER) ? " error" : " success",
res.status->code,
res.status->msg,
(ctx.status == 0) ? "???" : stat_str,
(status != NULL) ? status->msg : "",
host);
rev_proxy_doc = msg_pre_buf_2;
}
sprintf(msg_pre_buf_1, info->doc, res.status->code, res.status->msg,
http_msg != NULL ? http_msg->msg : "", err_msg[0] != 0 ? err_msg : ""); http_msg != NULL ? http_msg->msg : "", err_msg[0] != 0 ? err_msg : "");
content_length = snprintf(msg_buf, sizeof(msg_buf), http_default_document, res.status->code, content_length = snprintf(msg_buf, sizeof(msg_buf), http_default_document, res.status->code,
res.status->msg, msg_pre_buf, info->mode, info->icon, info->color, host); res.status->msg, msg_pre_buf_1, info->mode, info->icon, info->color, host,
http_add_header_field(&res.hdr, "Content-Type", "text/html; charset=UTF-8"); rev_proxy_doc);
} }
if (content_length >= 0) { if (content_length >= 0) {
sprintf(buf0, "%li", content_length); sprintf(buf0, "%li", content_length);
http_remove_header_field(&res.hdr, "Content-Length", HTTP_REMOVE_ALL);
http_add_header_field(&res.hdr, "Content-Length", buf0); http_add_header_field(&res.hdr, "Content-Length", buf0);
} else if (http_get_header_field(&res.hdr, "Transfer-Encoding") == NULL) { } else if (http_get_header_field(&res.hdr, "Transfer-Encoding") == NULL) {
server_keep_alive = 0; server_keep_alive = 0;

View File

@ -75,12 +75,22 @@ typedef struct {
http_hdr hdr; http_hdr hdr;
} http_res; } http_res;
typedef enum {
NONE, INTERNAL, CLIENT_REQ, SERVER_REQ, SERVER, SERVER_RES, CLIENT_RES
} http_error_origin;
typedef struct {
unsigned short status;
http_error_origin origin;
} http_status_ctx;
extern const http_status http_statuses[]; extern const http_status http_statuses[];
extern const http_status_msg http_status_messages[]; extern const http_status_msg http_status_messages[];
extern const int http_statuses_size; extern const int http_statuses_size;
extern const int http_status_messages_size; extern const int http_status_messages_size;
extern const char http_default_document[]; extern const char http_default_document[];
extern const char http_rev_proxy_document[];
extern const char http_error_document[]; extern const char http_error_document[];
extern const char http_error_icon[]; extern const char http_error_icon[];
extern const char http_warning_document[]; extern const char http_warning_document[];

View File

@ -116,20 +116,83 @@ const char http_default_document[] =
"\t<link rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/favicon.ico\"/>\n" "\t<link rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/favicon.ico\"/>\n"
"%5$s" "%5$s"
"\t<style>\n" "\t<style>\n"
"\t\thtml{font-family:\"Arial\",sans-serif;--error:" HTTP_COLOR_ERROR ";--warning:" HTTP_COLOR_WARNING ";--success:" HTTP_COLOR_SUCCESS ";--info:" HTTP_COLOR_INFO ";--color:var(--%4$s);}\n" "\t\thtml{font-family:\"Arial\",sans-serif;--error:" HTTP_COLOR_ERROR ";--warning:" HTTP_COLOR_WARNING ";--success:" HTTP_COLOR_SUCCESS ";--info:" HTTP_COLOR_INFO ";--soft:#808080;--color:var(--%4$s);}\n"
"\t\tbody{background-color:#F0F0F0;margin:0;}\n" "\t\tbody{background-color:#F0F0F0;margin:0;}\n"
"\t\tmain{max-width:650px;margin:2em auto;}\n" "\t\tmain{max-width:650px;margin:2em auto;}\n"
"\t\tsection{margin:1em;background-color:#FFFFFF;border: 1px solid var(--color);border-radius:4px;padding:1em;}\n" "\t\tsection{margin:2em 1em;background-color:#FFFFFF;border: 1px solid var(--color);border-radius:4px;padding:1em;}\n"
"\t\th1,h2,h3,h4,h5,h6,h7{text-align:center;color:var(--color);font-weight:normal;}\n" "\t\th1,h2,h3,h4,h5,h6{text-align:center;color:var(--color);font-weight:normal;}\n"
"\t\th1{font-size:3em;margin:0.125em 0 0.125em 0;}\n" "\t\th1{font-size:3em;margin:0.125em 0 0.125em 0;}\n"
"\t\th2{font-size:1.5em;margin:0.25em 0 1em 0;}\n" "\t\th2{font-size:1.5em;margin:0.25em 0 1em 0;}\n"
"\t\tp{text-align:center;font-size:0.875em;}\n" "\t\tp{text-align:center;font-size:0.875em;}\n"
"\t\tdiv.footer{color:#808080;font-size:0.75em;text-align:center;margin:2em 0 0.5em 0;}\n" "\t\tdiv.footer{color:var(--soft);font-size:0.75em;text-align:center;margin:2em 0 0.5em 0;}\n"
"\t\tdiv.footer a{color:#808080;}\n" "\t\tdiv.footer a{color:var(--soft);}\n"
"\n"
"\t\tsection.error-ctx{display:flex;padding:0;border:none;}\n"
"\t\tdiv.box{flex:100%% 1 1;border:1px solid var(--info);color:var(--info);position:relative;padding:1em;box-sizing:border-box;text-align:center;}\n"
"\t\tdiv.box.error{border-color:var(--error);color:var(--error);}\n"
"\t\tdiv.box.success{border-color:var(--success);color:var(--success);}\n"
"\t\tdiv.arrow{position:absolute;height:20px;width:30px;z-index:10;background-repeat:no-repeat;background-size:contain;}\n"
"\t\tdiv.arrow.response{left:-17.5px;bottom:calc(33.3333%% - 10px);}\n"
"\t\tdiv.arrow.request{right:-17.5px;top:calc(33.3333%% - 10px);}\n"
"\t\tdiv.border{flex:1px 0 0;background-color:var(--info);}\n"
"\t\tdiv.border.error{background-color:var(--error);}\n"
"\t\tdiv.border.success{background-color:var(--success);}\n"
"\t\tdiv.content>span{display:block;color:var(--soft);font-size:0.75em;}\n"
"\t\tdiv.content>img{height:3.75rem;margin:0.75rem auto;display:block;}\n"
"\t\th3{font-size:2.25em;margin:0.75rem 0 0 0;color:unset;height:2.5rem;}\n"
"\t\th4{font-size:1em;margin:0 0 0.75rem 0;color:unset;height:1.25rem;}\n"
"\n"
"\t\tdiv.arrow.request.success{background-image:url('data:image/svg+xml;base64,"
"PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
"L3N2ZyI+PHBhdGggZD0iTTEsMSBMMjUsMSBMMjksMTAgTDI1LDE5IEwxLDE5IiBmaWxsPSIjRkZG"
"RkZGIiBzdHJva2U9IiMwMDgwMDAiIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPgo=');}\n"
"\t\tdiv.arrow.request.error{background-image:url('data:image/svg+xml;base64,"
"PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
"L3N2ZyI+PHBhdGggZD0iTTEsMSBMMjUsMSBMMjksMTAgTDI1LDE5IEwxLDE5IiBmaWxsPSIjRkZG"
"RkZGIiBzdHJva2U9IiNDMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPgo=');}\n"
"\t\tdiv.arrow.response.success{background-image:url('data:image/svg+xml;base64,"
"PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
"L3N2ZyI+PHBhdGggZD0iTTI5LDE5IEw1LDE5IEwxLDEwIEw1LDEgTDI5LDEiIGZpbGw9IiNGRkZG"
"RkYiIHN0cm9rZT0iIzAwODAwMCIgc3Ryb2tlLXdpZHRoPSIyIi8+PC9zdmc+Cg==');}\n"
"\t\tdiv.arrow.response.error{background-image:url('data:image/svg+xml;base64,"
"PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
"L3N2ZyI+PHBhdGggZD0iTTI5LDE5IEw1LDE5IEwxLDEwIEw1LDEgTDI5LDEiIGZpbGw9IiNGRkZG"
"RkYiIHN0cm9rZT0iI0MwMDAwMCIgc3Ryb2tlLXdpZHRoPSIyIi8+PC9zdmc+Cg==');}\n"
"\n"
"\t\t@media(prefers-color-scheme:dark){\n" "\t\t@media(prefers-color-scheme:dark){\n"
"\t\t\thtml{color:#FFFFFF;}\n" "\t\t\thtml{color:#FFFFFF;--soft:#404040;}\n"
"\t\t\tbody{background-color:#101010;}\n" "\t\t\tbody{background-color:#101010;}\n"
"\t\t\tsection{background-color:#181818;}\n" "\t\t\tsection{background-color:#181818;}\n"
"\n"
"\t\t\tdiv.arrow.request.success{background-image:url('data:image/svg+xml;base64,"
"PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
"L3N2ZyI+PHBhdGggZD0iTTEsMSBMMjUsMSBMMjksMTAgTDI1LDE5IEwxLDE5IiBmaWxsPSIjMTgx"
"ODE4IiBzdHJva2U9IiMwMDgwMDAiIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPgo=');}\n"
"\t\t\tdiv.arrow.request.error{background-image:url('data:image/svg+xml;base64,"
"PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
"L3N2ZyI+PHBhdGggZD0iTTEsMSBMMjUsMSBMMjksMTAgTDI1LDE5IEwxLDE5IiBmaWxsPSIjMTgx"
"ODE4IiBzdHJva2U9IiNDMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIvPjwvc3ZnPgo=');}\n"
"\t\t\tdiv.arrow.response.success{background-image:url('data:image/svg+xml;base64,"
"PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
"L3N2ZyI+PHBhdGggZD0iTTI5LDE5IEw1LDE5IEwxLDEwIEw1LDEgTDI5LDEiIGZpbGw9IiMxODE4"
"MTgiIHN0cm9rZT0iIzAwODAwMCIgc3Ryb2tlLXdpZHRoPSIyIi8+PC9zdmc+Cg==');}\n"
"\t\t\tdiv.arrow.response.error{background-image:url('data:image/svg+xml;base64,"
"PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
"L3N2ZyI+PHBhdGggZD0iTTI5LDE5IEw1LDE5IEwxLDEwIEw1LDEgTDI5LDEiIGZpbGw9IiMxODE4"
"MTgiIHN0cm9rZT0iI0MwMDAwMCIgc3Ryb2tlLXdpZHRoPSIyIi8+PC9zdmc+Cg==');}\n"
"\t\t}\n"
"\t\t@media(min-width:650px){\n"
"\t\t\tdiv.box:first-child{border-top-left-radius:4px;border-bottom-left-radius:4px;border-right:none;}\n"
"\t\t\tdiv.box:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px;border-left:none;}\n"
"\t\t\tdiv.box:not(:last-child):not(:first-child){border-left:none;border-right:none;}\n"
"\t\t}\n"
"\t\t@media(max-width:650px){\n"
"\t\t\tsection.error-ctx{flex-direction:column;height:unset;}\n"
"\t\t\tdiv.box:first-child{border-top-left-radius:4px;border-top-right-radius:4px;border-bottom:none;padding-top:1em;}\n"
"\t\t\tdiv.box:last-child{border-bottom-right-radius:4px;border-bottom-left-radius:4px;border-top:none;padding-bottom:1em;}\n"
"\t\t\tdiv.box:not(:last-child):not(:first-child){border-top:none;border-bottom:none;}\n"
"\t\t\tdiv.arrow.response{transform:rotate(90deg);top:-10px;left:calc(33.3333%% - 22.5px);right:unset;}\n"
"\t\t\tdiv.arrow.request{transform:rotate(90deg);bottom:-10px;right:calc(33.3333%% - 22.5px);top:unset;}\n"
"\t\t}\n" "\t\t}\n"
"\t</style>\n" "\t</style>\n"
"</head>\n" "</head>\n"
@ -139,10 +202,49 @@ const char http_default_document[] =
"%3$s" "%3$s"
"\t\t\t<div class=\"footer\"><a href=\"https://%7$s/\">%7$s</a> - " SERVER_STR_HTML "</div>\n" "\t\t\t<div class=\"footer\"><a href=\"https://%7$s/\">%7$s</a> - " SERVER_STR_HTML "</div>\n"
"\t\t</section>\n" "\t\t</section>\n"
"%8$s"
"\t</main>\n" "\t</main>\n"
"</body>\n" "</body>\n"
"</html>\n"; "</html>\n";
const char http_rev_proxy_document[] =
"\t\t<section class=\"error-ctx\">\n"
"\t\t\t<div class=\"box%1$s\">\n"
"\t\t\t\t<div class=\"content\">\n"
"\t\t\t\t\t<span>Client</span>\n"
"\t\t\t\t\t<img src=\"data:image/svg+xml;base64,"
"PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAw"
"L3N2ZyI+PHBhdGggZD0iTTIsMzIgYTMwLDMwLDAsMSwwLDYwLDAgYTMwLDMwLDAsMSwwLC02MCww"
"IEw2MiwzMiBNNiwxNiBMNTgsMTYgTTYsNDggTDU4LDQ4IE0zMiwyIEwzMiw2MiBhMTUsMzAsMCwx"
"LDAsMCwtNjAgYTE1LDMwLDAsMSwwLDAsNjAgWiIgc3Ryb2tlPSIjMDA4MDAwIiBzdHJva2Utd2lk"
"dGg9IjIiIGZpbGw9IiMwMDAwMDAwMCIvPjwvc3ZnPgo=\"/>\n"
"\t\t\t\t\t<span>Your Browser</span>\n"
"\t\t\t\t</div>\n"
"\t\t\t\t<div class=\"arrow request%2$s\"></div>\n"
"\t\t\t</div>\n"
"\t\t\t<div class=\"border%8$s\"></div>\n"
"\t\t\t<div class=\"box%3$s\">\n"
"\t\t\t\t<div class=\"content\">\n"
"\t\t\t\t\t<span>Reverse Proxy</span>\n"
"\t\t\t\t\t<h3>%10$03i</h3>\n"
"\t\t\t\t\t<h4>%11$s</h4>\n"
"\t\t\t\t\t<span>" SERVER_NAME "</span>\n"
"\t\t\t\t</div>\n"
"\t\t\t\t<div class=\"arrow request%4$s\"></div>\n"
"\t\t\t\t<div class=\"arrow response%5$s\"></div>\n"
"\t\t\t</div>\n"
"\t\t\t<div class=\"border%9$s\"></div>\n"
"\t\t\t<div class=\"box%6$s\">\n"
"\t\t\t\t<div class=\"content\">\n"
"\t\t\t\t\t<span>Server</span>\n"
"\t\t\t\t\t<h3>%12$s</h3>\n"
"\t\t\t\t\t<h4>%13$s</h4>\n"
"\t\t\t\t\t<span>%14$s</span>\n"
"\t\t\t\t</div>\n"
"\t\t\t\t<div class=\"arrow response%7$s\"></div>\n"
"\t\t\t</div>\n"
"\t\t</section>\n";
const char http_error_document[] = const char http_error_document[] =
"\t\t\t<h1>%1$i</h1>\n" "\t\t\t<h1>%1$i</h1>\n"
"\t\t\t<h2>%2$s :&#xFEFF;(</h2>\n" "\t\t\t<h2>%2$s :&#xFEFF;(</h2>\n"

View File

@ -36,7 +36,7 @@ int rev_proxy_request_header(http_req *req, int enc) {
http_add_header_field(&req->hdr, "Connection", "keep-alive"); http_add_header_field(&req->hdr, "Connection", "keep-alive");
char *via = http_get_header_field(&req->hdr, "Via"); char *via = http_get_header_field(&req->hdr, "Via");
sprintf(buf1, "HTTP/%s %s", req->version, DEFAULT_HOST); sprintf(buf1, "HTTP/%s %s", req->version, SERVER_NAME);
if (via == NULL) { if (via == NULL) {
http_add_header_field(&req->hdr, "Via", buf1); http_add_header_field(&req->hdr, "Via", buf1);
} else { } else {
@ -134,7 +134,7 @@ int rev_proxy_response_header(http_req *req, http_res *res) {
int p_len; int p_len;
char *via = http_get_header_field(&res->hdr, "Via"); char *via = http_get_header_field(&res->hdr, "Via");
p_len = snprintf(buf1, sizeof(buf1), "HTTP/%s %s", req->version, DEFAULT_HOST); p_len = snprintf(buf1, sizeof(buf1), "HTTP/%s %s", req->version, SERVER_NAME);
if (p_len < 0 || p_len >= sizeof(buf1)) { if (p_len < 0 || p_len >= sizeof(buf1)) {
print(ERR_STR "Appended part of header field 'Via' too long" CLR_STR); print(ERR_STR "Appended part of header field 'Via' too long" CLR_STR);
return -1; return -1;
@ -154,8 +154,8 @@ int rev_proxy_response_header(http_req *req, http_res *res) {
return 0; return 0;
} }
int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client, http_status *custom_status, int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_config *conf, sock *client,
char *err_msg) { http_status *custom_status, char *err_msg) {
char buffer[CHUNK_SIZE]; char buffer[CHUNK_SIZE];
long ret; long ret;
int tries = 0; int tries = 0;
@ -177,6 +177,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
if (rev_proxy.socket < 0) { if (rev_proxy.socket < 0) {
print(ERR_STR "Unable to create socket: %s" CLR_STR, strerror(errno)); print(ERR_STR "Unable to create socket: %s" CLR_STR, strerror(errno));
res->status = http_get_status(500); res->status = http_get_status(500);
ctx->origin = INTERNAL;
return -1; return -1;
} }
@ -187,6 +188,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
if (setsockopt(rev_proxy.socket, SOL_SOCKET, SO_SNDTIMEO, &server_timeout, sizeof(server_timeout)) < 0) { if (setsockopt(rev_proxy.socket, SOL_SOCKET, SO_SNDTIMEO, &server_timeout, sizeof(server_timeout)) < 0) {
rev_proxy_timeout_err: rev_proxy_timeout_err:
res->status = http_get_status(500); res->status = http_get_status(500);
ctx->origin = INTERNAL;
print(ERR_STR "Unable to set timeout for socket: %s" CLR_STR, strerror(errno)); print(ERR_STR "Unable to set timeout for socket: %s" CLR_STR, strerror(errno));
sprintf(err_msg, "Unable to set timeout for socket: %s", strerror(errno)); sprintf(err_msg, "Unable to set timeout for socket: %s", strerror(errno));
goto proxy_err; goto proxy_err;
@ -197,6 +199,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
host_ent = gethostbyname2(conf->rev_proxy.hostname, AF_INET); host_ent = gethostbyname2(conf->rev_proxy.hostname, AF_INET);
if (host_ent == NULL) { if (host_ent == NULL) {
res->status = http_get_status(503); res->status = http_get_status(503);
ctx->origin = SERVER_REQ;
print(ERR_STR "Unable to connect to server: Name or service not known" CLR_STR); print(ERR_STR "Unable to connect to server: Name or service not known" CLR_STR);
sprintf(err_msg, "Unable to connect to server: Name or service not known."); sprintf(err_msg, "Unable to connect to server: Name or service not known.");
goto proxy_err; goto proxy_err;
@ -218,10 +221,13 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
if (connect(rev_proxy.socket, (struct sockaddr *) &address, sizeof(address)) < 0) { if (connect(rev_proxy.socket, (struct sockaddr *) &address, sizeof(address)) < 0) {
if (errno == ETIMEDOUT) { if (errno == ETIMEDOUT) {
res->status = http_get_status(504); res->status = http_get_status(504);
ctx->origin = SERVER_REQ;
} else if (errno == ECONNREFUSED) { } else if (errno == ECONNREFUSED) {
res->status = http_get_status(503); res->status = http_get_status(503);
ctx->origin = SERVER_REQ;
} else { } else {
res->status = http_get_status(500); res->status = http_get_status(500);
ctx->origin = INTERNAL;
} }
print(ERR_STR "Unable to connect to [%s]:%i: %s" CLR_STR, buffer, conf->rev_proxy.port, strerror(errno)); print(ERR_STR "Unable to connect to [%s]:%i: %s" CLR_STR, buffer, conf->rev_proxy.port, strerror(errno));
sprintf(err_msg, "Unable to connect to server: %s.", strerror(errno)); sprintf(err_msg, "Unable to connect to server: %s.", strerror(errno));
@ -240,6 +246,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
rev_proxy.enc = 1; rev_proxy.enc = 1;
if (ret < 0) { if (ret < 0) {
res->status = http_get_status(502); res->status = http_get_status(502);
ctx->origin = SERVER_REQ;
print(ERR_STR "Unable to perform handshake: %s" CLR_STR, sock_strerror(&rev_proxy)); print(ERR_STR "Unable to perform handshake: %s" CLR_STR, sock_strerror(&rev_proxy));
sprintf(err_msg, "Unable to perform handshake: %s.", sock_strerror(&rev_proxy)); sprintf(err_msg, "Unable to perform handshake: %s.", sock_strerror(&rev_proxy));
goto proxy_err; goto proxy_err;
@ -253,12 +260,14 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
ret = rev_proxy_request_header(req, (int) client->enc); ret = rev_proxy_request_header(req, (int) client->enc);
if (ret != 0) { if (ret != 0) {
res->status = http_get_status(500); res->status = http_get_status(500);
ctx->origin = INTERNAL;
return -1; return -1;
} }
ret = http_send_request(&rev_proxy, req); ret = http_send_request(&rev_proxy, req);
if (ret < 0) { if (ret < 0) {
res->status = http_get_status(502); res->status = http_get_status(502);
ctx->origin = SERVER_REQ;
print(ERR_STR "Unable to send request to server (1): %s" CLR_STR, sock_strerror(&rev_proxy)); print(ERR_STR "Unable to send request to server (1): %s" CLR_STR, sock_strerror(&rev_proxy));
sprintf(err_msg, "Unable to send request to server: %s.", sock_strerror(&rev_proxy)); sprintf(err_msg, "Unable to send request to server: %s.", sock_strerror(&rev_proxy));
retry = tries < 4; retry = tries < 4;
@ -276,6 +285,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
ret = sock_send(&rev_proxy, client->buf, len, 0); ret = sock_send(&rev_proxy, client->buf, len, 0);
if (ret <= 0) { if (ret <= 0) {
res->status = http_get_status(502); res->status = http_get_status(502);
ctx->origin = SERVER_REQ;
print(ERR_STR "Unable to send request to server (2): %s" CLR_STR, sock_strerror(&rev_proxy)); print(ERR_STR "Unable to send request to server (2): %s" CLR_STR, sock_strerror(&rev_proxy));
sprintf(err_msg, "Unable to send request to server: %s.", sock_strerror(&rev_proxy)); sprintf(err_msg, "Unable to send request to server: %s.", sock_strerror(&rev_proxy));
retry = tries < 4; retry = tries < 4;
@ -288,16 +298,19 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
if (ret <= 0) { if (ret <= 0) {
if (ret == -1) { if (ret == -1) {
res->status = http_get_status(502); res->status = http_get_status(502);
ctx->origin = SERVER_REQ;
print(ERR_STR "Unable to send request to server (3): %s" CLR_STR, sock_strerror(&rev_proxy)); print(ERR_STR "Unable to send request to server (3): %s" CLR_STR, sock_strerror(&rev_proxy));
sprintf(err_msg, "Unable to send request to server: %s.", sock_strerror(&rev_proxy)); sprintf(err_msg, "Unable to send request to server: %s.", sock_strerror(&rev_proxy));
goto proxy_err; goto proxy_err;
} else if (ret == -2) { } else if (ret == -2) {
res->status = http_get_status(400); res->status = http_get_status(400);
ctx->origin = CLIENT_REQ;
print(ERR_STR "Unable to receive request from client: %s" CLR_STR, sock_strerror(client)); print(ERR_STR "Unable to receive request from client: %s" CLR_STR, sock_strerror(client));
sprintf(err_msg, "Unable to receive request from client: %s.", sock_strerror(client)); sprintf(err_msg, "Unable to receive request from client: %s.", sock_strerror(client));
return -1; return -1;
} }
res->status = http_get_status(500); res->status = http_get_status(500);
ctx->origin = INTERNAL;
print(ERR_STR "Unknown Error" CLR_STR); print(ERR_STR "Unknown Error" CLR_STR);
return -1; return -1;
} }
@ -307,6 +320,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
ret = sock_recv(&rev_proxy, buffer, sizeof(buffer), MSG_PEEK); ret = sock_recv(&rev_proxy, buffer, sizeof(buffer), MSG_PEEK);
if (ret <= 0) { if (ret <= 0) {
res->status = http_get_status(502); res->status = http_get_status(502);
ctx->origin = SERVER_RES;
print(ERR_STR "Unable to receive response from server: %s" CLR_STR, sock_strerror(&rev_proxy)); print(ERR_STR "Unable to receive response from server: %s" CLR_STR, sock_strerror(&rev_proxy));
sprintf(err_msg, "Unable to receive response from server: %s.", sock_strerror(&rev_proxy)); sprintf(err_msg, "Unable to receive response from server: %s.", sock_strerror(&rev_proxy));
goto proxy_err; goto proxy_err;
@ -317,6 +331,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
if (header_len <= 0) { if (header_len <= 0) {
res->status = http_get_status(502); res->status = http_get_status(502);
ctx->origin = SERVER_RES;
print(ERR_STR "Unable to parse header: End of header not found" CLR_STR); print(ERR_STR "Unable to parse header: End of header not found" CLR_STR);
sprintf(err_msg, "Unable to parser header: End of header not found."); sprintf(err_msg, "Unable to parser header: End of header not found.");
goto proxy_err; goto proxy_err;
@ -325,6 +340,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
for (int i = 0; i < header_len; i++) { for (int i = 0; i < header_len; i++) {
if ((buf[i] >= 0x00 && buf[i] <= 0x1F && buf[i] != '\r' && buf[i] != '\n') || buf[i] == 0x7F) { if ((buf[i] >= 0x00 && buf[i] <= 0x1F && buf[i] != '\r' && buf[i] != '\n') || buf[i] == 0x7F) {
res->status = http_get_status(502); res->status = http_get_status(502);
ctx->origin = SERVER_RES;
print(ERR_STR "Unable to parse header: Header contains illegal characters" CLR_STR); print(ERR_STR "Unable to parse header: Header contains illegal characters" CLR_STR);
sprintf(err_msg, "Unable to parse header: Header contains illegal characters."); sprintf(err_msg, "Unable to parse header: Header contains illegal characters.");
goto proxy_err; goto proxy_err;
@ -336,6 +352,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
char *pos0 = strstr(ptr, "\r\n"); char *pos0 = strstr(ptr, "\r\n");
if (pos0 == NULL) { if (pos0 == NULL) {
res->status = http_get_status(502); res->status = http_get_status(502);
ctx->origin = SERVER_RES;
print(ERR_STR "Unable to parse header: Invalid header format" CLR_STR); print(ERR_STR "Unable to parse header: Invalid header format" CLR_STR);
sprintf(err_msg, "Unable to parse header: Invalid header format."); sprintf(err_msg, "Unable to parse header: Invalid header format.");
goto proxy_err; goto proxy_err;
@ -343,6 +360,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
if (ptr == buf) { if (ptr == buf) {
if (strncmp(ptr, "HTTP/", 5) != 0) { if (strncmp(ptr, "HTTP/", 5) != 0) {
res->status = http_get_status(502); res->status = http_get_status(502);
ctx->origin = SERVER_RES;
print(ERR_STR "Unable to parse header: Invalid header format" CLR_STR); print(ERR_STR "Unable to parse header: Invalid header format" CLR_STR);
sprintf(err_msg, "Unable to parse header: Invalid header format."); sprintf(err_msg, "Unable to parse header: Invalid header format.");
goto proxy_err; goto proxy_err;
@ -357,6 +375,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
res->status = custom_status; res->status = custom_status;
} else if (res->status == NULL) { } else if (res->status == NULL) {
res->status = http_get_status(502); res->status = http_get_status(502);
ctx->origin = SERVER_RES;
print(ERR_STR "Unable to parse header: Invalid or unknown status code" CLR_STR); print(ERR_STR "Unable to parse header: Invalid or unknown status code" CLR_STR);
sprintf(err_msg, "Unable to parse header: Invalid or unknown status code."); sprintf(err_msg, "Unable to parse header: Invalid or unknown status code.");
goto proxy_err; goto proxy_err;
@ -365,6 +384,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
ret = http_parse_header_field(&res->hdr, ptr, pos0); ret = http_parse_header_field(&res->hdr, ptr, pos0);
if (ret != 0) { if (ret != 0) {
res->status = http_get_status(502); res->status = http_get_status(502);
ctx->origin = SERVER_RES;
print(ERR_STR "Unable to parse header" CLR_STR); print(ERR_STR "Unable to parse header" CLR_STR);
sprintf(err_msg, "Unable to parse header."); sprintf(err_msg, "Unable to parse header.");
goto proxy_err; goto proxy_err;
@ -380,6 +400,7 @@ int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client
ret = rev_proxy_response_header(req, res); ret = rev_proxy_response_header(req, res);
if (ret != 0) { if (ret != 0) {
res->status = http_get_status(500); res->status = http_get_status(500);
ctx->origin = INTERNAL;
return -1; return -1;
} }
@ -497,3 +518,8 @@ int rev_proxy_send(sock *client, unsigned long len_to_send, int flags) {
return 0; return 0;
} }
int rev_proxy_void() {
while (sock_recv(&rev_proxy, NULL, 1024, 0) > 0);
return 0;
}

View File

@ -13,6 +13,10 @@
#define REV_PROXY_COMPRESS_BR 4 #define REV_PROXY_COMPRESS_BR 4
#define REV_PROXY_COMPRESS 6 #define REV_PROXY_COMPRESS 6
#ifndef SERVER_NAME
# define SERVER_NAME "revproxy"
#endif
#include "http.h" #include "http.h"
#include "config.h" #include "config.h"
@ -24,9 +28,11 @@ int rev_proxy_request_header(http_req *req, int enc);
int rev_proxy_response_header(http_req *req, http_res *res); int rev_proxy_response_header(http_req *req, http_res *res);
int rev_proxy_init(http_req *req, http_res *res, host_config *conf, sock *client, http_status *custom_status, int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_config *conf, sock *client,
char *err_msg); http_status *custom_status, char *err_msg);
int rev_proxy_send(sock *client, unsigned long len_to_send, int flags); int rev_proxy_send(sock *client, unsigned long len_to_send, int flags);
int rev_proxy_void();
#endif //NECRONDA_SERVER_REV_PROXY_H #endif //NECRONDA_SERVER_REV_PROXY_H

View File

@ -21,10 +21,6 @@
#define CHUNK_SIZE 8192 #define CHUNK_SIZE 8192
#ifndef DEFAULT_HOST
# define DEFAULT_HOST "www.necronda.net"
#endif
extern int sockets[NUM_SOCKETS]; extern int sockets[NUM_SOCKETS];
extern pid_t children[MAX_CHILDREN]; extern pid_t children[MAX_CHILDREN];
extern MMDB_s mmdbs[MAX_MMDB]; extern MMDB_s mmdbs[MAX_MMDB];

View File

@ -12,4 +12,12 @@
#define SERVER_STR "Necronda/" NECRONDA_VERSION #define SERVER_STR "Necronda/" NECRONDA_VERSION
#define SERVER_STR_HTML "Necronda&nbsp;web&nbsp;server&nbsp;" NECRONDA_VERSION #define SERVER_STR_HTML "Necronda&nbsp;web&nbsp;server&nbsp;" NECRONDA_VERSION
#ifndef DEFAULT_HOST
# define DEFAULT_HOST "www.necronda.net"
#endif
#ifndef SERVER_NAME
# define SERVER_NAME DEFAULT_HOST
#endif
#endif //NECRONDA_SERVER_NECRONDA_H #endif //NECRONDA_SERVER_NECRONDA_H