mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-27 13:28:32 +00:00
MINOR: http-fetch: Add a sample to retrieve the server status code
The code returned by the "status" sample fetch is the one in the HTTP response at the moment the sample is evaluated. It may be the status code in the server response or the one of the HAProxy reply in case of error, deny, redirect... However, it could be handy to retrieve the status code returned by the server, when a HTTP response was really received from it. It is the purpose of the "server_status" sample fetch. The server status code itself is stored in the HTTP txn.
This commit is contained in:
parent
263f4e3d9c
commit
b2f82b2b51
@ -22822,6 +22822,10 @@ resp_ver : string (deprecated)
|
||||
ACL derivatives :
|
||||
resp.ver : exact string match
|
||||
|
||||
server_status : integer
|
||||
Return an integer containing the HTTP status code as received from the
|
||||
server. If no response was received from the server, the sample fetch fails.
|
||||
|
||||
set-cookie([<name>]) : string (deprecated)
|
||||
This extracts the last occurrence of the cookie name <name> on a "Set-Cookie"
|
||||
header line from the response and uses the corresponding value to match. This
|
||||
|
@ -239,7 +239,8 @@ struct http_txn {
|
||||
unsigned int flags; /* transaction flags */
|
||||
enum http_meth_t meth; /* HTTP method */
|
||||
/* 1 unused byte here */
|
||||
short status; /* HTTP status from the server, negative if from proxy */
|
||||
short status; /* HTTP status sent to the client, negative if not set */
|
||||
short server_status; /* HTTP status received from the server, negative if not received */
|
||||
struct http_reply *http_reply; /* The HTTP reply to use as reply */
|
||||
struct buffer l7_buffer; /* To store the data, in case we have to retry */
|
||||
char cache_hash[20]; /* Store the cache hash */
|
||||
|
@ -1429,7 +1429,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
}
|
||||
|
||||
/* 1: get the status code and the version. Also set HTTP flags */
|
||||
txn->status = sl->info.res.status;
|
||||
txn->server_status = txn->status = sl->info.res.status;
|
||||
if (sl->flags & HTX_SL_F_VER_11)
|
||||
msg->flags |= HTTP_MSGF_VER_11;
|
||||
if (sl->flags & HTX_SL_F_XFER_LEN) {
|
||||
@ -1488,7 +1488,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
htx->first = channel_htx_fwd_headers(rep, htx);
|
||||
msg->msg_state = HTTP_MSG_RPBEFORE;
|
||||
msg->flags = 0;
|
||||
txn->status = 0;
|
||||
txn->server_status = txn->status = 0;
|
||||
s->logs.t_data = -1; /* was not a response yet */
|
||||
s->scf->flags |= SC_FL_SND_ASAP; /* Send ASAP informational messages */
|
||||
goto next_one;
|
||||
@ -5036,6 +5036,7 @@ struct http_txn *http_create_txn(struct stream *s)
|
||||
txn->meth = HTTP_METH_OTHER;
|
||||
txn->flags = ((sc && sc_ep_test(sc, SE_FL_NOT_FIRST)) ? TX_NOT_FIRST : 0);
|
||||
txn->status = -1;
|
||||
txn->server_status = -1;
|
||||
txn->http_reply = NULL;
|
||||
txn->l7_buffer = BUF_NULL;
|
||||
write_u32(txn->cache_hash, 0);
|
||||
|
@ -311,8 +311,12 @@ struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, struct che
|
||||
if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
|
||||
s->flags |= SF_REDIRECTABLE;
|
||||
}
|
||||
else if (txn->status == -1)
|
||||
txn->status = sl->info.res.status;
|
||||
else {
|
||||
if (txn->status == -1)
|
||||
txn->status = sl->info.res.status;
|
||||
if (!(htx->flags & HTX_FL_PROXY_RESP) && txn->server_status == -1)
|
||||
txn->server_status = sl->info.res.status;
|
||||
}
|
||||
if (sl->flags & HTX_SL_F_VER_11)
|
||||
msg->flags |= HTTP_MSGF_VER_11;
|
||||
}
|
||||
@ -441,6 +445,28 @@ static int smp_fetch_stcode(const struct arg *args, struct sample *smp, const ch
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* It returns the server status code */
|
||||
static int smp_fetch_srv_status(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
||||
{
|
||||
struct http_txn *txn;
|
||||
|
||||
txn = (smp->strm ? smp->strm->txn : NULL);
|
||||
if (!txn)
|
||||
return 0;
|
||||
|
||||
if (txn->server_status == -1) {
|
||||
struct channel *chn = SMP_RES_CHN(smp);
|
||||
struct htx *htx = smp_prefetch_htx(smp, chn, NULL, 1);
|
||||
|
||||
if (!htx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
smp->data.type = SMP_T_SINT;
|
||||
smp->data.u.sint = txn->server_status;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int smp_fetch_uniqueid(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
||||
{
|
||||
struct ist unique_id;
|
||||
@ -2298,6 +2324,8 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
|
||||
{ "res.hdr_names", smp_fetch_hdr_names, ARG1(0,STR), NULL, SMP_T_STR, SMP_USE_HRSHV },
|
||||
{ "res.hdr_val", smp_fetch_hdr_val, ARG2(0,STR,SINT), val_hdr, SMP_T_SINT, SMP_USE_HRSHV },
|
||||
|
||||
{ "server_status", smp_fetch_srv_status, 0, NULL, SMP_T_SINT, SMP_USE_HRSHP },
|
||||
|
||||
/* scook is valid only on the response and is used for ACL compatibility */
|
||||
{ "scook", smp_fetch_cookie, ARG1(0,STR), NULL, SMP_T_STR, SMP_USE_HRSHV },
|
||||
{ "scook_cnt", smp_fetch_cookie_cnt, ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_HRSHV },
|
||||
|
Loading…
Reference in New Issue
Block a user