]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: htx: Don't rely on h1_sl anymore except during H1 header parsing
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 26 Nov 2018 20:37:08 +0000 (21:37 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 1 Dec 2018 16:37:27 +0000 (17:37 +0100)
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.

include/proto/http_htx.h
include/proto/htx.h
src/http_fetch.c
src/http_htx.c
src/htx.c
src/mux_h1.c
src/proto_htx.c
src/stats.c

index 7a6d476b5761d21b15f25064bb1203b2a01e67a4..9afea5c99ead7c74ad6bea9cf9fd7a51233165fe 100644 (file)
 #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);
index 296ff4df55529326fbcece8a28b23a28caa76ecf..9ee71e573def991a245622963176661e1c923cda 100644 (file)
@@ -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);
index 38905095962b931cc1694b042d67cbeed28cc030..884a32049718c776b6a6e8e947c5e4965c16f5e7 100644 (file)
@@ -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--;
index 1a8e5bb9e947545804a95e39fbe87f68aee183da..82f9497d951b43ff4a7cd3a3f2c70acda7fead85 100644 (file)
 #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));
 
-       /* 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);
+       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));
 
-       return http_replace_reqline(htx, new_sl);
+       /* create the new start line */
+       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));
 
-       /* 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);
+       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));
 
-       return http_replace_reqline(htx, new_sl);
+       /* create the new start line */
+       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, 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, sl.rq.u.ptr, p.ptr - sl.rq.u.ptr); /* uri: host part */
+       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, query.ptr + offset, query.len - offset); /* uri: new QS */
+       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));
 
-       /* 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;
+       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 */
+       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));
 
-       /* 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);
+       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));
 
-       return http_replace_resline(htx, new_sl);
+       /* create the new start line */
+       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));
 
-       /* 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;
+       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));
 
-       return http_replace_resline(htx, new_sl);
+       /* create the new start line */
+       return http_replace_stline(htx, vsn, status, reason);
 }
 
 /* Replaces a part of a header value referenced in the context <ctx> by
index a57e1e8e785bf8441e23cea7010425901632cf9d..a57c57d15f9eda8e1ea1364a5f63f0a50308183e 100644 (file)
--- a/src/htx.c
+++ b/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;
-}
 
-/* Replaces the response start line a new one. It returns the new block on
- * success, otherwise it returns NULL.
- */
-struct htx_blk *htx_replace_resline(struct htx *htx, struct htx_blk *blk,
-                                   const union h1_sl sl)
-{
-        enum htx_blk_type type;
-       uint32_t size;
-
-        type = htx_get_blk_type(blk);
-        if (type != HTX_BLK_RES_SL)
-                return NULL;
+       /* 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;
 
-       if (htx->sl_off == blk->addr)
-               htx->sl_off = -1;
+       HTX_SL_P1_LEN(sl) = p1.len;
+       HTX_SL_P2_LEN(sl) = p2.len;
+       HTX_SL_P3_LEN(sl) = p3.len;
 
-       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)
-               return NULL;
+       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);
 
-       blk->info = (type << 28) + size;
-        htx_set_blk_resline(htx, blk, sl);
-       return blk;
+       return sl;
 }
 
-
-/* Adds an HTX block of type SL in <htx>. 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_add_reqline(struct htx *htx, 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_blk *blk;
+       struct htx_sl  *sl;
        uint32_t size;
 
-       size = sizeof(struct htx_sl) + sl.rq.m.len + sl.rq.u.len + sl.rq.v.len;
+       if (type != HTX_BLK_REQ_SL && type != HTX_BLK_RES_SL)
+               return NULL;
+
+       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
index 37c0f8883b379989db55c9ec685a38783f19d10a..47293618c02713d03386142dfcf9a442c1017830 100644 (file)
@@ -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;
index 0e1abb6b7d35a63f21dbbfc0f41077b98c96be27..693ea901f01da186ca729a33152d89e7b2507741 100644 (file)
@@ -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));
index c0de42961b9cc602042007783bf17f7a59bb844e..57968860fc6033af5b5bfa1435a7e60e56b0c6ae 100644 (file)
@@ -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;
-
-       sl.st.status = 200;
-       sl.st.v = ist("HTTP/1.1");
-       sl.st.c = ist("200");
-       sl.st.r = ist("OK");
+       struct htx_sl *sl;
+       unsigned int flags;
 
-       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")) ||