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 */
}
/* 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) {
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;
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);
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;
}
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;
{ "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 },