mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 22:01:31 +02:00
REORG: cli: move "show errors" out of cli.c
It really belongs to proto_http.c since it's a dump for HTTP request and response errors. Note that it's possible that some parts do not need to be exported anymore since it really is the only place where errors are manipulated.
This commit is contained in:
parent
f13ebdf286
commit
12207b360a
@ -47,7 +47,6 @@ enum {
|
|||||||
STAT_CLI_PROMPT, /* display the prompt (first output, same code) */
|
STAT_CLI_PROMPT, /* display the prompt (first output, same code) */
|
||||||
STAT_CLI_PRINT, /* display message in cli->msg */
|
STAT_CLI_PRINT, /* display message in cli->msg */
|
||||||
STAT_CLI_PRINT_FREE, /* display message in cli->msg. After the display, free the pointer */
|
STAT_CLI_PRINT_FREE, /* display message in cli->msg. After the display, free the pointer */
|
||||||
STAT_CLI_O_ERR, /* dump errors */
|
|
||||||
STAT_CLI_O_ENV, /* dump environment */
|
STAT_CLI_O_ENV, /* dump environment */
|
||||||
STAT_CLI_O_CUSTOM, /* custom callback pointer */
|
STAT_CLI_O_CUSTOM, /* custom callback pointer */
|
||||||
};
|
};
|
||||||
|
184
src/cli.c
184
src/cli.c
@ -56,7 +56,6 @@
|
|||||||
#include <proto/pipe.h>
|
#include <proto/pipe.h>
|
||||||
#include <proto/listener.h>
|
#include <proto/listener.h>
|
||||||
#include <proto/map.h>
|
#include <proto/map.h>
|
||||||
#include <proto/proto_http.h>
|
|
||||||
#include <proto/proto_uxst.h>
|
#include <proto/proto_uxst.h>
|
||||||
#include <proto/proxy.h>
|
#include <proto/proxy.h>
|
||||||
#include <proto/sample.h>
|
#include <proto/sample.h>
|
||||||
@ -68,7 +67,6 @@
|
|||||||
#include <proto/task.h>
|
#include <proto/task.h>
|
||||||
|
|
||||||
static int stats_dump_env_to_buffer(struct stream_interface *si);
|
static int stats_dump_env_to_buffer(struct stream_interface *si);
|
||||||
static int stats_dump_errors_to_buffer(struct stream_interface *si);
|
|
||||||
|
|
||||||
static struct applet cli_applet;
|
static struct applet cli_applet;
|
||||||
|
|
||||||
@ -79,7 +77,6 @@ static const char stats_sock_usage_msg[] =
|
|||||||
" prompt : toggle interactive mode with prompt\n"
|
" prompt : toggle interactive mode with prompt\n"
|
||||||
" quit : disconnect\n"
|
" quit : disconnect\n"
|
||||||
" show env [var] : dump environment variables known to the process\n"
|
" show env [var] : dump environment variables known to the process\n"
|
||||||
" show errors : report last request and response errors for each proxy\n"
|
|
||||||
" set timeout : change a timeout setting\n"
|
" set timeout : change a timeout setting\n"
|
||||||
" set maxconn : change a maxconn setting\n"
|
" set maxconn : change a maxconn setting\n"
|
||||||
" set rate-limit : change a rate limiting value\n"
|
" set rate-limit : change a rate limiting value\n"
|
||||||
@ -577,20 +574,6 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
|
|||||||
appctx->st2 = STAT_ST_END;
|
appctx->st2 = STAT_ST_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(args[1], "errors") == 0) {
|
|
||||||
if (strm_li(s)->bind_conf->level < ACCESS_LVL_OPER) {
|
|
||||||
appctx->ctx.cli.msg = stats_permission_denied_msg;
|
|
||||||
appctx->st0 = STAT_CLI_PRINT;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (*args[2])
|
|
||||||
appctx->ctx.errors.iid = atoi(args[2]);
|
|
||||||
else
|
|
||||||
appctx->ctx.errors.iid = -1;
|
|
||||||
appctx->ctx.errors.px = NULL;
|
|
||||||
appctx->st2 = STAT_ST_INIT;
|
|
||||||
appctx->st0 = STAT_CLI_O_ERR; // stats_dump_errors_to_buffer
|
|
||||||
}
|
|
||||||
else { /* neither "stat" nor "info" nor "sess" nor "errors" nor "table" */
|
else { /* neither "stat" nor "info" nor "sess" nor "errors" nor "table" */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1291,10 +1274,6 @@ static void cli_io_handler(struct appctx *appctx)
|
|||||||
else
|
else
|
||||||
si_applet_cant_put(si);
|
si_applet_cant_put(si);
|
||||||
break;
|
break;
|
||||||
case STAT_CLI_O_ERR: /* errors dump */
|
|
||||||
if (stats_dump_errors_to_buffer(si))
|
|
||||||
appctx->st0 = STAT_CLI_PROMPT;
|
|
||||||
break;
|
|
||||||
case STAT_CLI_O_ENV: /* environment dump */
|
case STAT_CLI_O_ENV: /* environment dump */
|
||||||
if (stats_dump_env_to_buffer(si))
|
if (stats_dump_env_to_buffer(si))
|
||||||
appctx->st0 = STAT_CLI_PROMPT;
|
appctx->st0 = STAT_CLI_PROMPT;
|
||||||
@ -1385,169 +1364,6 @@ static void cli_release_handler(struct appctx *appctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function dumps all captured errors onto the stream interface's
|
|
||||||
* read buffer. It returns 0 if the output buffer is full and it needs
|
|
||||||
* to be called again, otherwise non-zero.
|
|
||||||
*/
|
|
||||||
static int stats_dump_errors_to_buffer(struct stream_interface *si)
|
|
||||||
{
|
|
||||||
struct appctx *appctx = __objt_appctx(si->end);
|
|
||||||
extern const char *monthname[12];
|
|
||||||
|
|
||||||
if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
chunk_reset(&trash);
|
|
||||||
|
|
||||||
if (!appctx->ctx.errors.px) {
|
|
||||||
/* the function had not been called yet, let's prepare the
|
|
||||||
* buffer for a response.
|
|
||||||
*/
|
|
||||||
struct tm tm;
|
|
||||||
|
|
||||||
get_localtime(date.tv_sec, &tm);
|
|
||||||
chunk_appendf(&trash, "Total events captured on [%02d/%s/%04d:%02d:%02d:%02d.%03d] : %u\n",
|
|
||||||
tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
|
|
||||||
tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(date.tv_usec/1000),
|
|
||||||
error_snapshot_id);
|
|
||||||
|
|
||||||
if (bi_putchk(si_ic(si), &trash) == -1) {
|
|
||||||
/* Socket buffer full. Let's try again later from the same point */
|
|
||||||
si_applet_cant_put(si);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
appctx->ctx.errors.px = proxy;
|
|
||||||
appctx->ctx.errors.buf = 0;
|
|
||||||
appctx->ctx.errors.bol = 0;
|
|
||||||
appctx->ctx.errors.ptr = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we have two inner loops here, one for the proxy, the other one for
|
|
||||||
* the buffer.
|
|
||||||
*/
|
|
||||||
while (appctx->ctx.errors.px) {
|
|
||||||
struct error_snapshot *es;
|
|
||||||
|
|
||||||
if (appctx->ctx.errors.buf == 0)
|
|
||||||
es = &appctx->ctx.errors.px->invalid_req;
|
|
||||||
else
|
|
||||||
es = &appctx->ctx.errors.px->invalid_rep;
|
|
||||||
|
|
||||||
if (!es->when.tv_sec)
|
|
||||||
goto next;
|
|
||||||
|
|
||||||
if (appctx->ctx.errors.iid >= 0 &&
|
|
||||||
appctx->ctx.errors.px->uuid != appctx->ctx.errors.iid &&
|
|
||||||
es->oe->uuid != appctx->ctx.errors.iid)
|
|
||||||
goto next;
|
|
||||||
|
|
||||||
if (appctx->ctx.errors.ptr < 0) {
|
|
||||||
/* just print headers now */
|
|
||||||
|
|
||||||
char pn[INET6_ADDRSTRLEN];
|
|
||||||
struct tm tm;
|
|
||||||
int port;
|
|
||||||
|
|
||||||
get_localtime(es->when.tv_sec, &tm);
|
|
||||||
chunk_appendf(&trash, " \n[%02d/%s/%04d:%02d:%02d:%02d.%03d]",
|
|
||||||
tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
|
|
||||||
tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(es->when.tv_usec/1000));
|
|
||||||
|
|
||||||
switch (addr_to_str(&es->src, pn, sizeof(pn))) {
|
|
||||||
case AF_INET:
|
|
||||||
case AF_INET6:
|
|
||||||
port = get_host_port(&es->src);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
port = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (appctx->ctx.errors.buf) {
|
|
||||||
case 0:
|
|
||||||
chunk_appendf(&trash,
|
|
||||||
" frontend %s (#%d): invalid request\n"
|
|
||||||
" backend %s (#%d)",
|
|
||||||
appctx->ctx.errors.px->id, appctx->ctx.errors.px->uuid,
|
|
||||||
(es->oe->cap & PR_CAP_BE) ? es->oe->id : "<NONE>",
|
|
||||||
(es->oe->cap & PR_CAP_BE) ? es->oe->uuid : -1);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
chunk_appendf(&trash,
|
|
||||||
" backend %s (#%d): invalid response\n"
|
|
||||||
" frontend %s (#%d)",
|
|
||||||
appctx->ctx.errors.px->id, appctx->ctx.errors.px->uuid,
|
|
||||||
es->oe->id, es->oe->uuid);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk_appendf(&trash,
|
|
||||||
", server %s (#%d), event #%u\n"
|
|
||||||
" src %s:%d, session #%d, session flags 0x%08x\n"
|
|
||||||
" HTTP msg state %d, msg flags 0x%08x, tx flags 0x%08x\n"
|
|
||||||
" HTTP chunk len %lld bytes, HTTP body len %lld bytes\n"
|
|
||||||
" buffer flags 0x%08x, out %d bytes, total %lld bytes\n"
|
|
||||||
" pending %d bytes, wrapping at %d, error at position %d:\n \n",
|
|
||||||
es->srv ? es->srv->id : "<NONE>", es->srv ? es->srv->puid : -1,
|
|
||||||
es->ev_id,
|
|
||||||
pn, port, es->sid, es->s_flags,
|
|
||||||
es->state, es->m_flags, es->t_flags,
|
|
||||||
es->m_clen, es->m_blen,
|
|
||||||
es->b_flags, es->b_out, es->b_tot,
|
|
||||||
es->len, es->b_wrap, es->pos);
|
|
||||||
|
|
||||||
if (bi_putchk(si_ic(si), &trash) == -1) {
|
|
||||||
/* Socket buffer full. Let's try again later from the same point */
|
|
||||||
si_applet_cant_put(si);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
appctx->ctx.errors.ptr = 0;
|
|
||||||
appctx->ctx.errors.sid = es->sid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appctx->ctx.errors.sid != es->sid) {
|
|
||||||
/* the snapshot changed while we were dumping it */
|
|
||||||
chunk_appendf(&trash,
|
|
||||||
" WARNING! update detected on this snapshot, dump interrupted. Please re-check!\n");
|
|
||||||
if (bi_putchk(si_ic(si), &trash) == -1) {
|
|
||||||
si_applet_cant_put(si);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OK, ptr >= 0, so we have to dump the current line */
|
|
||||||
while (es->buf && appctx->ctx.errors.ptr < es->len && appctx->ctx.errors.ptr < global.tune.bufsize) {
|
|
||||||
int newptr;
|
|
||||||
int newline;
|
|
||||||
|
|
||||||
newline = appctx->ctx.errors.bol;
|
|
||||||
newptr = dump_text_line(&trash, es->buf, global.tune.bufsize, es->len, &newline, appctx->ctx.errors.ptr);
|
|
||||||
if (newptr == appctx->ctx.errors.ptr)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (bi_putchk(si_ic(si), &trash) == -1) {
|
|
||||||
/* Socket buffer full. Let's try again later from the same point */
|
|
||||||
si_applet_cant_put(si);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
appctx->ctx.errors.ptr = newptr;
|
|
||||||
appctx->ctx.errors.bol = newline;
|
|
||||||
};
|
|
||||||
next:
|
|
||||||
appctx->ctx.errors.bol = 0;
|
|
||||||
appctx->ctx.errors.ptr = -1;
|
|
||||||
appctx->ctx.errors.buf++;
|
|
||||||
if (appctx->ctx.errors.buf > 1) {
|
|
||||||
appctx->ctx.errors.buf = 0;
|
|
||||||
appctx->ctx.errors.px = appctx->ctx.errors.px->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dump complete */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function dumps all environmnent variables to the buffer. It returns 0
|
/* This function dumps all environmnent variables to the buffer. It returns 0
|
||||||
* if the output buffer is full and it needs to be called again, otherwise
|
* if the output buffer is full and it needs to be called again, otherwise
|
||||||
* non-zero. Dumps only one entry if st2 == STAT_ST_END.
|
* non-zero. Dumps only one entry if st2 == STAT_ST_END.
|
||||||
|
193
src/proto_http.c
193
src/proto_http.c
@ -39,6 +39,7 @@
|
|||||||
#include <common/version.h>
|
#include <common/version.h>
|
||||||
|
|
||||||
#include <types/capture.h>
|
#include <types/capture.h>
|
||||||
|
#include <types/cli.h>
|
||||||
#include <types/filters.h>
|
#include <types/filters.h>
|
||||||
#include <types/global.h>
|
#include <types/global.h>
|
||||||
#include <types/stats.h>
|
#include <types/stats.h>
|
||||||
@ -50,6 +51,7 @@
|
|||||||
#include <proto/backend.h>
|
#include <proto/backend.h>
|
||||||
#include <proto/channel.h>
|
#include <proto/channel.h>
|
||||||
#include <proto/checks.h>
|
#include <proto/checks.h>
|
||||||
|
#include <proto/cli.h>
|
||||||
#include <proto/compression.h>
|
#include <proto/compression.h>
|
||||||
#include <proto/stats.h>
|
#include <proto/stats.h>
|
||||||
#include <proto/fd.h>
|
#include <proto/fd.h>
|
||||||
@ -12823,6 +12825,196 @@ struct action_kw *action_http_res_custom(const char *kw)
|
|||||||
return action_lookup(&http_res_keywords.list, kw);
|
return action_lookup(&http_res_keywords.list, kw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* "show errors" handler for the CLI. Returns 0 if wants to continue, 1 to stop
|
||||||
|
* now.
|
||||||
|
*/
|
||||||
|
static int cli_parse_show_errors(char **args, struct appctx *appctx, void *private)
|
||||||
|
{
|
||||||
|
if (!cli_has_level(appctx, ACCESS_LVL_OPER))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (*args[2])
|
||||||
|
appctx->ctx.errors.iid = atoi(args[2]);
|
||||||
|
else
|
||||||
|
appctx->ctx.errors.iid = -1;
|
||||||
|
appctx->ctx.errors.px = NULL;
|
||||||
|
appctx->st2 = STAT_ST_INIT;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function dumps all captured errors onto the stream interface's
|
||||||
|
* read buffer. It returns 0 if the output buffer is full and it needs
|
||||||
|
* to be called again, otherwise non-zero.
|
||||||
|
*/
|
||||||
|
static int cli_io_handler_show_errors(struct appctx *appctx)
|
||||||
|
{
|
||||||
|
struct stream_interface *si = appctx->owner;
|
||||||
|
extern const char *monthname[12];
|
||||||
|
|
||||||
|
if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
chunk_reset(&trash);
|
||||||
|
|
||||||
|
if (!appctx->ctx.errors.px) {
|
||||||
|
/* the function had not been called yet, let's prepare the
|
||||||
|
* buffer for a response.
|
||||||
|
*/
|
||||||
|
struct tm tm;
|
||||||
|
|
||||||
|
get_localtime(date.tv_sec, &tm);
|
||||||
|
chunk_appendf(&trash, "Total events captured on [%02d/%s/%04d:%02d:%02d:%02d.%03d] : %u\n",
|
||||||
|
tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
|
||||||
|
tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(date.tv_usec/1000),
|
||||||
|
error_snapshot_id);
|
||||||
|
|
||||||
|
if (bi_putchk(si_ic(si), &trash) == -1) {
|
||||||
|
/* Socket buffer full. Let's try again later from the same point */
|
||||||
|
si_applet_cant_put(si);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
appctx->ctx.errors.px = proxy;
|
||||||
|
appctx->ctx.errors.buf = 0;
|
||||||
|
appctx->ctx.errors.bol = 0;
|
||||||
|
appctx->ctx.errors.ptr = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we have two inner loops here, one for the proxy, the other one for
|
||||||
|
* the buffer.
|
||||||
|
*/
|
||||||
|
while (appctx->ctx.errors.px) {
|
||||||
|
struct error_snapshot *es;
|
||||||
|
|
||||||
|
if (appctx->ctx.errors.buf == 0)
|
||||||
|
es = &appctx->ctx.errors.px->invalid_req;
|
||||||
|
else
|
||||||
|
es = &appctx->ctx.errors.px->invalid_rep;
|
||||||
|
|
||||||
|
if (!es->when.tv_sec)
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
if (appctx->ctx.errors.iid >= 0 &&
|
||||||
|
appctx->ctx.errors.px->uuid != appctx->ctx.errors.iid &&
|
||||||
|
es->oe->uuid != appctx->ctx.errors.iid)
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
if (appctx->ctx.errors.ptr < 0) {
|
||||||
|
/* just print headers now */
|
||||||
|
|
||||||
|
char pn[INET6_ADDRSTRLEN];
|
||||||
|
struct tm tm;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
get_localtime(es->when.tv_sec, &tm);
|
||||||
|
chunk_appendf(&trash, " \n[%02d/%s/%04d:%02d:%02d:%02d.%03d]",
|
||||||
|
tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
|
||||||
|
tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(es->when.tv_usec/1000));
|
||||||
|
|
||||||
|
switch (addr_to_str(&es->src, pn, sizeof(pn))) {
|
||||||
|
case AF_INET:
|
||||||
|
case AF_INET6:
|
||||||
|
port = get_host_port(&es->src);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
port = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (appctx->ctx.errors.buf) {
|
||||||
|
case 0:
|
||||||
|
chunk_appendf(&trash,
|
||||||
|
" frontend %s (#%d): invalid request\n"
|
||||||
|
" backend %s (#%d)",
|
||||||
|
appctx->ctx.errors.px->id, appctx->ctx.errors.px->uuid,
|
||||||
|
(es->oe->cap & PR_CAP_BE) ? es->oe->id : "<NONE>",
|
||||||
|
(es->oe->cap & PR_CAP_BE) ? es->oe->uuid : -1);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
chunk_appendf(&trash,
|
||||||
|
" backend %s (#%d): invalid response\n"
|
||||||
|
" frontend %s (#%d)",
|
||||||
|
appctx->ctx.errors.px->id, appctx->ctx.errors.px->uuid,
|
||||||
|
es->oe->id, es->oe->uuid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk_appendf(&trash,
|
||||||
|
", server %s (#%d), event #%u\n"
|
||||||
|
" src %s:%d, session #%d, session flags 0x%08x\n"
|
||||||
|
" HTTP msg state %d, msg flags 0x%08x, tx flags 0x%08x\n"
|
||||||
|
" HTTP chunk len %lld bytes, HTTP body len %lld bytes\n"
|
||||||
|
" buffer flags 0x%08x, out %d bytes, total %lld bytes\n"
|
||||||
|
" pending %d bytes, wrapping at %d, error at position %d:\n \n",
|
||||||
|
es->srv ? es->srv->id : "<NONE>", es->srv ? es->srv->puid : -1,
|
||||||
|
es->ev_id,
|
||||||
|
pn, port, es->sid, es->s_flags,
|
||||||
|
es->state, es->m_flags, es->t_flags,
|
||||||
|
es->m_clen, es->m_blen,
|
||||||
|
es->b_flags, es->b_out, es->b_tot,
|
||||||
|
es->len, es->b_wrap, es->pos);
|
||||||
|
|
||||||
|
if (bi_putchk(si_ic(si), &trash) == -1) {
|
||||||
|
/* Socket buffer full. Let's try again later from the same point */
|
||||||
|
si_applet_cant_put(si);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
appctx->ctx.errors.ptr = 0;
|
||||||
|
appctx->ctx.errors.sid = es->sid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appctx->ctx.errors.sid != es->sid) {
|
||||||
|
/* the snapshot changed while we were dumping it */
|
||||||
|
chunk_appendf(&trash,
|
||||||
|
" WARNING! update detected on this snapshot, dump interrupted. Please re-check!\n");
|
||||||
|
if (bi_putchk(si_ic(si), &trash) == -1) {
|
||||||
|
si_applet_cant_put(si);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OK, ptr >= 0, so we have to dump the current line */
|
||||||
|
while (es->buf && appctx->ctx.errors.ptr < es->len && appctx->ctx.errors.ptr < global.tune.bufsize) {
|
||||||
|
int newptr;
|
||||||
|
int newline;
|
||||||
|
|
||||||
|
newline = appctx->ctx.errors.bol;
|
||||||
|
newptr = dump_text_line(&trash, es->buf, global.tune.bufsize, es->len, &newline, appctx->ctx.errors.ptr);
|
||||||
|
if (newptr == appctx->ctx.errors.ptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (bi_putchk(si_ic(si), &trash) == -1) {
|
||||||
|
/* Socket buffer full. Let's try again later from the same point */
|
||||||
|
si_applet_cant_put(si);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
appctx->ctx.errors.ptr = newptr;
|
||||||
|
appctx->ctx.errors.bol = newline;
|
||||||
|
};
|
||||||
|
next:
|
||||||
|
appctx->ctx.errors.bol = 0;
|
||||||
|
appctx->ctx.errors.ptr = -1;
|
||||||
|
appctx->ctx.errors.buf++;
|
||||||
|
if (appctx->ctx.errors.buf > 1) {
|
||||||
|
appctx->ctx.errors.buf = 0;
|
||||||
|
appctx->ctx.errors.px = appctx->ctx.errors.px->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dump complete */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* register cli keywords */
|
||||||
|
static struct cli_kw_list cli_kws = {{ },{
|
||||||
|
{ { "show", "errors", NULL },
|
||||||
|
"show errors : report last request and response errors for each proxy",
|
||||||
|
cli_parse_show_errors, cli_io_handler_show_errors, NULL,
|
||||||
|
},
|
||||||
|
{{},}
|
||||||
|
}};
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* All supported ACL keywords must be declared here. */
|
/* All supported ACL keywords must be declared here. */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
@ -13076,6 +13268,7 @@ static void __http_protocol_init(void)
|
|||||||
sample_register_convs(&sample_conv_kws);
|
sample_register_convs(&sample_conv_kws);
|
||||||
http_req_keywords_register(&http_req_actions);
|
http_req_keywords_register(&http_req_actions);
|
||||||
http_res_keywords_register(&http_res_actions);
|
http_res_keywords_register(&http_res_actions);
|
||||||
|
cli_register_kw(&cli_kws);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user