MEDIUM: tune.http.maxhdr makes it possible to configure the maximum number of HTTP headers

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.
This commit is contained in:
Willy Tarreau 2011-10-24 19:14:41 +02:00
parent 34eb671f24
commit ac1932da3e
7 changed files with 30 additions and 6 deletions

View 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,

View 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

View 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 */

View 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 */

View 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)

View 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 */

View 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);
}