mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-03-11 05:48:41 +00:00
MEDIUM: htx: Don't rely on h1_sl anymore except during H1 header parsing
Instead, we now use the htx_sl coming from the HTX message. It avoids to have too H1 specific code in version-agnostic parts. Of course, the concept of the start-line is higly influenced by the H1, but the structure htx_sl can be adapted, if necessary. And many things depend on a start-line during HTTP analyzis. Using the structure htx_sl also avoid boring conversions between HTX version and H1 version.
This commit is contained in:
parent
54483df5ba
commit
f1ba18d7b3
@ -28,11 +28,10 @@
|
||||
#include <types/h1.h>
|
||||
#include <types/http_htx.h>
|
||||
|
||||
union h1_sl http_find_stline(const struct htx *htx);
|
||||
struct htx_sl *http_find_stline(struct htx *htx);
|
||||
int http_find_header(const struct htx *htx, const struct ist name, struct http_hdr_ctx *ctx, int full);
|
||||
int http_add_header(struct htx *htx, const struct ist n, const struct ist v);
|
||||
int http_replace_reqline(struct htx *htx, const union h1_sl sl);
|
||||
int http_replace_resline(struct htx *htx, const union h1_sl sl);
|
||||
int http_replace_stline(struct htx *htx, const struct ist p1, const struct ist p2, const struct ist p3);
|
||||
int http_replace_req_meth(struct htx *htx, const struct ist meth);
|
||||
int http_replace_req_uri(struct htx *htx, const struct ist uri);
|
||||
int http_replace_req_path(struct htx *htx, const struct ist path);
|
||||
|
@ -26,8 +26,6 @@
|
||||
#include <common/config.h>
|
||||
#include <common/standard.h>
|
||||
#include <common/http-hdr.h>
|
||||
|
||||
#include <types/h1.h>
|
||||
#include <types/htx.h>
|
||||
|
||||
extern struct htx htx_empty;
|
||||
@ -41,15 +39,14 @@ struct htx_blk *htx_replace_blk_value(struct htx *htx, struct htx_blk *blk,
|
||||
struct htx_ret htx_xfer_blks(struct htx *dst, struct htx *src, uint32_t count,
|
||||
enum htx_blk_type mark);
|
||||
|
||||
struct htx_blk *htx_replace_reqline(struct htx *htx, struct htx_blk *blk,
|
||||
const union h1_sl sl);
|
||||
struct htx_blk *htx_replace_resline(struct htx *htx, struct htx_blk *blk,
|
||||
const union h1_sl sl);
|
||||
struct htx_sl *htx_add_stline(struct htx *htx, enum htx_blk_type type, unsigned int flags,
|
||||
const struct ist p1, const struct ist p2, const struct ist p3);
|
||||
struct htx_sl *htx_replace_stline(struct htx *htx, struct htx_blk *blk, const struct ist p1,
|
||||
const struct ist p2, const struct ist p3);
|
||||
|
||||
struct htx_blk *htx_replace_header(struct htx *htx, struct htx_blk *blk,
|
||||
const struct ist name, const struct ist value);
|
||||
|
||||
struct htx_blk *htx_add_reqline(struct htx *htx, const union h1_sl sl);
|
||||
struct htx_blk *htx_add_resline(struct htx *htx, const union h1_sl sl);
|
||||
struct htx_blk *htx_add_header(struct htx *htx, const struct ist name, const struct ist value);
|
||||
struct htx_blk *htx_add_all_headers(struct htx *htx, const struct http_hdr *hdrs);
|
||||
struct htx_blk *htx_add_pseudo_header(struct htx *htx, enum htx_phdr_type phdr, const struct ist value);
|
||||
|
107
src/http_fetch.c
107
src/http_fetch.c
@ -173,6 +173,7 @@ struct htx *smp_prefetch_htx(struct sample *smp, const struct arg *args)
|
||||
unsigned int opt = smp->opt;
|
||||
struct http_txn *txn = NULL;
|
||||
struct htx *htx = NULL;
|
||||
struct htx_sl *sl;
|
||||
|
||||
/* Note: it is possible that <s> is NULL when called before stream
|
||||
* initialization (eg: tcp-request connection), so this function is the
|
||||
@ -190,8 +191,6 @@ struct htx *smp_prefetch_htx(struct sample *smp, const struct arg *args)
|
||||
|
||||
if (px->mode == PR_MODE_HTTP) {
|
||||
if ((opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ) {
|
||||
union h1_sl sl;
|
||||
|
||||
htx = htx_from_buf(&s->req.buf);
|
||||
if (htx_is_empty(htx) || htx_get_tail_type(htx) < HTX_BLK_EOH) {
|
||||
/* Parsing is done by the mux, just wait */
|
||||
@ -205,7 +204,7 @@ struct htx *smp_prefetch_htx(struct sample *smp, const struct arg *args)
|
||||
*/
|
||||
if (txn) {
|
||||
sl = http_find_stline(htx);
|
||||
txn->meth = sl.rq.meth;
|
||||
txn->meth = sl->info.req.meth;
|
||||
if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
|
||||
s->flags |= SF_REDIRECTABLE;
|
||||
}
|
||||
@ -226,7 +225,8 @@ struct htx *smp_prefetch_htx(struct sample *smp, const struct arg *args)
|
||||
struct buffer *buf;
|
||||
struct h1m h1m;
|
||||
struct http_hdr hdrs[MAX_HTTP_HDR];
|
||||
union h1_sl sl;
|
||||
union h1_sl h1sl;
|
||||
unsigned int flags = HTX_FL_NONE;
|
||||
int ret;
|
||||
|
||||
buf = &s->req.buf;
|
||||
@ -235,7 +235,7 @@ struct htx *smp_prefetch_htx(struct sample *smp, const struct arg *args)
|
||||
|
||||
h1m_init_req(&h1m);
|
||||
ret = h1_headers_to_hdr_list(b_head(buf), b_stop(buf),
|
||||
hdrs, sizeof(hdrs)/sizeof(hdrs[0]), &h1m, &sl);
|
||||
hdrs, sizeof(hdrs)/sizeof(hdrs[0]), &h1m, &h1sl);
|
||||
if (ret <= 0) {
|
||||
/* Invalid or too big*/
|
||||
if (ret < 0 || channel_full(&s->req, global.tune.maxrewrite))
|
||||
@ -249,18 +249,39 @@ struct htx *smp_prefetch_htx(struct sample *smp, const struct arg *args)
|
||||
/* OK we just got a valid HTTP request. We have to
|
||||
* convert it into an HTX message.
|
||||
*/
|
||||
if (unlikely(sl.rq.v.len == 0)) {
|
||||
if (unlikely(h1sl.rq.v.len == 0)) {
|
||||
/* try to convert HTTP/0.9 requests to HTTP/1.0 */
|
||||
if (sl.rq.meth != HTTP_METH_GET || !sl.rq.u.len)
|
||||
if (h1sl.rq.meth != HTTP_METH_GET || !h1sl.rq.u.len)
|
||||
return NULL;
|
||||
sl.rq.v = ist("HTTP/1.0");
|
||||
h1sl.rq.v = ist("HTTP/1.0");
|
||||
}
|
||||
else if ((h1sl.rq.v.len == 8) &&
|
||||
((*(h1sl.rq.v.ptr + 5) > '1') ||
|
||||
((*(h1sl.rq.v.ptr + 5) == '1') && (*(h1sl.rq.v.ptr + 7) >= '1'))))
|
||||
h1m.flags |= H1_MF_VER_11;
|
||||
|
||||
|
||||
/* Set HTX start-line flags */
|
||||
if (h1m.flags & H1_MF_VER_11)
|
||||
flags |= HTX_SL_F_VER_11;
|
||||
if (h1m.flags & H1_MF_XFER_ENC)
|
||||
flags |= HTX_SL_F_XFER_ENC;
|
||||
if (h1m.flags & H1_MF_XFER_LEN) {
|
||||
flags |= HTX_SL_F_XFER_LEN;
|
||||
if (h1m.flags & H1_MF_CHNK)
|
||||
flags |= HTX_SL_F_CHNK;
|
||||
else if (h1m.flags & H1_MF_CLEN)
|
||||
flags |= HTX_SL_F_CLEN;
|
||||
}
|
||||
|
||||
htx = htx_from_buf(get_trash_chunk());
|
||||
if (!htx_add_reqline(htx, sl) || !htx_add_all_headers(htx, hdrs))
|
||||
sl = htx_add_stline(htx, HTX_BLK_REQ_SL, flags, h1sl.rq.m, h1sl.rq.u, h1sl.rq.v);
|
||||
if (!sl || !htx_add_all_headers(htx, hdrs))
|
||||
return NULL;
|
||||
sl->info.req.meth = h1sl.rq.meth;
|
||||
|
||||
if (txn) {
|
||||
txn->meth = sl.rq.meth;
|
||||
txn->meth = h1sl.rq.meth;
|
||||
if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
|
||||
s->flags |= SF_REDIRECTABLE;
|
||||
}
|
||||
@ -411,7 +432,7 @@ static int smp_fetch_meth(const struct arg *args, struct sample *smp, const char
|
||||
smp->data.type = SMP_T_METH;
|
||||
smp->data.u.meth.meth = meth;
|
||||
if (meth == HTTP_METH_OTHER) {
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
|
||||
if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
|
||||
/* ensure the indexes are not affected */
|
||||
@ -419,8 +440,8 @@ static int smp_fetch_meth(const struct arg *args, struct sample *smp, const char
|
||||
|
||||
sl = http_find_stline(htx);
|
||||
smp->flags |= SMP_F_CONST;
|
||||
smp->data.u.meth.str.area = sl.rq.m.ptr;
|
||||
smp->data.u.meth.str.data = sl.rq.m.len;
|
||||
smp->data.u.meth.str.area = HTX_SL_REQ_MPTR(sl);
|
||||
smp->data.u.meth.str.data = HTX_SL_REQ_MLEN(sl);
|
||||
}
|
||||
smp->flags |= SMP_F_VOL_1ST;
|
||||
}
|
||||
@ -454,14 +475,14 @@ static int smp_fetch_rqver(const struct arg *args, struct sample *smp, const cha
|
||||
if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
|
||||
/* HTX version */
|
||||
struct htx *htx = smp_prefetch_htx(smp, args);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
|
||||
if (!htx)
|
||||
return 0;
|
||||
|
||||
sl = http_find_stline(htx);
|
||||
len = sl.rq.v.len;
|
||||
ptr = sl.rq.v.ptr;
|
||||
len = HTX_SL_REQ_VLEN(sl);
|
||||
ptr = HTX_SL_REQ_VPTR(sl);
|
||||
}
|
||||
else {
|
||||
/* LEGACY version */
|
||||
@ -493,14 +514,14 @@ static int smp_fetch_stver(const struct arg *args, struct sample *smp, const cha
|
||||
if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
|
||||
/* HTX version */
|
||||
struct htx *htx = smp_prefetch_htx(smp, args);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
|
||||
if (!htx)
|
||||
return 0;
|
||||
|
||||
sl = http_find_stline(htx);
|
||||
len = sl.st.v.len;
|
||||
ptr = sl.st.v.ptr;
|
||||
len = HTX_SL_RES_VLEN(sl);
|
||||
ptr = HTX_SL_RES_VPTR(sl);
|
||||
}
|
||||
else {
|
||||
/* LEGACY version */
|
||||
@ -536,14 +557,14 @@ static int smp_fetch_stcode(const struct arg *args, struct sample *smp, const ch
|
||||
if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
|
||||
/* HTX version */
|
||||
struct htx *htx = smp_prefetch_htx(smp, args);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
|
||||
if (!htx)
|
||||
return 0;
|
||||
|
||||
sl = http_find_stline(htx);
|
||||
len = sl.st.c.len;
|
||||
ptr = sl.st.c.ptr;
|
||||
len = HTX_SL_RES_CLEN(sl);
|
||||
ptr = HTX_SL_RES_CPTR(sl);
|
||||
}
|
||||
else {
|
||||
/* LEGACY version */
|
||||
@ -955,14 +976,14 @@ static int smp_fetch_url(const struct arg *args, struct sample *smp, const char
|
||||
if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
|
||||
/* HTX version */
|
||||
struct htx *htx = smp_prefetch_htx(smp, args);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
|
||||
if (!htx)
|
||||
return 0;
|
||||
sl = http_find_stline(htx);
|
||||
smp->data.type = SMP_T_STR;
|
||||
smp->data.u.str.area = sl.rq.u.ptr;
|
||||
smp->data.u.str.data = sl.rq.u.len;
|
||||
smp->data.u.str.area = HTX_SL_REQ_UPTR(sl);
|
||||
smp->data.u.str.data = HTX_SL_REQ_ULEN(sl);
|
||||
smp->flags = SMP_F_VOL_1ST | SMP_F_CONST;
|
||||
}
|
||||
else {
|
||||
@ -986,12 +1007,12 @@ static int smp_fetch_url_ip(const struct arg *args, struct sample *smp, const ch
|
||||
if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
|
||||
/* HTX version */
|
||||
struct htx *htx = smp_prefetch_htx(smp, args);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
|
||||
if (!htx)
|
||||
return 0;
|
||||
sl = http_find_stline(htx);
|
||||
url2sa(sl.rq.u.ptr, sl.rq.u.len, &addr, NULL);
|
||||
url2sa(HTX_SL_REQ_UPTR(sl), HTX_SL_REQ_ULEN(sl), &addr, NULL);
|
||||
}
|
||||
else {
|
||||
/* LEGACY version */
|
||||
@ -1018,12 +1039,12 @@ static int smp_fetch_url_port(const struct arg *args, struct sample *smp, const
|
||||
if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
|
||||
/* HTX version */
|
||||
struct htx *htx = smp_prefetch_htx(smp, args);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
|
||||
if (!htx)
|
||||
return 0;
|
||||
sl = http_find_stline(htx);
|
||||
url2sa(sl.rq.u.ptr, sl.rq.u.len, &addr, NULL);
|
||||
url2sa(HTX_SL_REQ_UPTR(sl), HTX_SL_REQ_ULEN(sl), &addr, NULL);
|
||||
}
|
||||
else {
|
||||
/* LEGACY version */
|
||||
@ -1492,7 +1513,7 @@ static int smp_fetch_path(const struct arg *args, struct sample *smp, const char
|
||||
if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
|
||||
/* HTX version */
|
||||
struct htx *htx = smp_prefetch_htx(smp, args);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
struct ist path;
|
||||
size_t len;
|
||||
|
||||
@ -1500,7 +1521,7 @@ static int smp_fetch_path(const struct arg *args, struct sample *smp, const char
|
||||
return 0;
|
||||
|
||||
sl = http_find_stline(htx);
|
||||
path = http_get_path(sl.rq.u);
|
||||
path = http_get_path(htx_sl_req_uri(sl));
|
||||
if (!path.ptr)
|
||||
return 0;
|
||||
|
||||
@ -1551,7 +1572,7 @@ static int smp_fetch_base(const struct arg *args, struct sample *smp, const char
|
||||
if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
|
||||
/* HTX version */
|
||||
struct htx *htx = smp_prefetch_htx(smp, args);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
struct http_hdr_ctx ctx;
|
||||
struct ist path;
|
||||
|
||||
@ -1568,7 +1589,7 @@ static int smp_fetch_base(const struct arg *args, struct sample *smp, const char
|
||||
|
||||
/* now retrieve the path */
|
||||
sl = http_find_stline(htx);
|
||||
path = http_get_path(sl.rq.u);
|
||||
path = http_get_path(htx_sl_req_uri(sl));
|
||||
if (path.ptr) {
|
||||
size_t len;
|
||||
|
||||
@ -1634,7 +1655,7 @@ static int smp_fetch_base32(const struct arg *args, struct sample *smp, const ch
|
||||
if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
|
||||
/* HTX version */
|
||||
struct htx *htx = smp_prefetch_htx(smp, args);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
struct http_hdr_ctx ctx;
|
||||
struct ist path;
|
||||
|
||||
@ -1650,7 +1671,7 @@ static int smp_fetch_base32(const struct arg *args, struct sample *smp, const ch
|
||||
|
||||
/* now retrieve the path */
|
||||
sl = http_find_stline(htx);
|
||||
path = http_get_path(sl.rq.u);
|
||||
path = http_get_path(htx_sl_req_uri(sl));
|
||||
if (path.ptr) {
|
||||
size_t len;
|
||||
|
||||
@ -1757,14 +1778,14 @@ static int smp_fetch_query(const struct arg *args, struct sample *smp, const cha
|
||||
if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
|
||||
/* HTX version */
|
||||
struct htx *htx = smp_prefetch_htx(smp, args);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
|
||||
if (!htx)
|
||||
return 0;
|
||||
|
||||
sl = http_find_stline(htx);
|
||||
ptr = sl.rq.u.ptr;
|
||||
end = sl.rq.u.ptr + sl.rq.u.len;
|
||||
ptr = HTX_SL_REQ_UPTR(sl);
|
||||
end = HTX_SL_REQ_UPTR(sl) + HTX_SL_REQ_ULEN(sl);
|
||||
}
|
||||
else {
|
||||
/* LEGACY version */
|
||||
@ -2432,17 +2453,17 @@ static int smp_fetch_url_param(const struct arg *args, struct sample *smp, const
|
||||
if (IS_HTX_SMP(smp) || (smp->px->mode == PR_MODE_TCP)) {
|
||||
/* HTX version */
|
||||
struct htx *htx = smp_prefetch_htx(smp, args);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
|
||||
if (!htx)
|
||||
return 0;
|
||||
|
||||
sl = http_find_stline(htx);
|
||||
smp->ctx.a[0] = http_find_param_list(sl.rq.u.ptr, sl.rq.u.len, delim);
|
||||
smp->ctx.a[0] = http_find_param_list(HTX_SL_REQ_UPTR(sl), HTX_SL_REQ_ULEN(sl), delim);
|
||||
if (!smp->ctx.a[0])
|
||||
return 0;
|
||||
|
||||
smp->ctx.a[1] = sl.rq.u.ptr + sl.rq.u.len;
|
||||
smp->ctx.a[1] = HTX_SL_REQ_UPTR(sl) + HTX_SL_REQ_ULEN(sl);
|
||||
}
|
||||
else {
|
||||
/* LEGACY version */
|
||||
@ -2603,7 +2624,7 @@ static int smp_fetch_url32(const struct arg *args, struct sample *smp, const cha
|
||||
/* HTX version */
|
||||
struct htx *htx = smp_prefetch_htx(smp, args);
|
||||
struct http_hdr_ctx ctx;
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
struct ist path;
|
||||
|
||||
if (!htx)
|
||||
@ -2618,7 +2639,7 @@ static int smp_fetch_url32(const struct arg *args, struct sample *smp, const cha
|
||||
|
||||
/* now retrieve the path */
|
||||
sl = http_find_stline(htx);
|
||||
path = http_get_path(sl.rq.u);
|
||||
path = http_get_path(htx_sl_req_uri(sl));
|
||||
while (path.len > 0 && *(path.ptr) != '?') {
|
||||
path.ptr++;
|
||||
path.len--;
|
||||
|
211
src/http_htx.c
211
src/http_htx.c
@ -17,44 +17,33 @@
|
||||
#include <proto/htx.h>
|
||||
|
||||
/* Finds the start line in the HTX message stopping at the first
|
||||
* end-of-message. It returns an empty start line when not found, otherwise, it
|
||||
* returns the corresponding <struct h1_sl>.
|
||||
* end-of-message. It returns NULL when not found, otherwise, it returns the
|
||||
* pointer on the htx_sl structure. The HTX message may be updated if the
|
||||
* start-line is returned following a lookup.
|
||||
*/
|
||||
union h1_sl http_find_stline(const struct htx *htx)
|
||||
struct htx_sl *http_find_stline(struct htx *htx)
|
||||
{
|
||||
struct htx_sl *htx_sl;
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl = NULL;
|
||||
int32_t pos;
|
||||
|
||||
sl = htx_get_stline(htx);
|
||||
if (sl)
|
||||
return sl;
|
||||
|
||||
for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) {
|
||||
struct htx_blk *blk = htx_get_blk(htx, pos);
|
||||
enum htx_blk_type type = htx_get_blk_type(blk);
|
||||
|
||||
if (type == HTX_BLK_REQ_SL) {
|
||||
htx_sl = htx_get_blk_ptr(htx, blk);
|
||||
sl.rq.meth = htx_sl->info.req.meth;
|
||||
sl.rq.m = htx_sl_req_meth(htx_sl);
|
||||
sl.rq.u = htx_sl_req_uri(htx_sl);
|
||||
sl.rq.v = htx_sl_req_vsn(htx_sl);
|
||||
return sl;
|
||||
}
|
||||
|
||||
if (type == HTX_BLK_RES_SL) {
|
||||
htx_sl = htx_get_blk_ptr(htx, blk);
|
||||
sl.st.status = htx_sl->info.res.status;
|
||||
sl.st.v = htx_sl_res_vsn(htx_sl);
|
||||
sl.st.c = htx_sl_res_code(htx_sl);
|
||||
sl.st.r = htx_sl_res_reason(htx_sl);
|
||||
return sl;
|
||||
if (type == HTX_BLK_REQ_SL || type == HTX_BLK_RES_SL) {
|
||||
sl = htx_get_blk_ptr(htx, blk);
|
||||
htx->sl_off = blk->addr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == HTX_BLK_EOH || type == HTX_BLK_EOM)
|
||||
break;
|
||||
}
|
||||
|
||||
sl.rq.m = ist("");
|
||||
sl.rq.u = ist("");
|
||||
sl.rq.v = ist("");
|
||||
return sl;
|
||||
}
|
||||
|
||||
@ -193,50 +182,24 @@ int http_add_header(struct htx *htx, const struct ist n, const struct ist v)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Replaces the request start line of the HTX message <htx> by <sl>. It returns
|
||||
* 1 on success, otherwise it returns 0. The start line must be found in the
|
||||
/* Replaces parts of the start-line of the HTX message <htx>. It returns 1 on
|
||||
* success, otherwise it returns 0. The right block is search in the HTX
|
||||
* message.
|
||||
*/
|
||||
int http_replace_reqline(struct htx *htx, const union h1_sl sl)
|
||||
int http_replace_stline(struct htx *htx, const struct ist p1, const struct ist p2, const struct ist p3)
|
||||
{
|
||||
int32_t pos;
|
||||
|
||||
for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) {
|
||||
struct htx_blk *blk = htx_get_blk(htx, pos);
|
||||
enum htx_blk_type type = htx_get_blk_type(blk);
|
||||
struct htx_blk *blk = htx_get_blk(htx, pos);
|
||||
enum htx_blk_type type = htx_get_blk_type(blk);
|
||||
|
||||
if (type == HTX_BLK_REQ_SL) {
|
||||
blk = htx_replace_reqline(htx, blk, sl);
|
||||
if (!blk)
|
||||
if (htx->sl_off == blk->addr) {
|
||||
if (!htx_replace_stline(htx, blk, p1, p2, p3))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if (type == HTX_BLK_EOM)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Replaces the response start line of the HTX message <htx> by <sl>. It returns
|
||||
* 1 on success, otherwise it returns 0. The start line must be found in the
|
||||
* message.
|
||||
*/
|
||||
int http_replace_resline(struct htx *htx, const union h1_sl sl)
|
||||
{
|
||||
int32_t pos;
|
||||
|
||||
for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) {
|
||||
struct htx_blk *blk = htx_get_blk(htx, pos);
|
||||
enum htx_blk_type type = htx_get_blk_type(blk);
|
||||
|
||||
if (type == HTX_BLK_RES_SL) {
|
||||
blk = htx_replace_resline(htx, blk, sl);
|
||||
if (!blk)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if (type == HTX_BLK_EOM)
|
||||
break;
|
||||
}
|
||||
@ -250,20 +213,19 @@ int http_replace_resline(struct htx *htx, const union h1_sl sl)
|
||||
int http_replace_req_meth(struct htx *htx, const struct ist meth)
|
||||
{
|
||||
struct buffer *temp = get_trash_chunk();
|
||||
union h1_sl sl = http_find_stline(htx);
|
||||
union h1_sl new_sl;
|
||||
struct htx_sl *sl = http_find_stline(htx);
|
||||
struct ist uri, vsn;
|
||||
|
||||
/* Start by copying old uri and version */
|
||||
chunk_memcat(temp, sl.rq.u.ptr, sl.rq.u.len); /* uri */
|
||||
chunk_memcat(temp, sl.rq.v.ptr, sl.rq.v.len); /* vsn */
|
||||
chunk_memcat(temp, HTX_SL_REQ_UPTR(sl), HTX_SL_REQ_ULEN(sl)); /* uri */
|
||||
uri = ist2(temp->area, HTX_SL_REQ_ULEN(sl));
|
||||
|
||||
chunk_memcat(temp, HTX_SL_REQ_VPTR(sl), HTX_SL_REQ_VLEN(sl)); /* vsn */
|
||||
vsn = ist2(temp->area + uri.len, HTX_SL_REQ_VLEN(sl));
|
||||
|
||||
/* create the new start line */
|
||||
new_sl.rq.meth = find_http_meth(meth.ptr, meth.len);
|
||||
new_sl.rq.m = meth;
|
||||
new_sl.rq.u = ist2(temp->area, sl.rq.u.len);
|
||||
new_sl.rq.v = ist2(temp->area + sl.rq.u.len, sl.rq.v.len);
|
||||
|
||||
return http_replace_reqline(htx, new_sl);
|
||||
sl->info.req.meth = find_http_meth(meth.ptr, meth.len);
|
||||
return http_replace_stline(htx, meth, uri, vsn);
|
||||
}
|
||||
|
||||
/* Replace the request uri in the HTX message <htx> by <uri>. It returns 1 on
|
||||
@ -272,20 +234,18 @@ int http_replace_req_meth(struct htx *htx, const struct ist meth)
|
||||
int http_replace_req_uri(struct htx *htx, const struct ist uri)
|
||||
{
|
||||
struct buffer *temp = get_trash_chunk();
|
||||
union h1_sl sl = http_find_stline(htx);
|
||||
union h1_sl new_sl;
|
||||
struct htx_sl *sl = http_find_stline(htx);
|
||||
struct ist meth, vsn;
|
||||
|
||||
/* Start by copying old method and version */
|
||||
chunk_memcat(temp, sl.rq.m.ptr, sl.rq.m.len); /* meth */
|
||||
chunk_memcat(temp, sl.rq.v.ptr, sl.rq.v.len); /* vsn */
|
||||
chunk_memcat(temp, HTX_SL_REQ_MPTR(sl), HTX_SL_REQ_MLEN(sl)); /* meth */
|
||||
meth = ist2(temp->area, HTX_SL_REQ_MLEN(sl));
|
||||
|
||||
chunk_memcat(temp, HTX_SL_REQ_VPTR(sl), HTX_SL_REQ_VLEN(sl)); /* vsn */
|
||||
vsn = ist2(temp->area + meth.len, HTX_SL_REQ_VLEN(sl));
|
||||
|
||||
/* create the new start line */
|
||||
new_sl.rq.meth = sl.rq.meth;
|
||||
new_sl.rq.m = ist2(temp->area, sl.rq.m.len);
|
||||
new_sl.rq.u = uri;
|
||||
new_sl.rq.v = ist2(temp->area + sl.rq.m.len, sl.rq.v.len);
|
||||
|
||||
return http_replace_reqline(htx, new_sl);
|
||||
return http_replace_stline(htx, meth, uri, vsn);
|
||||
}
|
||||
|
||||
/* Replace the request path in the HTX message <htx> by <path>. The host part
|
||||
@ -294,36 +254,31 @@ int http_replace_req_uri(struct htx *htx, const struct ist uri)
|
||||
int http_replace_req_path(struct htx *htx, const struct ist path)
|
||||
{
|
||||
struct buffer *temp = get_trash_chunk();
|
||||
union h1_sl sl = http_find_stline(htx);
|
||||
union h1_sl new_sl;
|
||||
struct ist p, uri;
|
||||
struct htx_sl *sl = http_find_stline(htx);
|
||||
struct ist meth, uri, vsn, p;
|
||||
size_t plen = 0;
|
||||
|
||||
p = http_get_path(sl.rq.u);
|
||||
uri = htx_sl_req_uri(sl);
|
||||
p = http_get_path(uri);
|
||||
if (!p.ptr)
|
||||
p = sl.rq.u;
|
||||
p = uri;
|
||||
while (plen < p.len && *(p.ptr + plen) != '?')
|
||||
plen++;
|
||||
|
||||
/* Start by copying old method and version and create the new uri */
|
||||
chunk_memcat(temp, sl.rq.m.ptr, sl.rq.m.len); /* meth */
|
||||
chunk_memcat(temp, sl.rq.v.ptr, sl.rq.v.len); /* vsn */
|
||||
chunk_memcat(temp, HTX_SL_REQ_MPTR(sl), HTX_SL_REQ_MLEN(sl)); /* meth */
|
||||
meth = ist2(temp->area, HTX_SL_REQ_MLEN(sl));
|
||||
|
||||
chunk_memcat(temp, sl.rq.u.ptr, p.ptr - sl.rq.u.ptr); /* uri: host part */
|
||||
chunk_memcat(temp, HTX_SL_REQ_VPTR(sl), HTX_SL_REQ_VLEN(sl)); /* vsn */
|
||||
vsn = ist2(temp->area + meth.len, HTX_SL_REQ_VLEN(sl));
|
||||
|
||||
chunk_memcat(temp, uri.ptr, p.ptr - uri.ptr); /* uri: host part */
|
||||
chunk_memcat(temp, path.ptr, path.len); /* uri: new path */
|
||||
chunk_memcat(temp, p.ptr + plen, p.len - plen); /* uri: QS part */
|
||||
|
||||
/* Get uri ptr and len */
|
||||
uri.ptr = temp->area + sl.rq.m.len + sl.rq.v.len;
|
||||
uri.len = sl.rq.u.len - plen + path.len;
|
||||
uri = ist2(temp->area + meth.len + vsn.len, uri.len - plen + path.len);
|
||||
|
||||
/* create the new start line */
|
||||
new_sl.rq.meth = sl.rq.meth;
|
||||
new_sl.rq.m = ist2(temp->area, sl.rq.m.len);
|
||||
new_sl.rq.u = uri;
|
||||
new_sl.rq.v = ist2(temp->area + sl.rq.m.len, sl.rq.v.len);
|
||||
|
||||
return http_replace_reqline(htx, new_sl);
|
||||
return http_replace_stline(htx, meth, uri, vsn);
|
||||
}
|
||||
|
||||
/* Replace the request query-string in the HTX message <htx> by <query>. The
|
||||
@ -333,12 +288,12 @@ int http_replace_req_path(struct htx *htx, const struct ist path)
|
||||
int http_replace_req_query(struct htx *htx, const struct ist query)
|
||||
{
|
||||
struct buffer *temp = get_trash_chunk();
|
||||
union h1_sl sl = http_find_stline(htx);
|
||||
union h1_sl new_sl;
|
||||
struct ist q, uri;
|
||||
struct htx_sl *sl = http_find_stline(htx);
|
||||
struct ist meth, uri, vsn, q;
|
||||
int offset = 1;
|
||||
|
||||
q = sl.rq.u;
|
||||
uri = htx_sl_req_uri(sl);
|
||||
q = uri;
|
||||
while (q.len > 0 && *(q.ptr) != '?') {
|
||||
q.ptr++;
|
||||
q.len--;
|
||||
@ -355,23 +310,18 @@ int http_replace_req_query(struct htx *htx, const struct ist query)
|
||||
offset = 0;
|
||||
|
||||
/* Start by copying old method and version and create the new uri */
|
||||
chunk_memcat(temp, sl.rq.m.ptr, sl.rq.m.len); /* meth */
|
||||
chunk_memcat(temp, sl.rq.v.ptr, sl.rq.v.len); /* vsn */
|
||||
chunk_memcat(temp, HTX_SL_REQ_MPTR(sl), HTX_SL_REQ_MLEN(sl)); /* meth */
|
||||
meth = ist2(temp->area, HTX_SL_REQ_MLEN(sl));
|
||||
|
||||
chunk_memcat(temp, sl.rq.u.ptr, q.ptr - sl.rq.u.ptr); /* uri: host + path part */
|
||||
chunk_memcat(temp, HTX_SL_REQ_VPTR(sl), HTX_SL_REQ_VLEN(sl)); /* vsn */
|
||||
vsn = ist2(temp->area + meth.len, HTX_SL_REQ_VLEN(sl));
|
||||
|
||||
chunk_memcat(temp, uri.ptr, q.ptr - uri.ptr); /* uri: host + path part */
|
||||
chunk_memcat(temp, query.ptr + offset, query.len - offset); /* uri: new QS */
|
||||
|
||||
/* Get uri ptr and len */
|
||||
uri.ptr = temp->area + sl.rq.m.len + sl.rq.v.len;
|
||||
uri.len = sl.rq.u.len - q.len + query.len - offset;
|
||||
uri = ist2(temp->area + meth.len + vsn.len, uri.len - q.len + query.len - offset);
|
||||
|
||||
/* create the new start line */
|
||||
new_sl.rq.meth = sl.rq.meth;
|
||||
new_sl.rq.m = ist2(temp->area, sl.rq.m.len);
|
||||
new_sl.rq.u = uri;
|
||||
new_sl.rq.v = ist2(temp->area + sl.rq.m.len, sl.rq.v.len);
|
||||
|
||||
return http_replace_reqline(htx, new_sl);
|
||||
return http_replace_stline(htx, meth, uri, vsn);
|
||||
}
|
||||
|
||||
/* Replace the response status in the HTX message <htx> by <status>. It returns
|
||||
@ -380,20 +330,19 @@ int http_replace_req_query(struct htx *htx, const struct ist query)
|
||||
int http_replace_res_status(struct htx *htx, const struct ist status)
|
||||
{
|
||||
struct buffer *temp = get_trash_chunk();
|
||||
union h1_sl sl = http_find_stline(htx);
|
||||
union h1_sl new_sl;
|
||||
struct htx_sl *sl = http_find_stline(htx);
|
||||
struct ist vsn, reason;
|
||||
|
||||
/* Start by copying old uri and version */
|
||||
chunk_memcat(temp, sl.st.v.ptr, sl.st.v.len); /* vsn */
|
||||
chunk_memcat(temp, sl.st.r.ptr, sl.st.r.len); /* reason */
|
||||
chunk_memcat(temp, HTX_SL_RES_VPTR(sl), HTX_SL_RES_VLEN(sl)); /* vsn */
|
||||
vsn = ist2(temp->area, HTX_SL_RES_VLEN(sl));
|
||||
|
||||
chunk_memcat(temp, HTX_SL_RES_RPTR(sl), HTX_SL_RES_RLEN(sl)); /* reason */
|
||||
reason = ist2(temp->area + vsn.len, HTX_SL_RES_RLEN(sl));
|
||||
|
||||
/* create the new start line */
|
||||
new_sl.st.status = strl2ui(status.ptr, status.len);
|
||||
new_sl.st.v = ist2(temp->area, sl.st.v.len);
|
||||
new_sl.st.c = status;
|
||||
new_sl.st.r = ist2(temp->area + sl.st.v.len, sl.st.r.len);
|
||||
|
||||
return http_replace_resline(htx, new_sl);
|
||||
sl->info.res.status = strl2ui(status.ptr, status.len);
|
||||
return http_replace_stline(htx, vsn, status, reason);
|
||||
}
|
||||
|
||||
/* Replace the response reason in the HTX message <htx> by <reason>. It returns
|
||||
@ -402,20 +351,18 @@ int http_replace_res_status(struct htx *htx, const struct ist status)
|
||||
int http_replace_res_reason(struct htx *htx, const struct ist reason)
|
||||
{
|
||||
struct buffer *temp = get_trash_chunk();
|
||||
union h1_sl sl = http_find_stline(htx);
|
||||
union h1_sl new_sl;
|
||||
struct htx_sl *sl = http_find_stline(htx);
|
||||
struct ist vsn, status;
|
||||
|
||||
/* Start by copying old uri and version */
|
||||
chunk_memcat(temp, sl.st.v.ptr, sl.st.v.len); /* vsn */
|
||||
chunk_memcat(temp, sl.st.c.ptr, sl.st.c.len); /* code */
|
||||
chunk_memcat(temp, HTX_SL_RES_VPTR(sl), HTX_SL_RES_VLEN(sl)); /* vsn */
|
||||
vsn = ist2(temp->area, HTX_SL_RES_VLEN(sl));
|
||||
|
||||
chunk_memcat(temp, HTX_SL_RES_CPTR(sl), HTX_SL_RES_CLEN(sl)); /* code */
|
||||
status = ist2(temp->area + vsn.len, HTX_SL_RES_CLEN(sl));
|
||||
|
||||
/* create the new start line */
|
||||
new_sl.st.status = sl.st.status;
|
||||
new_sl.st.v = ist2(temp->area, sl.st.v.len);
|
||||
new_sl.st.c = ist2(temp->area + sl.st.v.len, sl.st.c.len);
|
||||
new_sl.st.r = reason;
|
||||
|
||||
return http_replace_resline(htx, new_sl);
|
||||
return http_replace_stline(htx, vsn, status, reason);
|
||||
}
|
||||
|
||||
/* Replaces a part of a header value referenced in the context <ctx> by
|
||||
|
150
src/htx.c
150
src/htx.c
@ -586,136 +586,90 @@ struct htx_blk *htx_replace_header(struct htx *htx, struct htx_blk *blk,
|
||||
return blk;
|
||||
}
|
||||
|
||||
static void htx_set_blk_reqline(struct htx *htx, struct htx_blk *blk, const union h1_sl sl)
|
||||
{
|
||||
struct htx_sl *htx_sl;
|
||||
|
||||
htx_sl = htx_get_blk_ptr(htx, blk);
|
||||
htx_sl->info.req.meth = sl.rq.meth;
|
||||
|
||||
if (htx->sl_off == -1)
|
||||
htx->sl_off = blk->addr;
|
||||
|
||||
HTX_SL_REQ_MLEN(htx_sl) = sl.rq.m.len;
|
||||
HTX_SL_REQ_ULEN(htx_sl) = sl.rq.u.len;
|
||||
HTX_SL_REQ_VLEN(htx_sl) = sl.rq.v.len;
|
||||
|
||||
memcpy(HTX_SL_REQ_MPTR(htx_sl), sl.rq.m.ptr, sl.rq.m.len);
|
||||
memcpy(HTX_SL_REQ_UPTR(htx_sl), sl.rq.u.ptr, sl.rq.u.len);
|
||||
memcpy(HTX_SL_REQ_VPTR(htx_sl), sl.rq.v.ptr, sl.rq.v.len);
|
||||
}
|
||||
|
||||
|
||||
static void htx_set_blk_resline(struct htx *htx, struct htx_blk *blk, const union h1_sl sl)
|
||||
{
|
||||
struct htx_sl *htx_sl;
|
||||
|
||||
htx_sl = htx_get_blk_ptr(htx, blk);
|
||||
htx_sl->info.res.status = sl.st.status;
|
||||
|
||||
if (htx->sl_off == -1)
|
||||
htx->sl_off = blk->addr;
|
||||
|
||||
HTX_SL_RES_VLEN(htx_sl) = sl.st.v.len;
|
||||
HTX_SL_RES_CLEN(htx_sl) = sl.st.c.len;
|
||||
HTX_SL_RES_RLEN(htx_sl) = sl.st.r.len;
|
||||
|
||||
memcpy(HTX_SL_RES_VPTR(htx_sl), sl.st.v.ptr, sl.st.v.len);
|
||||
memcpy(HTX_SL_RES_CPTR(htx_sl), sl.st.c.ptr, sl.st.c.len);
|
||||
memcpy(HTX_SL_RES_RPTR(htx_sl), sl.st.r.ptr, sl.st.r.len);
|
||||
}
|
||||
|
||||
/* Replaces the request start line a new one. It returns the new block on
|
||||
* success, otherwise it returns NULL.
|
||||
/* Replaces the parts of the start-line. It returns the new start-line on
|
||||
* success, otherwise it returns NULL. It is the caller responsibility to update
|
||||
* sl->info, if necessary.
|
||||
*/
|
||||
struct htx_blk *htx_replace_reqline(struct htx *htx, struct htx_blk *blk,
|
||||
const union h1_sl sl)
|
||||
struct htx_sl *htx_replace_stline(struct htx *htx, struct htx_blk *blk, const struct ist p1,
|
||||
const struct ist p2, const struct ist p3)
|
||||
{
|
||||
struct htx_sl *sl;
|
||||
struct htx_sl tmp; /* used to save sl->info and sl->flags */
|
||||
enum htx_blk_type type;
|
||||
uint32_t size;
|
||||
|
||||
type = htx_get_blk_type(blk);
|
||||
if (type != HTX_BLK_REQ_SL)
|
||||
if (type != HTX_BLK_REQ_SL || HTX_BLK_RES_SL)
|
||||
return NULL;
|
||||
|
||||
/* Save start-line info and flags */
|
||||
sl = htx_get_blk_ptr(htx, blk);
|
||||
tmp.info = sl->info;
|
||||
tmp.flags = sl->flags;
|
||||
if (htx->sl_off == blk->addr)
|
||||
htx->sl_off = -1;
|
||||
|
||||
size = sizeof(struct htx_sl) + sl.rq.m.len + sl.rq.u.len + sl.rq.v.len;
|
||||
|
||||
size = sizeof(*sl) + p1.len + p2.len + p3.len;
|
||||
blk = htx_new_blk_value(htx, blk, size);
|
||||
if (!blk)
|
||||
return NULL;
|
||||
|
||||
blk->info = (type << 28) + size;
|
||||
htx_set_blk_reqline(htx, blk, sl);
|
||||
return blk;
|
||||
|
||||
/* Restore start-line info and flags*/
|
||||
sl = htx_get_blk_ptr(htx, blk);
|
||||
sl->info = tmp.info;
|
||||
sl->flags = tmp.flags;
|
||||
if (htx->sl_off == -1)
|
||||
htx->sl_off = blk->addr;
|
||||
|
||||
HTX_SL_P1_LEN(sl) = p1.len;
|
||||
HTX_SL_P2_LEN(sl) = p2.len;
|
||||
HTX_SL_P3_LEN(sl) = p3.len;
|
||||
|
||||
memcpy(HTX_SL_P1_PTR(sl), p1.ptr, p1.len);
|
||||
memcpy(HTX_SL_P2_PTR(sl), p2.ptr, p2.len);
|
||||
memcpy(HTX_SL_P3_PTR(sl), p3.ptr, p3.len);
|
||||
|
||||
return sl;
|
||||
}
|
||||
|
||||
/* Replaces the response start line a new one. It returns the new block on
|
||||
* success, otherwise it returns NULL.
|
||||
/* Add a new start-line. It returns it on success, otherwise it returns NULL. It
|
||||
* is the caller responsibility to set sl->info, if necessary.
|
||||
*/
|
||||
struct htx_blk *htx_replace_resline(struct htx *htx, struct htx_blk *blk,
|
||||
const union h1_sl sl)
|
||||
struct htx_sl *htx_add_stline(struct htx *htx, enum htx_blk_type type, unsigned int flags,
|
||||
const struct ist p1, const struct ist p2, const struct ist p3)
|
||||
{
|
||||
enum htx_blk_type type;
|
||||
struct htx_blk *blk;
|
||||
struct htx_sl *sl;
|
||||
uint32_t size;
|
||||
|
||||
type = htx_get_blk_type(blk);
|
||||
if (type != HTX_BLK_RES_SL)
|
||||
return NULL;
|
||||
|
||||
if (htx->sl_off == blk->addr)
|
||||
htx->sl_off = -1;
|
||||
|
||||
size = sizeof(struct htx_sl) + sl.rq.m.len + sl.rq.u.len + sl.rq.v.len;
|
||||
blk = htx_new_blk_value(htx, blk, size);
|
||||
if (!blk)
|
||||
if (type != HTX_BLK_REQ_SL && type != HTX_BLK_RES_SL)
|
||||
return NULL;
|
||||
|
||||
blk->info = (type << 28) + size;
|
||||
htx_set_blk_resline(htx, blk, sl);
|
||||
return blk;
|
||||
}
|
||||
|
||||
|
||||
/* Adds an HTX block of type SL in <htx>. It returns the new block on
|
||||
* success. Otherwise, it returns NULL.
|
||||
*/
|
||||
struct htx_blk *htx_add_reqline(struct htx *htx, const union h1_sl sl)
|
||||
{
|
||||
struct htx_blk *blk;
|
||||
uint32_t size;
|
||||
|
||||
size = sizeof(struct htx_sl) + sl.rq.m.len + sl.rq.u.len + sl.rq.v.len;
|
||||
size = sizeof(*sl) + p1.len + p2.len + p3.len;
|
||||
|
||||
/* FIXME: check size (< 256MB) */
|
||||
blk = htx_add_blk(htx, HTX_BLK_REQ_SL, size);
|
||||
blk = htx_add_blk(htx, type, size);
|
||||
if (!blk)
|
||||
return NULL;
|
||||
|
||||
blk->info += size;
|
||||
htx_set_blk_reqline(htx, blk, sl);
|
||||
return blk;
|
||||
}
|
||||
|
||||
/* Adds an HTX block of type SL in <htx>. It returns the new block on
|
||||
* success. Otherwise, it returns NULL.
|
||||
*/
|
||||
struct htx_blk *htx_add_resline(struct htx *htx, const union h1_sl sl)
|
||||
{
|
||||
struct htx_blk *blk;
|
||||
uint32_t size;
|
||||
sl = htx_get_blk_ptr(htx, blk);
|
||||
if (htx->sl_off == -1)
|
||||
htx->sl_off = blk->addr;
|
||||
|
||||
size = sizeof(struct htx_sl) + sl.st.v.len + sl.st.c.len + sl.st.r.len;
|
||||
sl->flags = flags;
|
||||
|
||||
/* FIXME: check size (< 256MB) */
|
||||
blk = htx_add_blk(htx, HTX_BLK_RES_SL, size);
|
||||
if (!blk)
|
||||
return NULL;
|
||||
HTX_SL_P1_LEN(sl) = p1.len;
|
||||
HTX_SL_P2_LEN(sl) = p2.len;
|
||||
HTX_SL_P3_LEN(sl) = p3.len;
|
||||
|
||||
blk->info += size;
|
||||
htx_set_blk_resline(htx, blk, sl);
|
||||
return blk;
|
||||
memcpy(HTX_SL_P1_PTR(sl), p1.ptr, p1.len);
|
||||
memcpy(HTX_SL_P2_PTR(sl), p2.ptr, p2.len);
|
||||
memcpy(HTX_SL_P3_PTR(sl), p3.ptr, p3.len);
|
||||
|
||||
return sl;
|
||||
}
|
||||
|
||||
/* Adds an HTX block of type HDR in <htx>. It returns the new block on
|
||||
|
56
src/mux_h1.c
56
src/mux_h1.c
@ -490,7 +490,13 @@ static int h1_process_req_vsn(struct h1s *h1s, struct h1m *h1m, union h1_sl sl)
|
||||
|
||||
/* Add HTTP version */
|
||||
sl.rq.v = ist("HTTP/1.0");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((sl.rq.v.len == 8) &&
|
||||
((*(sl.rq.v.ptr + 5) > '1') ||
|
||||
((*(sl.rq.v.ptr + 5) == '1') && (*(sl.rq.v.ptr + 7) >= '1'))))
|
||||
h1m->flags |= H1_MF_VER_11;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -516,6 +522,12 @@ static int h1_process_res_vsn(struct h1s *h1s, struct h1m *h1m, union h1_sl sl)
|
||||
!isdigit((unsigned char)*(sl.st.v.ptr + 7)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((sl.st.v.len == 8) &&
|
||||
((*(sl.st.v.ptr + 5) > '1') ||
|
||||
((*(sl.st.v.ptr + 5) == '1') && (*(sl.st.v.ptr + 7) >= '1'))))
|
||||
h1m->flags |= H1_MF_VER_11;
|
||||
|
||||
return 1;
|
||||
}
|
||||
/* Remove all "Connection:" headers from the HTX message <htx> */
|
||||
@ -752,7 +764,8 @@ static size_t h1_process_headers(struct h1s *h1s, struct h1m *h1m, struct htx *h
|
||||
struct buffer *buf, size_t *ofs, size_t max)
|
||||
{
|
||||
struct http_hdr hdrs[MAX_HTTP_HDR];
|
||||
union h1_sl sl;
|
||||
union h1_sl h1sl;
|
||||
unsigned int flags = HTX_SL_F_NONE;
|
||||
int ret = 0;
|
||||
|
||||
if (!max)
|
||||
@ -763,7 +776,7 @@ static size_t h1_process_headers(struct h1s *h1s, struct h1m *h1m, struct htx *h
|
||||
b_slow_realign(buf, trash.area, 0);
|
||||
|
||||
ret = h1_headers_to_hdr_list(b_peek(buf, *ofs), b_peek(buf, *ofs) + max,
|
||||
hdrs, sizeof(hdrs)/sizeof(hdrs[0]), h1m, &sl);
|
||||
hdrs, sizeof(hdrs)/sizeof(hdrs[0]), h1m, &h1sl);
|
||||
if (ret <= 0) {
|
||||
/* Incomplete or invalid message. If the buffer is full, it's an
|
||||
* error because headers are too large to be handled by the
|
||||
@ -784,21 +797,21 @@ static size_t h1_process_headers(struct h1s *h1s, struct h1m *h1m, struct htx *h
|
||||
/* Save the request's method or the response's status, check if the body
|
||||
* length is known and check the VSN validity */
|
||||
if (!(h1m->flags & H1_MF_RESP)) {
|
||||
h1s->meth = sl.rq.meth;
|
||||
h1s->meth = h1sl.rq.meth;
|
||||
|
||||
/* Request have always a known length */
|
||||
h1m->flags |= H1_MF_XFER_LEN;
|
||||
if (!(h1m->flags & H1_MF_CHNK) && !h1m->body_len)
|
||||
h1m->state = H1_MSG_DONE;
|
||||
|
||||
if (!h1_process_req_vsn(h1s, h1m, sl)) {
|
||||
h1m->err_pos = sl.rq.v.ptr - b_head(buf);
|
||||
if (!h1_process_req_vsn(h1s, h1m, h1sl)) {
|
||||
h1m->err_pos = h1sl.rq.v.ptr - b_head(buf);
|
||||
h1m->err_state = h1m->state;
|
||||
goto vsn_error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
h1s->status = sl.st.status;
|
||||
h1s->status = h1sl.st.status;
|
||||
|
||||
if ((h1s->meth == HTTP_METH_HEAD) ||
|
||||
(h1s->status >= 100 && h1s->status < 200) ||
|
||||
@ -817,21 +830,44 @@ static size_t h1_process_headers(struct h1s *h1s, struct h1m *h1m, struct htx *h
|
||||
else
|
||||
h1m->state = H1_MSG_TUNNEL;
|
||||
|
||||
if (!h1_process_res_vsn(h1s, h1m, sl)) {
|
||||
h1m->err_pos = sl.st.v.ptr - b_head(buf);
|
||||
if (!h1_process_res_vsn(h1s, h1m, h1sl)) {
|
||||
h1m->err_pos = h1sl.st.v.ptr - b_head(buf);
|
||||
h1m->err_state = h1m->state;
|
||||
goto vsn_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set HTX start-line flags */
|
||||
if (h1m->flags & H1_MF_VER_11)
|
||||
flags |= HTX_SL_F_VER_11;
|
||||
if (h1m->flags & H1_MF_XFER_ENC)
|
||||
flags |= HTX_SL_F_XFER_ENC;
|
||||
if (h1m->flags & H1_MF_XFER_LEN) {
|
||||
flags |= HTX_SL_F_XFER_LEN;
|
||||
if (h1m->flags & H1_MF_CHNK)
|
||||
flags |= HTX_SL_F_CHNK;
|
||||
else if (h1m->flags & H1_MF_CLEN)
|
||||
flags |= HTX_SL_F_CLEN;
|
||||
}
|
||||
|
||||
if (!(h1m->flags & H1_MF_RESP)) {
|
||||
if (!htx_add_reqline(htx, sl) || !htx_add_all_headers(htx, hdrs))
|
||||
struct htx_sl *sl;
|
||||
|
||||
sl = htx_add_stline(htx, HTX_BLK_REQ_SL, flags, h1sl.rq.m, h1sl.rq.u, h1sl.rq.v);
|
||||
if (!sl || !htx_add_all_headers(htx, hdrs))
|
||||
goto error;
|
||||
sl->info.req.meth = h1s->meth;
|
||||
}
|
||||
else {
|
||||
if (!htx_add_resline(htx, sl) || !htx_add_all_headers(htx, hdrs))
|
||||
struct htx_sl *sl;
|
||||
|
||||
flags |= HTX_SL_F_IS_RESP;
|
||||
sl = htx_add_stline(htx, HTX_BLK_RES_SL, flags, h1sl.st.v, h1sl.st.c, h1sl.st.r);
|
||||
if (!sl || !htx_add_all_headers(htx, hdrs))
|
||||
goto error;
|
||||
sl->info.res.status = h1s->status;
|
||||
}
|
||||
|
||||
if (h1m->state == H1_MSG_DONE)
|
||||
if (!htx_add_endof(htx, HTX_BLK_EOM))
|
||||
goto error;
|
||||
|
120
src/proto_htx.c
120
src/proto_htx.c
@ -43,9 +43,9 @@ static void htx_end_response(struct stream *s);
|
||||
|
||||
static void htx_capture_headers(struct htx *htx, char **cap, struct cap_hdr *cap_hdr);
|
||||
static int htx_del_hdr_value(char *start, char *end, char **from, char *next);
|
||||
static size_t htx_fmt_req_line(const union h1_sl sl, char *str, size_t len);
|
||||
static size_t htx_fmt_res_line(const union h1_sl sl, char *str, size_t len);
|
||||
static void htx_debug_stline(const char *dir, struct stream *s, const union h1_sl sl);
|
||||
static size_t htx_fmt_req_line(const struct htx_sl *sl, char *str, size_t len);
|
||||
static size_t htx_fmt_res_line(const struct htx_sl *sl, char *str, size_t len);
|
||||
static void htx_debug_stline(const char *dir, struct stream *s, const struct htx_sl *sl);
|
||||
static void htx_debug_hdr(const char *dir, struct stream *s, const struct ist n, const struct ist v);
|
||||
|
||||
static enum rule_result htx_req_get_intercept_rule(struct proxy *px, struct list *rules, struct stream *s, int *deny_status);
|
||||
@ -81,7 +81,7 @@ int htx_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
||||
struct http_txn *txn = s->txn;
|
||||
struct http_msg *msg = &txn->req;
|
||||
struct htx *htx;
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
|
||||
DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
|
||||
now_ms, __FUNCTION__,
|
||||
@ -301,19 +301,19 @@ int htx_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
||||
* 1: identify the method
|
||||
*/
|
||||
sl = http_find_stline(htx);
|
||||
txn->meth = sl.rq.meth;
|
||||
txn->meth = sl->info.req.meth;
|
||||
msg->flags |= HTTP_MSGF_XFER_LEN;
|
||||
|
||||
/* ... and check if the request is HTTP/1.1 or above */
|
||||
if ((sl.rq.v.len == 8) &&
|
||||
((*(sl.rq.v.ptr + 5) > '1') ||
|
||||
((*(sl.rq.v.ptr + 5) == '1') && (*(sl.rq.v.ptr + 7) >= '1'))))
|
||||
if ((HTX_SL_REQ_VLEN(sl) == 8) &&
|
||||
((*(HTX_SL_REQ_VPTR(sl) + 5) > '1') ||
|
||||
((*(HTX_SL_REQ_VPTR(sl) + 5) == '1') && (*(HTX_SL_REQ_VPTR(sl) + 7) >= '1'))))
|
||||
msg->flags |= HTTP_MSGF_VER_11;
|
||||
|
||||
/* we can make use of server redirect on GET and HEAD */
|
||||
if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD)
|
||||
s->flags |= SF_REDIRECTABLE;
|
||||
else if (txn->meth == HTTP_METH_OTHER && isteqi(sl.rq.m, ist("PRI"))) {
|
||||
else if (txn->meth == HTTP_METH_OTHER && isteqi(htx_sl_req_meth(sl), ist("PRI"))) {
|
||||
/* PRI is reserved for the HTTP/2 preface */
|
||||
goto return_bad_req;
|
||||
}
|
||||
@ -324,7 +324,7 @@ int htx_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
||||
* the monitor-uri is defined by the frontend.
|
||||
*/
|
||||
if (unlikely((sess->fe->monitor_uri_len != 0) &&
|
||||
isteqi(sl.rq.u, ist2(sess->fe->monitor_uri, sess->fe->monitor_uri_len)))) {
|
||||
isteqi(htx_sl_req_uri(sl), ist2(sess->fe->monitor_uri, sess->fe->monitor_uri_len)))) {
|
||||
/*
|
||||
* We have found the monitor URI
|
||||
*/
|
||||
@ -389,7 +389,7 @@ int htx_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
||||
* CONNECT ip:port.
|
||||
*/
|
||||
if ((sess->fe->options2 & PR_O2_USE_PXHDR) &&
|
||||
*(sl.rq.u.ptr) != '/' && *(sl.rq.u.ptr) != '*')
|
||||
*HTX_SL_REQ_UPTR(sl) != '/' && *HTX_SL_REQ_UPTR(sl) != '*')
|
||||
txn->flags |= TX_USE_PX_CONN;
|
||||
|
||||
/* 5: we may need to capture headers */
|
||||
@ -777,8 +777,8 @@ int htx_process_request(struct stream *s, struct channel *req, int an_bit)
|
||||
*/
|
||||
if ((s->be->options & PR_O_HTTP_PROXY) && !(s->flags & SF_ADDR_SET)) {
|
||||
struct connection *conn;
|
||||
union h1_sl sl;
|
||||
struct ist path;
|
||||
struct htx_sl *sl;
|
||||
struct ist uri, path;
|
||||
|
||||
/* Note that for now we don't reuse existing proxy connections */
|
||||
if (unlikely((conn = cs_conn(si_alloc_cs(&s->si[1], NULL))) == NULL)) {
|
||||
@ -796,8 +796,9 @@ int htx_process_request(struct stream *s, struct channel *req, int an_bit)
|
||||
return 0;
|
||||
}
|
||||
sl = http_find_stline(htx);
|
||||
path = http_get_path(sl.rq.u);
|
||||
if (url2sa(sl.rq.u.ptr, sl.rq.u.len - path.len, &conn->addr.to, NULL) == -1)
|
||||
uri = htx_sl_req_uri(sl);
|
||||
path = http_get_path(uri);
|
||||
if (url2sa(uri.ptr, uri.len - path.len, &conn->addr.to, NULL) == -1)
|
||||
goto return_bad_req;
|
||||
|
||||
/* if the path was found, we have to remove everything between
|
||||
@ -805,13 +806,10 @@ int htx_process_request(struct stream *s, struct channel *req, int an_bit)
|
||||
* to replace from all the uri by a single "/".
|
||||
*
|
||||
* Instead of rewritting the whole start line, we just update
|
||||
* <sl.rq.u>. Some space will be lost but it should be
|
||||
* the star-line URI. Some space will be lost but it should be
|
||||
* insignificant.
|
||||
*/
|
||||
if (path.ptr)
|
||||
sl.rq.u = path;
|
||||
else
|
||||
istcpy(&sl.rq.u, ist("/"), 1);
|
||||
istcpy(&uri, (path.len ? path : ist("/")), uri.len);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1429,7 +1427,7 @@ int htx_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
struct http_msg *msg = &txn->rsp;
|
||||
struct htx *htx;
|
||||
struct connection *srv_conn;
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
int n;
|
||||
|
||||
DPRINTF(stderr,"[%u] %s: stream=%p b=%p, exp(r,w)=%u,%u bf=%08x bh=%lu analysers=%02x\n",
|
||||
@ -1612,14 +1610,14 @@ int htx_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
|
||||
/* 1: get the status code */
|
||||
sl = http_find_stline(htx);
|
||||
txn->status = sl.st.status;
|
||||
txn->status = sl->info.res.status;
|
||||
if (htx->extra != ULLONG_MAX)
|
||||
msg->flags |= HTTP_MSGF_XFER_LEN;
|
||||
|
||||
/* ... and check if the request is HTTP/1.1 or above */
|
||||
if ((sl.st.v.len == 8) &&
|
||||
((*(sl.st.v.ptr + 5) > '1') ||
|
||||
((*(sl.st.v.ptr + 5) == '1') && (*(sl.st.v.ptr + 7) >= '1'))))
|
||||
if ((HTX_SL_RES_VLEN(sl) == 8) &&
|
||||
((*(HTX_SL_RES_VPTR(sl) + 5) > '1') ||
|
||||
((*(HTX_SL_RES_VPTR(sl) + 5) == '1') && (*(HTX_SL_RES_VPTR(sl) + 7) >= '1'))))
|
||||
msg->flags |= HTTP_MSGF_VER_11;
|
||||
|
||||
n = txn->status / 100;
|
||||
@ -2319,7 +2317,7 @@ void htx_adjust_conn_mode(struct stream *s, struct http_txn *txn)
|
||||
int htx_apply_redirect_rule(struct redirect_rule *rule, struct stream *s, struct http_txn *txn)
|
||||
{
|
||||
struct htx *htx = htx_from_buf(&s->req.buf);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
const char *msg_fmt;
|
||||
struct buffer *chunk;
|
||||
int ret = 0;
|
||||
@ -2362,7 +2360,7 @@ int htx_apply_redirect_rule(struct redirect_rule *rule, struct stream *s, struct
|
||||
host = ctx.value;
|
||||
|
||||
sl = http_find_stline(htx);
|
||||
path = http_get_path(sl.rq.u);
|
||||
path = http_get_path(htx_sl_req_uri(sl));
|
||||
/* build message using path */
|
||||
if (path.ptr) {
|
||||
if (rule->flags & REDIRECT_FLAG_DROP_QS) {
|
||||
@ -2409,7 +2407,7 @@ int htx_apply_redirect_rule(struct redirect_rule *rule, struct stream *s, struct
|
||||
struct ist path;
|
||||
|
||||
sl = http_find_stline(htx);
|
||||
path = http_get_path(sl.rq.u);
|
||||
path = http_get_path(htx_sl_req_uri(sl));
|
||||
/* build message using path */
|
||||
if (path.ptr) {
|
||||
if (rule->flags & REDIRECT_FLAG_DROP_QS) {
|
||||
@ -3535,7 +3533,8 @@ static int htx_apply_filter_to_req_line(struct stream *s, struct channel *req, s
|
||||
|
||||
/* Now we have the request line between cur_ptr and cur_end */
|
||||
if (regex_exec_match2(exp->preg, reqline->area, reqline->data, MAX_MATCH, pmatch, 0)) {
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl = http_find_stline(htx);
|
||||
struct ist meth, uri, vsn;
|
||||
int len;
|
||||
|
||||
switch (exp->action) {
|
||||
@ -3559,11 +3558,9 @@ static int htx_apply_filter_to_req_line(struct stream *s, struct channel *req, s
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
http_parse_stline(ist2(trash.area, len),
|
||||
&sl.rq.m, &sl.rq.u, &sl.rq.v);
|
||||
sl.rq.meth = find_http_meth(sl.rq.m.ptr, sl.rq.m.len);
|
||||
|
||||
if (!http_replace_reqline(htx, sl))
|
||||
http_parse_stline(ist2(trash.area, len), &meth, &uri, &vsn);
|
||||
sl->info.req.meth = find_http_meth(meth.ptr, meth.len);
|
||||
if (!http_replace_stline(htx, meth, uri, vsn))
|
||||
return -1;
|
||||
done = 1;
|
||||
break;
|
||||
@ -3745,7 +3742,8 @@ static int htx_apply_filter_to_sts_line(struct stream *s, struct channel *res, s
|
||||
|
||||
/* Now we have the status line between cur_ptr and cur_end */
|
||||
if (regex_exec_match2(exp->preg, resline->area, resline->data, MAX_MATCH, pmatch, 0)) {
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl = http_find_stline(htx);
|
||||
struct ist vsn, code, reason;
|
||||
int len;
|
||||
|
||||
switch (exp->action) {
|
||||
@ -3764,11 +3762,9 @@ static int htx_apply_filter_to_sts_line(struct stream *s, struct channel *res, s
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
http_parse_stline(ist2(trash.area, len),
|
||||
&sl.st.v, &sl.st.c, &sl.st.r);
|
||||
sl.st.status = strl2ui(sl.st.c.ptr, sl.st.c.len);
|
||||
|
||||
if (!http_replace_resline(htx, sl))
|
||||
http_parse_stline(ist2(trash.area, len), &vsn, &code, &reason);
|
||||
sl->info.res.status = strl2ui(code.ptr, code.len);
|
||||
if (!http_replace_stline(htx, vsn, code, reason))
|
||||
return -1;
|
||||
|
||||
done = 1;
|
||||
@ -4729,8 +4725,8 @@ static int htx_stats_check_uri(struct stream *s, struct http_txn *txn, struct pr
|
||||
{
|
||||
struct uri_auth *uri_auth = backend->uri_auth;
|
||||
struct htx *htx;
|
||||
struct htx_sl *sl;
|
||||
struct ist uri;
|
||||
union h1_sl sl;
|
||||
|
||||
if (!uri_auth)
|
||||
return 0;
|
||||
@ -4740,7 +4736,7 @@ static int htx_stats_check_uri(struct stream *s, struct http_txn *txn, struct pr
|
||||
|
||||
htx = htx_from_buf(&s->req.buf);
|
||||
sl = http_find_stline(htx);
|
||||
uri = sl.rq.u;
|
||||
uri = htx_sl_req_uri(sl);
|
||||
|
||||
/* check URI size */
|
||||
if (uri_auth->uri_len > uri.len)
|
||||
@ -4771,7 +4767,7 @@ static int htx_handle_stats(struct stream *s, struct channel *req)
|
||||
const char *h, *lookup, *end;
|
||||
struct appctx *appctx;
|
||||
struct htx *htx;
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
|
||||
appctx = si_appctx(si);
|
||||
memset(&appctx->ctx.stats, 0, sizeof(appctx->ctx.stats));
|
||||
@ -4783,8 +4779,8 @@ static int htx_handle_stats(struct stream *s, struct channel *req)
|
||||
|
||||
htx = htx_from_buf(&req->buf);
|
||||
sl = http_find_stline(htx);
|
||||
lookup = sl.rq.u.ptr + uri_auth->uri_len;
|
||||
end = sl.rq.u.ptr + sl.rq.u.len;
|
||||
lookup = HTX_SL_REQ_UPTR(sl) + uri_auth->uri_len;
|
||||
end = HTX_SL_REQ_UPTR(sl) + HTX_SL_REQ_ULEN(sl);
|
||||
|
||||
for (h = lookup; h <= end - 3; h++) {
|
||||
if (memcmp(h, ";up", 3) == 0) {
|
||||
@ -4913,8 +4909,8 @@ void htx_perform_server_redirect(struct stream *s, struct stream_interface *si)
|
||||
{
|
||||
struct http_txn *txn = s->txn;
|
||||
struct htx *htx;
|
||||
struct htx_sl *sl;
|
||||
struct server *srv;
|
||||
union h1_sl sl;
|
||||
struct ist path;
|
||||
|
||||
/* 1: create the response header */
|
||||
@ -4932,7 +4928,7 @@ void htx_perform_server_redirect(struct stream *s, struct stream_interface *si)
|
||||
/* 3: add the request Path */
|
||||
htx = htx_from_buf(&s->req.buf);
|
||||
sl = http_find_stline(htx);
|
||||
path = http_get_path(sl.rq.u);
|
||||
path = http_get_path(htx_sl_req_uri(sl));
|
||||
if (!path.ptr)
|
||||
return;
|
||||
|
||||
@ -5358,23 +5354,23 @@ static int htx_del_hdr_value(char *start, char *end, char **from, char *next)
|
||||
/* Formats the start line of the request (without CRLF) and puts it in <str> and
|
||||
* return the written lenght. The line can be truncated if it exceeds <len>.
|
||||
*/
|
||||
static size_t htx_fmt_req_line(const union h1_sl sl, char *str, size_t len)
|
||||
static size_t htx_fmt_req_line(const struct htx_sl *sl, char *str, size_t len)
|
||||
{
|
||||
struct ist dst = ist2(str, 0);
|
||||
|
||||
if (istcat(&dst, sl.rq.m, len) == -1)
|
||||
if (istcat(&dst, htx_sl_req_meth(sl), len) == -1)
|
||||
goto end;
|
||||
if (dst.len + 1 > len)
|
||||
goto end;
|
||||
dst.ptr[dst.len++] = ' ';
|
||||
|
||||
if (istcat(&dst, sl.rq.u, len) == -1)
|
||||
if (istcat(&dst, htx_sl_req_uri(sl), len) == -1)
|
||||
goto end;
|
||||
if (dst.len + 1 > len)
|
||||
goto end;
|
||||
dst.ptr[dst.len++] = ' ';
|
||||
|
||||
istcat(&dst, sl.rq.v, len);
|
||||
istcat(&dst, htx_sl_req_vsn(sl), len);
|
||||
end:
|
||||
return dst.len;
|
||||
}
|
||||
@ -5382,23 +5378,23 @@ static size_t htx_fmt_req_line(const union h1_sl sl, char *str, size_t len)
|
||||
/* Formats the start line of the response (without CRLF) and puts it in <str> and
|
||||
* return the written lenght. The line can be truncated if it exceeds <len>.
|
||||
*/
|
||||
static size_t htx_fmt_res_line(const union h1_sl sl, char *str, size_t len)
|
||||
static size_t htx_fmt_res_line(const struct htx_sl *sl, char *str, size_t len)
|
||||
{
|
||||
struct ist dst = ist2(str, 0);
|
||||
|
||||
if (istcat(&dst, sl.st.v, len) == -1)
|
||||
if (istcat(&dst, htx_sl_res_vsn(sl), len) == -1)
|
||||
goto end;
|
||||
if (dst.len + 1 > len)
|
||||
goto end;
|
||||
dst.ptr[dst.len++] = ' ';
|
||||
|
||||
if (istcat(&dst, sl.st.c, len) == -1)
|
||||
if (istcat(&dst, htx_sl_res_code(sl), len) == -1)
|
||||
goto end;
|
||||
if (dst.len + 1 > len)
|
||||
goto end;
|
||||
dst.ptr[dst.len++] = ' ';
|
||||
|
||||
istcat(&dst, sl.st.r, len);
|
||||
istcat(&dst, htx_sl_res_reason(sl), len);
|
||||
end:
|
||||
return dst.len;
|
||||
}
|
||||
@ -5407,7 +5403,7 @@ static size_t htx_fmt_res_line(const union h1_sl sl, char *str, size_t len)
|
||||
/*
|
||||
* Print a debug line with a start line.
|
||||
*/
|
||||
static void htx_debug_stline(const char *dir, struct stream *s, const union h1_sl sl)
|
||||
static void htx_debug_stline(const char *dir, struct stream *s, const struct htx_sl *sl)
|
||||
{
|
||||
struct session *sess = strm_sess(s);
|
||||
int max;
|
||||
@ -5417,19 +5413,19 @@ static void htx_debug_stline(const char *dir, struct stream *s, const union h1_s
|
||||
objt_conn(sess->origin) ? (unsigned short)objt_conn(sess->origin)->handle.fd : -1,
|
||||
objt_cs(s->si[1].end) ? (unsigned short)objt_cs(s->si[1].end)->conn->handle.fd : -1);
|
||||
|
||||
max = sl.rq.m.len;
|
||||
max = HTX_SL_P1_LEN(sl);
|
||||
UBOUND(max, trash.size - trash.data - 3);
|
||||
chunk_memcat(&trash, sl.rq.m.ptr, max);
|
||||
chunk_memcat(&trash, HTX_SL_P1_PTR(sl), max);
|
||||
trash.area[trash.data++] = ' ';
|
||||
|
||||
max = sl.rq.u.len;
|
||||
max = HTX_SL_P2_LEN(sl);
|
||||
UBOUND(max, trash.size - trash.data - 2);
|
||||
chunk_memcat(&trash, sl.rq.u.ptr, max);
|
||||
chunk_memcat(&trash, HTX_SL_P2_PTR(sl), max);
|
||||
trash.area[trash.data++] = ' ';
|
||||
|
||||
max = sl.rq.v.len;
|
||||
max = HTX_SL_P3_LEN(sl);
|
||||
UBOUND(max, trash.size - trash.data - 1);
|
||||
chunk_memcat(&trash, sl.rq.v.ptr, max);
|
||||
chunk_memcat(&trash, HTX_SL_P3_PTR(sl), max);
|
||||
trash.area[trash.data++] = '\n';
|
||||
|
||||
shut_your_big_mouth_gcc(write(1, trash.area, trash.data));
|
||||
|
25
src/stats.c
25
src/stats.c
@ -2984,15 +2984,14 @@ static int stats_send_htx_headers(struct stream_interface *si, struct htx *htx)
|
||||
struct stream *s = si_strm(si);
|
||||
struct uri_auth *uri = s->be->uri_auth;
|
||||
struct appctx *appctx = __objt_appctx(si->end);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
unsigned int flags;
|
||||
|
||||
sl.st.status = 200;
|
||||
sl.st.v = ist("HTTP/1.1");
|
||||
sl.st.c = ist("200");
|
||||
sl.st.r = ist("OK");
|
||||
|
||||
if (!htx_add_resline(htx, sl))
|
||||
flags = (HTX_SL_F_IS_RESP|HTX_SL_F_VER_11|HTX_SL_F_XFER_ENC|HTX_SL_F_XFER_LEN|HTX_SL_F_CHNK);
|
||||
sl = htx_add_stline(htx, HTX_BLK_RES_SL, flags, ist("HTTP/1.1"), ist("200"), ist("OK"));
|
||||
if (!sl)
|
||||
goto full;
|
||||
sl->info.res.status = 200;
|
||||
|
||||
if (!htx_add_header(htx, ist("Cache-Control"), ist("no-cache")) ||
|
||||
!htx_add_header(htx, ist("Connection"), ist("close")))
|
||||
@ -3035,7 +3034,8 @@ static int stats_send_htx_redirect(struct stream_interface *si, struct htx *htx)
|
||||
struct stream *s = si_strm(si);
|
||||
struct uri_auth *uri = s->be->uri_auth;
|
||||
struct appctx *appctx = __objt_appctx(si->end);
|
||||
union h1_sl sl;
|
||||
struct htx_sl *sl;
|
||||
unsigned int flags;
|
||||
|
||||
/* scope_txt = search pattern + search query, appctx->ctx.stats.scope_len is always <= STAT_SCOPE_TXT_MAXLEN */
|
||||
scope_txt[0] = 0;
|
||||
@ -3060,12 +3060,11 @@ static int stats_send_htx_redirect(struct stream_interface *si, struct htx *htx)
|
||||
(appctx->ctx.stats.flags & STAT_NO_REFRESH) ? ";norefresh" : "",
|
||||
scope_txt);
|
||||
|
||||
sl.st.status = 303;
|
||||
sl.st.v = ist("HTTP/1.1");
|
||||
sl.st.c = ist("303");
|
||||
sl.st.r = ist("See Other");
|
||||
if (!htx_add_resline(htx, sl))
|
||||
flags = (HTX_SL_F_IS_RESP|HTX_SL_F_VER_11|HTX_SL_F_XFER_LEN|HTX_SL_F_CHNK);
|
||||
sl = htx_add_stline(htx, HTX_BLK_RES_SL, flags, ist("HTTP/1.1"), ist("303"), ist("See Other"));
|
||||
if (!sl)
|
||||
goto full;
|
||||
sl->info.res.status = 303;
|
||||
|
||||
if (!htx_add_header(htx, ist("Cache-Control"), ist("no-cache")) ||
|
||||
!htx_add_header(htx, ist("Connection"), ist("close")) ||
|
||||
|
Loading…
Reference in New Issue
Block a user