]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: tune.http.maxhdr makes it possible to configure the maximum number of HTTP...
authorWilly Tarreau <w@1wt.eu>
Mon, 24 Oct 2011 17:14:41 +0000 (19:14 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 24 Oct 2011 17:14:41 +0000 (19:14 +0200)
For a long time, the max number of headers was taken as a part of the buffer
size. Since the header size can be configured at runtime, it does not make
much sense anymore.

Nothing was making it necessary to have a static value, so let's turn this into
a tunable with a default value of 101 which equals what was previously used.

doc/configuration.txt
include/common/defaults.h
include/types/global.h
include/types/proto_http.h
src/cfgparse.c
src/frontend.c
src/proxy.c

index 5cce3b46b892504adfd714522edeb52cbf267a58..afe1bfc6552906e1e9363d5da32420ae92bd63f3 100644 (file)
@@ -458,6 +458,7 @@ The following keywords are supported in the "global" section :
    - spread-checks
    - tune.bufsize
    - tune.chksize
+   - tune.http.maxhdr
    - tune.maxaccept
    - tune.maxpollevents
    - tune.maxrewrite
@@ -725,6 +726,17 @@ tune.chksize <number>
   build time. It is not recommended to change this value, but to use better
   checks whenever possible.
 
+tune.http.maxhdr <number>
+  Sets the maximum number of headers in a request. When a request comes with a
+  number of headers greater than this value (including the first line), it is
+  rejected with a "400 Bad Request" status code. Similarly, too large responses
+  are blocked with "502 Bad Gateway". The default value is 101, which is enough
+  for all usages, considering that the widely deployed Apache server uses the
+  same limit. It can be useful to push this limit further to temporarily allow
+  a buggy application to work by the time it gets fixed. Keep in mind that each
+  new header consumes 32bits of memory for each session, so don't push this
+  limit too high.
+
 tune.maxaccept <number>
   Sets the maximum number of consecutive accepts that a process may perform on
   a single wake up. High values give higher priority to high connection rates,
index 0a4f42068f7f739e204918e0a94bafe12cb6e49a..86471313784968d44cc59f48155a144490e5afb9 100644 (file)
@@ -58,9 +58,9 @@
 #define        MAX_MATCH       10
 
 // max # of headers in one HTTP request or response
-// By default, about 100 headers per 8 kB.
+// By default, about 100 headers (+1 for the first line)
 #ifndef MAX_HTTP_HDR
-#define MAX_HTTP_HDR    ((BUFSIZE+79)/80)
+#define MAX_HTTP_HDR    101
 #endif
 
 // max # of headers in history when looking for header #-X
index 078a1d55cb17918eff6e349f92324239cf52e8f5..56110e8d2209d9be24fd436c6086324cc378dccf 100644 (file)
@@ -97,6 +97,7 @@ struct global {
                int server_rcvbuf; /* set server rcvbuf to this value if not null */
                int chksize;       /* check buffer size in bytes, defaults to BUFSIZE */
                int pipesize;      /* pipe size in bytes, system defaults if zero */
+               int max_http_hdr;  /* max number of HTTP headers, use MAX_HTTP_HDR if zero */
        } tune;
        struct {
                char *prefix;           /* path prefix of unix bind socket */
index d9bf83096407af9c4965620334b7b34e42182cb0..f1b3eef524410a32329a7296e061062120d103b2 100644 (file)
@@ -322,7 +322,7 @@ struct http_req_rule {
  */
 struct http_txn {
        struct http_msg req;            /* HTTP request message */
-       struct hdr_idx hdr_idx;         /* array of header indexes (max: MAX_HTTP_HDR) */
+       struct hdr_idx hdr_idx;         /* array of header indexes (max: global.tune.max_http_hdr) */
        unsigned int flags;             /* transaction flags */
        http_meth_t meth;               /* HTTP method */
 
index dac6bcab5ea31b5afb97e3bb4437d4a97840968e..5ddfbe26fed09b97d09b2358086c065266420c65 100644 (file)
@@ -596,6 +596,14 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
                }
                global.tune.pipesize = atol(args[1]);
        }
+       else if (!strcmp(args[0], "tune.http.maxhdr")) {
+               if (*(args[1]) == 0) {
+                       Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+               }
+               global.tune.max_http_hdr = atol(args[1]);
+       }
        else if (!strcmp(args[0], "uid")) {
                if (global.uid != 0) {
                        Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
@@ -6595,8 +6603,11 @@ out_uri_auth_compat:
                }
        }
 
+       if (!global.tune.max_http_hdr)
+               global.tune.max_http_hdr = MAX_HTTP_HDR;
+
        pool2_hdr_idx = create_pool("hdr_idx",
-                                   MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
+                                   global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
                                    MEM_F_SHARED);
 
        if (cfgerr > 0)
index 195a42414d8246ad4d83cf043315de503aa8dfe1..19980c0f41c1e9f0b45156fb75897c7f13c96905 100644 (file)
@@ -134,7 +134,7 @@ int frontend_accept(struct session *s)
                 * that we may make use of them. This of course includes
                 * (mode == PR_MODE_HTTP).
                 */
-               s->txn.hdr_idx.size = MAX_HTTP_HDR;
+               s->txn.hdr_idx.size = global.tune.max_http_hdr;
 
                if (unlikely((s->txn.hdr_idx.v = pool_alloc2(pool2_hdr_idx)) == NULL))
                        goto out_free_rspcap; /* no memory */
index d274dfe5fbfd1c51d6004c5ed4504b3a0e8f7fac..caec45d48558a367a0e9a84a7bd65f4c1e7d3765 100644 (file)
@@ -819,7 +819,7 @@ int session_set_backend(struct session *s, struct proxy *be)
                /* and now initialize the HTTP transaction state */
                http_init_txn(s);
 
-               s->txn.hdr_idx.size = MAX_HTTP_HDR;
+               s->txn.hdr_idx.size = global.tune.max_http_hdr;
                hdr_idx_init(&s->txn.hdr_idx);
        }