diff --git a/include/proto/httperr.h b/include/proto/httperr.h index 24a0cd1afc..749e4275e7 100644 --- a/include/proto/httperr.h +++ b/include/proto/httperr.h @@ -25,12 +25,14 @@ #include extern const int http_err_codes[HTTP_ERR_SIZE]; -extern const char *http_err_msgs[HTTP_ERR_SIZE]; +extern struct chunk http_err_chunks[HTTP_ERR_SIZE]; extern const char *HTTP_200; extern const char *HTTP_302; extern const char *HTTP_303; extern const char *HTTP_401_fmt; +struct chunk *error_message(struct session *s, int msgnum); + #endif /* _PROTO_HTTPERR_H */ /* diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h index 5ee3a53dec..82f68a19d5 100644 --- a/include/proto/proto_http.h +++ b/include/proto/proto_http.h @@ -51,6 +51,7 @@ void get_srv_from_appsession(struct session *t, const char *begin, const char *e void apply_filters_to_session(struct session *t, struct buffer *req, struct hdr_exp *exp); void manage_client_side_cookies(struct session *t, struct buffer *req); int stats_check_uri_auth(struct session *t, struct proxy *backend); +void init_proto_http(); #endif /* _PROTO_PROTO_HTTP_H */ diff --git a/src/backend.c b/src/backend.c index f794ea570a..f7dd675715 100644 --- a/src/backend.c +++ b/src/backend.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -545,7 +546,7 @@ int srv_count_retry_down(struct session *t, int conn_err) /* if not retryable anymore, let's abort */ tv_eternity(&t->req->cex); srv_close_with_err(t, conn_err, SN_FINST_C, - 503, &t->fe->errmsg[HTTP_ERR_503]); + 503, error_message(t, HTTP_ERR_503)); if (t->srv) t->srv->failed_conns++; t->be->beprm->failed_conns++; @@ -587,7 +588,7 @@ int srv_retryable_connect(struct session *t) case SN_ERR_INTERNAL: tv_eternity(&t->req->cex); srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C, - 500, &t->fe->errmsg[HTTP_ERR_500]); + 500, error_message(t, HTTP_ERR_500)); if (t->srv) t->srv->failed_conns++; t->be->beprm->failed_conns++; @@ -647,7 +648,7 @@ int srv_redispatch_connect(struct session *t) /* note: it is guaranteed that t->srv == NULL here */ tv_eternity(&t->req->cex); srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_C, - 503, &t->fe->errmsg[HTTP_ERR_503]); + 503, error_message(t, HTTP_ERR_503)); if (t->srv) t->srv->failed_conns++; t->be->beprm->failed_conns++; @@ -669,7 +670,7 @@ int srv_redispatch_connect(struct session *t) default: tv_eternity(&t->req->cex); srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C, - 500, &t->fe->errmsg[HTTP_ERR_500]); + 500, error_message(t, HTTP_ERR_500)); if (t->srv) t->srv->failed_conns++; t->be->beprm->failed_conns++; diff --git a/src/cfgparse.c b/src/cfgparse.c index f3659f5030..d70768592d 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -1740,7 +1740,7 @@ int readcfgfile(const char *file) char *args[MAX_LINE_ARGS]; int arg; int cfgerr = 0; - int nbchk, mininter, rc; + int nbchk, mininter; int confsect = CFG_NONE; struct proxy *curproxy = NULL; @@ -2029,17 +2029,6 @@ int readcfgfile(const char *file) if (curproxy->options & PR_O_LOGASAP) curproxy->to_log &= ~LW_BYTES; - for (rc = 0; rc < HTTP_ERR_SIZE; rc++) { - if (!http_err_msgs[rc]) { - Alert("Internal error: no message defined for HTTP return code %d. Aborting.\n"); - abort(); - } - if (!curproxy->errmsg[rc].str) { - curproxy->errmsg[rc].str = strdup(http_err_msgs[rc]); - curproxy->errmsg[rc].len = strlen(http_err_msgs[rc]); - } - } - /* * If this server supports a maxconn parameter, it needs a dedicated * tasks to fill the emptied slots when a connection leaves. diff --git a/src/haproxy.c b/src/haproxy.c index d2b6d10ade..047136422a 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -83,6 +83,7 @@ #include #include #include +#include #include #include #include @@ -353,6 +354,7 @@ void init(int argc, char **argv) start_date = now; init_log(); + init_proto_http(); cfg_polling_mechanism = POLL_USE_SELECT; /* select() is always available */ #if defined(ENABLE_POLL) diff --git a/src/proto_http.c b/src/proto_http.c index 89b5b60f6c..83fb1da323 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -114,9 +114,9 @@ const int http_err_codes[HTTP_ERR_SIZE] = { [HTTP_ERR_504] = 504, }; -const char *http_err_msgs[HTTP_ERR_SIZE] = { +static const char *http_err_msgs[HTTP_ERR_SIZE] = { [HTTP_ERR_400] = - "HTTP/1.0 400 Bad request\r\n" + "HTTP/1.0 400 Bad request\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" @@ -173,6 +173,24 @@ const char *http_err_msgs[HTTP_ERR_SIZE] = { }; +/* We must put the messages here since GCC cannot initialize consts depending + * on strlen(). + */ +struct chunk http_err_chunks[HTTP_ERR_SIZE]; + +void init_proto_http() +{ + int msg; + for (msg = 0; msg < HTTP_ERR_SIZE; msg++) { + if (!http_err_msgs[msg]) { + Alert("Internal error: no message defined for HTTP return code %d. Aborting.\n", msg); + abort(); + } + + http_err_chunks[msg].str = (char *)http_err_msgs[msg]; + http_err_chunks[msg].len = strlen(http_err_msgs[msg]); + } +} /* * We have 26 list of methods (1 per first letter), each of which can have @@ -275,6 +293,19 @@ void srv_close_with_err(struct session *t, int err, int finst, t->flags |= finst; } +/* This function returns the appropriate error location for the given session + * and message. + */ + +struct chunk *error_message(struct session *s, int msgnum) +{ + if (s->be->beprm->errmsg[msgnum].str) + return &s->be->beprm->errmsg[msgnum]; + else if (s->fe->errmsg[msgnum].str) + return &s->fe->errmsg[msgnum]; + else + return &http_err_chunks[msgnum]; +} /* * returns HTTP_METH_NONE if there is nothing valid to read (empty or non-text @@ -907,7 +938,7 @@ int process_cli(struct session *t) else if (tv_cmp2_ms(&req->rex, &now) <= 0) { /* read timeout : give up with an error message. */ t->logs.status = 408; - client_retnclose(t, &t->fe->errmsg[HTTP_ERR_408]); + client_retnclose(t, error_message(t, HTTP_ERR_408)); if (!(t->flags & SN_ERR_MASK)) t->flags |= SN_ERR_CLITO; if (!(t->flags & SN_FINST_MASK)) @@ -1030,7 +1061,7 @@ int process_cli(struct session *t) t->logs.status = 403; /* let's log the request time */ t->logs.t_request = tv_diff(&t->logs.tv_accept, &now); - client_retnclose(t, &t->fe->errmsg[HTTP_ERR_403]); + client_retnclose(t, error_message(t, HTTP_ERR_403)); goto return_prx_cond; } @@ -1233,7 +1264,7 @@ int process_cli(struct session *t) return_bad_req: /* let's centralize all bad requests */ t->hreq.hdr_state = HTTP_PA_ERROR; t->logs.status = 400; - client_retnclose(t, &t->fe->errmsg[HTTP_ERR_400]); + client_retnclose(t, error_message(t, HTTP_ERR_400)); return_prx_cond: if (!(t->flags & SN_ERR_MASK)) t->flags |= SN_ERR_PRXCOND; @@ -1586,7 +1617,7 @@ int process_srv(struct session *t) tv_eternity(&req->cex); t->logs.t_queue = tv_diff(&t->logs.tv_accept, &now); srv_close_with_err(t, SN_ERR_PRXCOND, SN_FINST_T, - 500, &t->fe->errmsg[HTTP_ERR_500]); + 500, error_message(t, HTTP_ERR_500)); return 1; } @@ -1603,7 +1634,7 @@ int process_srv(struct session *t) tv_eternity(&req->cex); t->logs.t_queue = tv_diff(&t->logs.tv_accept, &now); srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_Q, - 503, &t->fe->errmsg[HTTP_ERR_503]); + 503, error_message(t, HTTP_ERR_503)); if (t->srv) t->srv->failed_conns++; t->fe->failed_conns++; @@ -1788,7 +1819,7 @@ int process_srv(struct session *t) t->be->failed_secu++; t->srv_state = SV_STCLOSE; t->logs.status = 502; - client_return(t, &t->fe->errmsg[HTTP_ERR_502]); + client_return(t, error_message(t, HTTP_ERR_502)); if (!(t->flags & SN_ERR_MASK)) t->flags |= SN_ERR_PRXCOND; if (!(t->flags & SN_FINST_MASK)) @@ -1819,7 +1850,7 @@ int process_srv(struct session *t) t->be->failed_secu++; t->srv_state = SV_STCLOSE; t->logs.status = 502; - client_return(t, &t->fe->errmsg[HTTP_ERR_502]); + client_return(t, error_message(t, HTTP_ERR_502)); if (!(t->flags & SN_ERR_MASK)) t->flags |= SN_ERR_PRXCOND; if (!(t->flags & SN_FINST_MASK)) @@ -2259,7 +2290,7 @@ int process_srv(struct session *t) t->srv_state = SV_STCLOSE; t->logs.status = 502; - client_return(t, &t->fe->errmsg[HTTP_ERR_502]); + client_return(t, error_message(t, HTTP_ERR_502)); if (!(t->flags & SN_ERR_MASK)) t->flags |= SN_ERR_SRVCL; if (!(t->flags & SN_FINST_MASK)) @@ -2297,7 +2328,7 @@ int process_srv(struct session *t) t->be->failed_resp++; t->srv_state = SV_STCLOSE; t->logs.status = 504; - client_return(t, &t->fe->errmsg[HTTP_ERR_504]); + client_return(t, error_message(t, HTTP_ERR_504)); if (!(t->flags & SN_ERR_MASK)) t->flags |= SN_ERR_SRVTO; if (!(t->flags & SN_FINST_MASK)) @@ -3070,7 +3101,7 @@ int produce_content(struct session *s) else { /* unknown data source */ s->logs.status = 500; - client_retnclose(s, &s->fe->errmsg[HTTP_ERR_500]); + client_retnclose(s, error_message(s, HTTP_ERR_500)); if (!(s->flags & SN_ERR_MASK)) s->flags |= SN_ERR_PRXCOND; if (!(s->flags & SN_FINST_MASK))