mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-22 14:21:25 +02:00
MEDIUM: http-htx/proxy: Use a global and centralized storage for HTTP error messages
All custom HTTP errors are now stored in a global tree. Proxies use a references on these messages. The key used for errorfile directives is the file name as specified in the configuration. For errorloc directives, a key is created using the redirect code and the url. This means that the same custom error message is now stored only once. It may be used in several proxies or for several status code, it is only parsed and stored once.
This commit is contained in:
parent
ac2412fee8
commit
5885775de1
@ -49,9 +49,9 @@ unsigned int http_get_htx_fhdr(const struct htx *htx, const struct ist hdr,
|
|||||||
int occ, struct http_hdr_ctx *ctx, char **vptr, size_t *vlen);
|
int occ, struct http_hdr_ctx *ctx, char **vptr, size_t *vlen);
|
||||||
int http_str_to_htx(struct buffer *buf, struct ist raw);
|
int http_str_to_htx(struct buffer *buf, struct ist raw);
|
||||||
|
|
||||||
int http_load_errorfile(const char *file, struct buffer *buf, char **errmsg);
|
struct buffer *http_load_errorfile(const char *file, char **errmsg);
|
||||||
int http_load_errormsg(const struct ist msg, struct buffer *buf, char **errmsg);
|
struct buffer *http_load_errormsg(const char *key, const struct ist msg, char **errmsg);
|
||||||
int http_parse_errorfile(int status, const char *file, struct buffer *buf, char **errmsg);
|
struct buffer *http_parse_errorfile(int status, const char *file, char **errmsg);
|
||||||
int http_parse_errorloc(int errloc, int status, const char *url, struct buffer *buf, char **errmsg);
|
struct buffer *http_parse_errorloc(int errloc, int status, const char *url, char **errmsg);
|
||||||
|
|
||||||
#endif /* _PROTO_HTTP_HTX_H */
|
#endif /* _PROTO_HTTP_HTX_H */
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
#ifndef _TYPES_HTTP_HTX_H
|
#ifndef _TYPES_HTTP_HTX_H
|
||||||
#define _TYPES_HTTP_HTX_H
|
#define _TYPES_HTTP_HTX_H
|
||||||
|
|
||||||
|
#include <ebistree.h>
|
||||||
|
|
||||||
|
#include <common/buf.h>
|
||||||
#include <common/htx.h>
|
#include <common/htx.h>
|
||||||
#include <common/ist.h>
|
#include <common/ist.h>
|
||||||
|
|
||||||
@ -34,4 +37,12 @@ struct http_hdr_ctx {
|
|||||||
uint16_t lws_after;
|
uint16_t lws_after;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* A custom HTTP error message load from a row file and converted in HTX. The
|
||||||
|
* node key is the file path.
|
||||||
|
*/
|
||||||
|
struct http_error {
|
||||||
|
struct buffer msg;
|
||||||
|
struct ebpt_node node;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* _TYPES_HTTP_HTX_H */
|
#endif /* _TYPES_HTTP_HTX_H */
|
||||||
|
@ -427,7 +427,7 @@ struct proxy {
|
|||||||
char *check_path; /* PATH environment to use for external agent checks */
|
char *check_path; /* PATH environment to use for external agent checks */
|
||||||
char *expect_str; /* http-check expected content : string or text version of the regex */
|
char *expect_str; /* http-check expected content : string or text version of the regex */
|
||||||
struct my_regex *expect_regex; /* http-check expected content */
|
struct my_regex *expect_regex; /* http-check expected content */
|
||||||
struct buffer errmsg[HTTP_ERR_SIZE]; /* default or customized error messages for known errors */
|
struct buffer *errmsg[HTTP_ERR_SIZE]; /* default or customized error messages for known errors */
|
||||||
int uuid; /* universally unique proxy ID, used for SNMP */
|
int uuid; /* universally unique proxy ID, used for SNMP */
|
||||||
unsigned int backlog; /* force the frontend's listen backlog */
|
unsigned int backlog; /* force the frontend's listen backlog */
|
||||||
unsigned long bind_proc; /* bitmask of processes using this proxy */
|
unsigned long bind_proc; /* bitmask of processes using this proxy */
|
||||||
|
@ -262,8 +262,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* initialize error relocations */
|
/* initialize error relocations */
|
||||||
for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
|
memcpy(&curproxy->errmsg, &defproxy.errmsg, sizeof(defproxy.errmsg));
|
||||||
chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
|
|
||||||
|
|
||||||
if (curproxy->cap & PR_CAP_FE) {
|
if (curproxy->cap & PR_CAP_FE) {
|
||||||
curproxy->maxconn = defproxy.maxconn;
|
curproxy->maxconn = defproxy.maxconn;
|
||||||
@ -503,8 +502,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||||||
free(defproxy.conf.logformat_sd_string);
|
free(defproxy.conf.logformat_sd_string);
|
||||||
free(defproxy.conf.lfsd_file);
|
free(defproxy.conf.lfsd_file);
|
||||||
|
|
||||||
for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
|
memset(&defproxy.errmsg, 0, sizeof(defproxy.errmsg));
|
||||||
chunk_destroy(&defproxy.errmsg[rc]);
|
|
||||||
|
|
||||||
/* we cannot free uri_auth because it might already be used */
|
/* we cannot free uri_auth because it might already be used */
|
||||||
init_default_instance();
|
init_default_instance();
|
||||||
@ -3810,8 +3808,8 @@ stats_error_parsing:
|
|||||||
else if (!strcmp(args[0], "errorloc") ||
|
else if (!strcmp(args[0], "errorloc") ||
|
||||||
!strcmp(args[0], "errorloc302") ||
|
!strcmp(args[0], "errorloc302") ||
|
||||||
!strcmp(args[0], "errorloc303")) { /* error location */
|
!strcmp(args[0], "errorloc303")) { /* error location */
|
||||||
struct buffer chk;
|
struct buffer *msg;
|
||||||
int errloc, status, rc;
|
int errloc, status;
|
||||||
|
|
||||||
if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
|
if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
|
||||||
err_code |= ERR_WARN;
|
err_code |= ERR_WARN;
|
||||||
@ -3824,39 +3822,38 @@ stats_error_parsing:
|
|||||||
|
|
||||||
status = atol(args[1]);
|
status = atol(args[1]);
|
||||||
errloc = (!strcmp(args[0], "errorloc303") ? 303 : 302);
|
errloc = (!strcmp(args[0], "errorloc303") ? 303 : 302);
|
||||||
rc = http_parse_errorloc(errloc, status, args[2], &chk, &errmsg);
|
msg = http_parse_errorloc(errloc, status, args[2], &errmsg);
|
||||||
if (rc == -1) {
|
if (!msg) {
|
||||||
ha_alert("parsing [%s:%d] : %s: %s\n", file, linenum, args[0], errmsg);
|
ha_alert("parsing [%s:%d] : %s: %s\n", file, linenum, args[0], errmsg);
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
rc = http_get_status_idx(status);
|
||||||
chunk_destroy(&curproxy->errmsg[rc]);
|
curproxy->errmsg[rc] = msg;
|
||||||
curproxy->errmsg[rc] = chk;
|
|
||||||
}
|
}
|
||||||
else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
|
else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
|
||||||
struct buffer chk;
|
struct buffer *msg;
|
||||||
int status, rc;
|
int status;
|
||||||
|
|
||||||
if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
|
if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
|
||||||
err_code |= ERR_WARN;
|
err_code |= ERR_WARN;
|
||||||
|
|
||||||
if (*(args[1]) == 0 || *(args[2]) == 0) {
|
if (*(args[1]) == 0 || *(args[2]) == 0) {
|
||||||
ha_alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
|
ha_alert("parsing [%s:%d] : %s: expects <status_code> and <file> as arguments.\n",
|
||||||
|
file, linenum, args[0]);
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = atol(args[1]);
|
status = atol(args[1]);
|
||||||
rc = http_parse_errorfile(status, args[2], &chk, &errmsg);
|
msg = http_parse_errorfile(status, args[2], &errmsg);
|
||||||
if (rc == -1) {
|
if (!msg) {
|
||||||
ha_alert("parsing [%s:%d] : %s: %s\n", file, linenum, args[0], errmsg);
|
ha_alert("parsing [%s:%d] : %s: %s\n", file, linenum, args[0], errmsg);
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
rc = http_get_status_idx(status);
|
||||||
chunk_destroy(&curproxy->errmsg[rc]);
|
curproxy->errmsg[rc] = msg;
|
||||||
curproxy->errmsg[rc] = chk;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct cfg_kw_list *kwl;
|
struct cfg_kw_list *kwl;
|
||||||
|
@ -2331,7 +2331,6 @@ void deinit(void)
|
|||||||
struct post_deinit_fct *pdf;
|
struct post_deinit_fct *pdf;
|
||||||
struct proxy_deinit_fct *pxdf;
|
struct proxy_deinit_fct *pxdf;
|
||||||
struct server_deinit_fct *srvdf;
|
struct server_deinit_fct *srvdf;
|
||||||
int i;
|
|
||||||
|
|
||||||
deinit_signals();
|
deinit_signals();
|
||||||
while (p) {
|
while (p) {
|
||||||
@ -2359,9 +2358,6 @@ void deinit(void)
|
|||||||
free(p->conf.logformat_sd_string);
|
free(p->conf.logformat_sd_string);
|
||||||
free(p->conf.lfsd_file);
|
free(p->conf.lfsd_file);
|
||||||
|
|
||||||
for (i = 0; i < HTTP_ERR_SIZE; i++)
|
|
||||||
chunk_destroy(&p->errmsg[i]);
|
|
||||||
|
|
||||||
list_for_each_entry_safe(cond, condb, &p->mon_fail_cond, list) {
|
list_for_each_entry_safe(cond, condb, &p->mon_fail_cond, list) {
|
||||||
LIST_DEL(&cond->list);
|
LIST_DEL(&cond->list);
|
||||||
prune_acl_cond(cond);
|
prune_acl_cond(cond);
|
||||||
|
@ -4597,10 +4597,10 @@ struct buffer *http_error_message(struct stream *s)
|
|||||||
{
|
{
|
||||||
const int msgnum = http_get_status_idx(s->txn->status);
|
const int msgnum = http_get_status_idx(s->txn->status);
|
||||||
|
|
||||||
if (s->be->errmsg[msgnum].area)
|
if (s->be->errmsg[msgnum])
|
||||||
return &s->be->errmsg[msgnum];
|
return s->be->errmsg[msgnum];
|
||||||
else if (strm_fe(s)->errmsg[msgnum].area)
|
else if (strm_fe(s)->errmsg[msgnum])
|
||||||
return &strm_fe(s)->errmsg[msgnum];
|
return strm_fe(s)->errmsg[msgnum];
|
||||||
else
|
else
|
||||||
return &http_err_chunks[msgnum];
|
return &http_err_chunks[msgnum];
|
||||||
}
|
}
|
||||||
|
163
src/http_htx.c
163
src/http_htx.c
@ -29,6 +29,7 @@
|
|||||||
#include <proto/sample.h>
|
#include <proto/sample.h>
|
||||||
|
|
||||||
struct buffer http_err_chunks[HTTP_ERR_SIZE];
|
struct buffer http_err_chunks[HTTP_ERR_SIZE];
|
||||||
|
struct eb_root http_error_messages = EB_ROOT;
|
||||||
|
|
||||||
static int http_update_authority(struct htx *htx, struct htx_sl *sl, const struct ist host);
|
static int http_update_authority(struct htx *htx, struct htx_sl *sl, const struct ist host);
|
||||||
static int http_update_host(struct htx *htx, struct htx_sl *sl, const struct ist uri);
|
static int http_update_host(struct htx *htx, struct htx_sl *sl, const struct ist uri);
|
||||||
@ -836,21 +837,50 @@ end:
|
|||||||
return err_code;
|
return err_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER_CONFIG_POSTPARSER("http_htx", http_htx_init);
|
static void http_htx_deinit(void)
|
||||||
|
|
||||||
/* Reads content of an error file and convert it in an HTX message. On success,
|
|
||||||
* the result is stored in <buf> and 1 is returned. On error, 0 is returned and
|
|
||||||
* an error message is written into the <errmsg> buffer. It is this function
|
|
||||||
* responsibility to allocate <buf> and to release it if an error occurred.
|
|
||||||
*/
|
|
||||||
int http_load_errorfile(const char *file, struct buffer *buf, char **errmsg)
|
|
||||||
{
|
{
|
||||||
|
struct ebpt_node *node, *next;
|
||||||
|
struct http_error *http_err;
|
||||||
|
|
||||||
|
node = ebpt_first(&http_error_messages);
|
||||||
|
while (node) {
|
||||||
|
next = ebpt_next(node);
|
||||||
|
ebpt_delete(node);
|
||||||
|
http_err = container_of(node, typeof(*http_err), node);
|
||||||
|
chunk_destroy(&http_err->msg);
|
||||||
|
free(node->key);
|
||||||
|
free(http_err);
|
||||||
|
node = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_CONFIG_POSTPARSER("http_htx", http_htx_init);
|
||||||
|
REGISTER_POST_DEINIT(http_htx_deinit);
|
||||||
|
|
||||||
|
/* Reads content of the error file <file> and convert it into an HTX message. On
|
||||||
|
* success, the HTX message is returned. On error, NULL is returned and an error
|
||||||
|
* message is written into the <errmsg> buffer.
|
||||||
|
*/
|
||||||
|
struct buffer *http_load_errorfile(const char *file, char **errmsg)
|
||||||
|
{
|
||||||
|
struct buffer *buf = NULL;
|
||||||
|
struct buffer chk;
|
||||||
|
struct ebpt_node *node;
|
||||||
|
struct http_error *http_err;
|
||||||
struct stat stat;
|
struct stat stat;
|
||||||
char *err = NULL;
|
char *err = NULL;
|
||||||
int errnum, errlen;
|
int errnum, errlen;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
|
/* already loaded */
|
||||||
|
node = ebis_lookup_len(&http_error_messages, file, strlen(file));
|
||||||
|
if (node) {
|
||||||
|
http_err = container_of(node, typeof(*http_err), node);
|
||||||
|
buf = &http_err->msg;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the error file content */
|
||||||
fd = open(file, O_RDONLY);
|
fd = open(file, O_RDONLY);
|
||||||
if ((fd < 0) || (fstat(fd, &stat) < 0)) {
|
if ((fd < 0) || (fstat(fd, &stat) < 0)) {
|
||||||
memprintf(errmsg, "error opening file '%s'.", file);
|
memprintf(errmsg, "error opening file '%s'.", file);
|
||||||
@ -877,78 +907,125 @@ int http_load_errorfile(const char *file, struct buffer *buf, char **errmsg)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!http_str_to_htx(buf, ist2(err, errlen))) {
|
/* Create the node corresponding to the error file */
|
||||||
memprintf(errmsg, "unable to convert custom error message file '%s' in HTX.", file);
|
http_err = calloc(1, sizeof(*http_err));
|
||||||
|
if (!http_err) {
|
||||||
|
memprintf(errmsg, "out of memory.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
http_err->node.key = strdup(file);
|
||||||
|
if (!http_err->node.key) {
|
||||||
|
memprintf(errmsg, "out of memory.");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 1;
|
/* Convert the error file into an HTX message */
|
||||||
|
if (!http_str_to_htx(&chk, ist2(err, errlen))) {
|
||||||
|
memprintf(errmsg, "unable to convert custom error message file '%s' in HTX.", file);
|
||||||
|
free(http_err->node.key);
|
||||||
|
free(http_err);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert the node in the tree and return the HTX message */
|
||||||
|
http_err->msg = chk;
|
||||||
|
ebis_insert(&http_error_messages, &http_err->node);
|
||||||
|
buf = &http_err->msg;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
close(fd);
|
close(fd);
|
||||||
free(err);
|
free(err);
|
||||||
return ret;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert the raw http message <msg> into an HTX message. On success, the
|
/* Convert the raw http message <msg> into an HTX message. On sucess, the HTX
|
||||||
* result is stored in <buf> and 1 is returned. On error, 0 is returned and an
|
* message is returned. On error, NULL is returned and an error message is
|
||||||
* error message is written into the <errmsg> buffer. It is this function
|
* written into the <errmsg> buffer.
|
||||||
* responsibility to allocate <buf> and to release it if an error occurred.
|
|
||||||
*/
|
*/
|
||||||
int http_load_errormsg(const struct ist msg, struct buffer *buf, char **errmsg)
|
struct buffer *http_load_errormsg(const char *key, const struct ist msg, char **errmsg)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
struct buffer *buf = NULL;
|
||||||
|
struct buffer chk;
|
||||||
|
struct ebpt_node *node;
|
||||||
|
struct http_error *http_err;
|
||||||
|
|
||||||
/* Convert the error file into an HTX message */
|
/* already loaded */
|
||||||
if (!http_str_to_htx(buf, msg)) {
|
node = ebis_lookup_len(&http_error_messages, key, strlen(key));
|
||||||
memprintf(errmsg, "unable to convert message in HTX.");
|
if (node) {
|
||||||
|
http_err = container_of(node, typeof(*http_err), node);
|
||||||
|
buf = &http_err->msg;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* Create the node corresponding to the error file */
|
||||||
|
http_err = calloc(1, sizeof(*http_err));
|
||||||
|
if (!http_err) {
|
||||||
|
memprintf(errmsg, "out of memory.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
http_err->node.key = strdup(key);
|
||||||
|
if (!http_err->node.key) {
|
||||||
|
memprintf(errmsg, "out of memory.");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = 1;
|
|
||||||
|
|
||||||
|
/* Convert the error file into an HTX message */
|
||||||
|
if (!http_str_to_htx(&chk, msg)) {
|
||||||
|
memprintf(errmsg, "unable to convert message in HTX.");
|
||||||
|
free(http_err->node.key);
|
||||||
|
free(http_err);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert the node in the tree and return the HTX message */
|
||||||
|
http_err->msg = chk;
|
||||||
|
ebis_insert(&http_error_messages, &http_err->node);
|
||||||
|
buf = &http_err->msg;
|
||||||
out:
|
out:
|
||||||
return ret;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function parses the raw HTTP error file <file> for the status code
|
/* This function parses the raw HTTP error file <file> for the status code
|
||||||
* <status>. On success, it returns the HTTP_ERR_* value corresponding to the
|
* <status>. It returns NULL if there is any error, otherwise it return the
|
||||||
* specified status code and it allocated and fills the buffer <buf> with the
|
* corresponding HTX message.
|
||||||
* HTX message. On error, it returns -1 and nothing is allocated.
|
|
||||||
*/
|
*/
|
||||||
int http_parse_errorfile(int status, const char *file, struct buffer *buf, char **errmsg)
|
struct buffer *http_parse_errorfile(int status, const char *file, char **errmsg)
|
||||||
{
|
{
|
||||||
int rc, ret = -1;
|
struct buffer *buf = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
|
for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
|
||||||
if (http_err_codes[rc] == status) {
|
if (http_err_codes[rc] == status) {
|
||||||
if (http_load_errorfile(file, buf, errmsg))
|
buf = http_load_errorfile(file, errmsg);
|
||||||
ret = rc;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc >= HTTP_ERR_SIZE)
|
if (rc >= HTTP_ERR_SIZE)
|
||||||
memprintf(errmsg, "status code '%d' not handled.", status);
|
memprintf(errmsg, "status code '%d' not handled.", status);
|
||||||
return ret;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function creates HTX error message corresponding to a redirect message
|
/* This function creates HTX error message corresponding to a redirect message
|
||||||
* for the status code <status>. <url> is used as location url for the
|
* for the status code <status>. <url> is used as location url for the
|
||||||
* redirect. <errloc> is used to know if it is a 302 or a 303 redirect. On
|
* redirect. <errloc> is used to know if it is a 302 or a 303 redirect. It
|
||||||
* success, it returns the HTTP_ERR_* value corresponding to the specified
|
* returns NULL if there is any error, otherwise it return the corresponding HTX
|
||||||
* status code and it allocated and fills the buffer <buf> with the HTX
|
* message.
|
||||||
* message. On error, it returns -1 and nothing is allocated.
|
|
||||||
*/
|
*/
|
||||||
int http_parse_errorloc(int errloc, int status, const char *url, struct buffer *buf, char **errmsg)
|
struct buffer *http_parse_errorloc(int errloc, int status, const char *url, char **errmsg)
|
||||||
{
|
{
|
||||||
|
struct buffer *buf = NULL;
|
||||||
const char *msg;
|
const char *msg;
|
||||||
char *err = NULL;
|
char *key = NULL, *err = NULL;
|
||||||
int rc, errlen;
|
int rc, errlen;
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
|
for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
|
||||||
if (http_err_codes[rc] == status) {
|
if (http_err_codes[rc] == status) {
|
||||||
|
/* Create the error key */
|
||||||
|
if (!memprintf(&key, "errorloc%d %s", errloc, url)) {
|
||||||
|
memprintf(errmsg, "out of memory.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
/* Create the error message */
|
/* Create the error message */
|
||||||
msg = (errloc == 302 ? HTTP_302 : HTTP_303);
|
msg = (errloc == 302 ? HTTP_302 : HTTP_303);
|
||||||
errlen = strlen(msg) + strlen(url) + 5;
|
errlen = strlen(msg) + strlen(url) + 5;
|
||||||
@ -960,8 +1037,7 @@ int http_parse_errorloc(int errloc, int status, const char *url, struct buffer *
|
|||||||
errlen = snprintf(err, errlen, "%s%s\r\n\r\n", msg, url);
|
errlen = snprintf(err, errlen, "%s%s\r\n\r\n", msg, url);
|
||||||
|
|
||||||
/* Load it */
|
/* Load it */
|
||||||
if (http_load_errormsg(ist2(err, errlen), buf, errmsg))
|
buf = http_load_errormsg(key, ist2(err, errlen), errmsg);
|
||||||
ret = rc;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -969,8 +1045,9 @@ int http_parse_errorloc(int errloc, int status, const char *url, struct buffer *
|
|||||||
if (rc >= HTTP_ERR_SIZE)
|
if (rc >= HTTP_ERR_SIZE)
|
||||||
memprintf(errmsg, "status code '%d' not handled.", status);
|
memprintf(errmsg, "status code '%d' not handled.", status);
|
||||||
out:
|
out:
|
||||||
|
free(key);
|
||||||
free(err);
|
free(err);
|
||||||
return ret;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user