mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 23:27:04 +02:00
MEDIUM: httpclient: implement a way to use directly htx data
Add a HTTPCLIENT_O_RES_HTX flag which allow to store directly the HTX data in the response buffer instead of extracting the data in raw format. This is useful when the data need to be reused in another request.
This commit is contained in:
parent
2f4219ed68
commit
3e05e20029
@ -50,6 +50,7 @@ struct httpclient {
|
||||
|
||||
/* options */
|
||||
#define HTTPCLIENT_O_HTTPPROXY 0x00000001 /* the request must be use an absolute URI */
|
||||
#define HTTPCLIENT_O_RES_HTX 0x00000002 /* response is stored in HTX */
|
||||
|
||||
/* States of the HTTP Client Appctx */
|
||||
enum {
|
||||
|
@ -397,6 +397,8 @@ void httpclient_destroy(struct httpclient *hc)
|
||||
/* request */
|
||||
istfree(&hc->req.url);
|
||||
b_free(&hc->req.buf);
|
||||
|
||||
if (!(hc->options & HTTPCLIENT_O_RES_HTX)) {
|
||||
/* response */
|
||||
istfree(&hc->res.vsn);
|
||||
istfree(&hc->res.reason);
|
||||
@ -407,6 +409,8 @@ void httpclient_destroy(struct httpclient *hc)
|
||||
hdrs++;
|
||||
}
|
||||
ha_free(&hc->res.hdrs);
|
||||
}
|
||||
|
||||
b_free(&hc->res.buf);
|
||||
sockaddr_free(&hc->dst);
|
||||
|
||||
@ -502,6 +506,7 @@ void httpclient_applet_io_handler(struct appctx *appctx)
|
||||
struct htx_sl *sl = NULL;
|
||||
uint32_t hdr_num;
|
||||
uint32_t sz;
|
||||
int count = 0;
|
||||
int ret;
|
||||
|
||||
if (unlikely(se_fl_test(appctx->sedesc, (SE_FL_EOS|SE_FL_ERROR)))) {
|
||||
@ -608,6 +613,13 @@ void httpclient_applet_io_handler(struct appctx *appctx)
|
||||
break;
|
||||
|
||||
case HTTPCLIENT_S_RES_STLINE:
|
||||
/* in HTX mode, don't try to copy the stline
|
||||
* alone, we must copy the headers with it */
|
||||
if (hc->options & HTTPCLIENT_O_RES_HTX) {
|
||||
appctx->st0 = HTTPCLIENT_S_RES_HDR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Request is finished, report EOI */
|
||||
se_fl_set(appctx->sedesc, SE_FL_EOI);
|
||||
|
||||
@ -646,20 +658,43 @@ void httpclient_applet_io_handler(struct appctx *appctx)
|
||||
break;
|
||||
|
||||
case HTTPCLIENT_S_RES_HDR:
|
||||
/* first copy the headers in a local hdrs
|
||||
* structure, once we the total numbers of the
|
||||
* header we allocate the right size and copy
|
||||
* them. The htx block of the headers are
|
||||
* removed each time one is read */
|
||||
{
|
||||
struct http_hdr hdrs[global.tune.max_http_hdr];
|
||||
|
||||
if (!co_data(res))
|
||||
goto out;
|
||||
htx = htxbuf(&res->buf);
|
||||
if (htx_is_empty(htx))
|
||||
goto out;
|
||||
|
||||
if (hc->options & HTTPCLIENT_O_RES_HTX) {
|
||||
/* HTX mode transfers the header to the hc buffer */
|
||||
struct htx *hc_htx;
|
||||
struct htx_ret ret;
|
||||
|
||||
if (!b_alloc(&hc->res.buf, DB_MUX_TX))
|
||||
goto out;
|
||||
hc_htx = htxbuf(&hc->res.buf);
|
||||
|
||||
/* xfer the headers */
|
||||
count = htx->data;
|
||||
ret = htx_xfer_blks(hc_htx, htx, htx_used_space(htx), HTX_BLK_EOH);
|
||||
if (ret.ret <= 0)
|
||||
goto out;
|
||||
count -= htx->data;
|
||||
c_rew(res, count);
|
||||
|
||||
if (htx->flags & HTX_FL_EOM)
|
||||
hc_htx->flags |= HTX_FL_EOM;
|
||||
|
||||
htx_to_buf(htx, &res->buf);
|
||||
htx_to_buf(hc_htx, &hc->res.buf);
|
||||
|
||||
} else {
|
||||
/* first copy the headers in a local hdrs
|
||||
* structure, once we the total numbers of the
|
||||
* header we allocate the right size and copy
|
||||
* them. The htx block of the headers are
|
||||
* removed each time one is read */
|
||||
struct http_hdr hdrs[global.tune.max_http_hdr];
|
||||
|
||||
hdr_num = 0;
|
||||
blk = htx_get_head_blk(htx);
|
||||
while (blk) {
|
||||
@ -690,11 +725,11 @@ void httpclient_applet_io_handler(struct appctx *appctx)
|
||||
if (!hc->res.hdrs)
|
||||
goto error;
|
||||
memcpy(hc->res.hdrs, hdrs, sizeof(struct http_hdr) * (hdr_num + 1));
|
||||
|
||||
}
|
||||
}
|
||||
/* caller callback */
|
||||
if (hc->ops.res_headers)
|
||||
hc->ops.res_headers(hc);
|
||||
}
|
||||
|
||||
/* if there is no HTX data anymore and the EOM flag is
|
||||
* set, leave (no body) */
|
||||
@ -703,7 +738,7 @@ void httpclient_applet_io_handler(struct appctx *appctx)
|
||||
} else {
|
||||
appctx->st0 = HTTPCLIENT_S_RES_BODY;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case HTTPCLIENT_S_RES_BODY:
|
||||
@ -724,6 +759,27 @@ void httpclient_applet_io_handler(struct appctx *appctx)
|
||||
if (b_full(&hc->res.buf))
|
||||
goto process_data;
|
||||
|
||||
if (hc->options & HTTPCLIENT_O_RES_HTX) {
|
||||
/* HTX mode transfers the header to the hc buffer */
|
||||
struct htx *hc_htx;
|
||||
struct htx_ret ret;
|
||||
|
||||
hc_htx = htxbuf(&hc->res.buf);
|
||||
|
||||
/* xfer the status line to the res buffer */
|
||||
count = htx->data;
|
||||
ret = htx_xfer_blks(hc_htx, htx, htx_used_space(htx), HTX_BLK_UNUSED);
|
||||
if (ret.ret <= 0)
|
||||
goto process_data;
|
||||
count -= htx->data;
|
||||
c_rew(res, count);
|
||||
|
||||
if (htx->flags & HTX_FL_EOM)
|
||||
hc_htx->flags |= HTX_FL_EOM;
|
||||
|
||||
htx_to_buf(hc_htx, &hc->res.buf);
|
||||
} else {
|
||||
|
||||
/* decapsule the htx data to raw data */
|
||||
blk = htx_get_head_blk(htx);
|
||||
while (blk) {
|
||||
@ -754,10 +810,6 @@ void httpclient_applet_io_handler(struct appctx *appctx)
|
||||
else
|
||||
htx_cut_data_blk(htx, blk, vlen);
|
||||
|
||||
/* the data must be processed by the caller in the receive phase */
|
||||
if (hc->ops.res_payload)
|
||||
hc->ops.res_payload(hc);
|
||||
|
||||
/* cannot copy everything, need to process */
|
||||
if (vlen != blksz) {
|
||||
htx_to_buf(htx, &res->buf);
|
||||
@ -774,16 +826,18 @@ void httpclient_applet_io_handler(struct appctx *appctx)
|
||||
blk = htx_remove_blk(htx, blk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
htx_to_buf(htx, &res->buf);
|
||||
|
||||
/* the data must be processed by the caller in the receive phase */
|
||||
if (hc->ops.res_payload)
|
||||
hc->ops.res_payload(hc);
|
||||
|
||||
/* if not finished, should be called again */
|
||||
if (!(htx_is_empty(htx) && (htx->flags & HTX_FL_EOM)))
|
||||
goto out;
|
||||
|
||||
|
||||
/* end of message, we should quit */
|
||||
if ((htx_is_empty(htx) && (htx->flags & HTX_FL_EOM)))
|
||||
appctx->st0 = HTTPCLIENT_S_RES_END;
|
||||
/* end of message, we should quit */
|
||||
break;
|
||||
|
||||
case HTTPCLIENT_S_RES_END:
|
||||
|
Loading…
Reference in New Issue
Block a user