[MEDIUM] config: remove the limitation of 10 reqadd/rspadd statements

Now we use a linked list, there is no limit anymore.
This commit is contained in:
Willy Tarreau 2010-01-03 21:03:22 +01:00
parent 97cb780e81
commit deb9ed8f60
6 changed files with 62 additions and 67 deletions

View File

@ -1,23 +1,23 @@
/* /*
include/common/defaults.h * include/common/defaults.h
Miscellaneous default values. * Miscellaneous default values.
*
Copyright (C) 2000-2009 Willy Tarreau - w@1wt.eu * Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu
*
This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, version 2.1 * License as published by the Free Software Foundation, version 2.1
exclusively. * exclusively.
*
This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. * Lesser General Public License for more details.
*
You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#ifndef _COMMON_DEFAULTS_H #ifndef _COMMON_DEFAULTS_H
#define _COMMON_DEFAULTS_H #define _COMMON_DEFAULTS_H
@ -57,9 +57,6 @@
// max # args on a stats socket // max # args on a stats socket
#define MAX_STATS_ARGS 16 #define MAX_STATS_ARGS 16
// max # of added headers per request
#define MAX_NEWHDR 10
// max # of matches per regexp // max # of matches per regexp
#define MAX_MATCH 10 #define MAX_MATCH 10

View File

@ -1,6 +1,6 @@
/* /*
* list.h : list manipulation macros and structures. * list.h : list manipulation macros and structures.
* Copyright 2002-2008 Willy Tarreau <w@1wt.eu> * Copyright 2002-2010 Willy Tarreau <w@1wt.eu>
* *
*/ */
@ -33,6 +33,12 @@ struct bref {
struct list *ref; /* pointer to the target's list entry */ struct list *ref; /* pointer to the target's list entry */
}; };
/* a word list is a generic list with a pointer to a string in each element. */
struct wordlist {
struct list list;
char *s;
};
/* First undefine some macros which happen to also be defined on OpenBSD, /* First undefine some macros which happen to also be defined on OpenBSD,
* in sys/queue.h, used by sys/event.h * in sys/queue.h, used by sys/event.h
*/ */

View File

@ -2,7 +2,7 @@
* include/types/proxy.h * include/types/proxy.h
* This file defines everything related to proxies. * This file defines everything related to proxies.
* *
* Copyright (C) 2000-2009 Willy Tarreau - w@1wt.eu * Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -240,7 +240,6 @@ struct proxy {
int minlvl1, minlvl2; /* minimum log level for each server, 0 by default */ int minlvl1, minlvl2; /* minimum log level for each server, 0 by default */
int to_log; /* things to be logged (LW_*) */ int to_log; /* things to be logged (LW_*) */
int stop_time; /* date to stop listening, when stopping != 0 (int ticks) */ int stop_time; /* date to stop listening, when stopping != 0 (int ticks) */
int nb_reqadd, nb_rspadd;
struct hdr_exp *req_exp; /* regular expressions for request headers */ struct hdr_exp *req_exp; /* regular expressions for request headers */
struct hdr_exp *rsp_exp; /* regular expressions for response headers */ struct hdr_exp *rsp_exp; /* regular expressions for response headers */
int nb_req_cap, nb_rsp_cap; /* # of headers to be captured */ int nb_req_cap, nb_rsp_cap; /* # of headers to be captured */
@ -249,7 +248,7 @@ struct proxy {
struct pool_head *req_cap_pool, /* pools of pre-allocated char ** used to build the sessions */ struct pool_head *req_cap_pool, /* pools of pre-allocated char ** used to build the sessions */
*rsp_cap_pool; *rsp_cap_pool;
struct pool_head *hdr_idx_pool; /* pools of pre-allocated int* used for headers indexing */ struct pool_head *hdr_idx_pool; /* pools of pre-allocated int* used for headers indexing */
char *req_add[MAX_NEWHDR], *rsp_add[MAX_NEWHDR]; /* headers to be added */ struct list req_add, rsp_add; /* headers to be added */
struct pxcounters counters; /* statistics counters */ struct pxcounters counters; /* statistics counters */
int grace; /* grace time after stop request */ int grace; /* grace time after stop request */
char *check_req; /* HTTP or SSL request to use for PR_O_HTTP_CHK|PR_O_SSL3_CHK */ char *check_req; /* HTTP or SSL request to use for PR_O_HTTP_CHK|PR_O_SSL3_CHK */

View File

@ -1,7 +1,7 @@
/* /*
* Configuration parser * Configuration parser
* *
* Copyright 2000-2009 Willy Tarreau <w@1wt.eu> * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -327,7 +327,7 @@ int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, ch
*/ */
int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg) int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
{ {
if (proxy->nb_reqadd) { if (!LIST_ISEMPTY(&proxy->req_add)) {
Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n", Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
file, line, arg); file, line, arg);
return 1; return 1;
@ -796,6 +796,8 @@ static void init_new_proxy(struct proxy *p)
LIST_INIT(&p->mon_fail_cond); LIST_INIT(&p->mon_fail_cond);
LIST_INIT(&p->switching_rules); LIST_INIT(&p->switching_rules);
LIST_INIT(&p->tcp_req.inspect_rules); LIST_INIT(&p->tcp_req.inspect_rules);
LIST_INIT(&p->req_add);
LIST_INIT(&p->rsp_add);
/* Timeouts are defined as -1 */ /* Timeouts are defined as -1 */
proxy_reset_timeouts(p); proxy_reset_timeouts(p);
@ -3592,6 +3594,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]); warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
} }
else if (!strcmp(args[0], "reqadd")) { /* add request header */ else if (!strcmp(args[0], "reqadd")) { /* add request header */
struct wordlist *wl;
if (curproxy == &defproxy) { if (curproxy == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL; err_code |= ERR_ALERT | ERR_FATAL;
@ -3600,19 +3604,15 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL)) else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
err_code |= ERR_WARN; err_code |= ERR_WARN;
if (curproxy->nb_reqadd >= MAX_NEWHDR) {
Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
if (*(args[1]) == 0) { if (*(args[1]) == 0) {
Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]); Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL; err_code |= ERR_ALERT | ERR_FATAL;
goto out; goto out;
} }
curproxy->req_add[curproxy->nb_reqadd++] = strdup(args[1]); wl = calloc(1, sizeof(*wl));
wl->s = strdup(args[1]);
LIST_ADDQ(&curproxy->req_add, &wl->list);
warnif_misplaced_reqadd(curproxy, file, linenum, args[0]); warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
} }
else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */ else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
@ -3800,6 +3800,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
} }
} }
else if (!strcmp(args[0], "rspadd")) { /* add response header */ else if (!strcmp(args[0], "rspadd")) { /* add response header */
struct wordlist *wl;
if (curproxy == &defproxy) { if (curproxy == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL; err_code |= ERR_ALERT | ERR_FATAL;
@ -3808,19 +3810,15 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL)) else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
err_code |= ERR_WARN; err_code |= ERR_WARN;
if (curproxy->nb_rspadd >= MAX_NEWHDR) {
Alert("parsing [%s:%d] : too many '%s'. Continuing.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
if (*(args[1]) == 0) { if (*(args[1]) == 0) {
Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]); Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL; err_code |= ERR_ALERT | ERR_FATAL;
goto out; goto out;
} }
curproxy->rsp_add[curproxy->nb_rspadd++] = strdup(args[1]); wl = calloc(1, sizeof(*wl));
wl->s = strdup(args[1]);
LIST_ADDQ(&curproxy->rsp_add, &wl->list);
} }
else if (!strcmp(args[0], "errorloc") || else if (!strcmp(args[0], "errorloc") ||
!strcmp(args[0], "errorloc302") || !strcmp(args[0], "errorloc302") ||

View File

@ -1,6 +1,6 @@
/* /*
* HA-Proxy : High Availability-enabled HTTP/TCP proxy * HA-Proxy : High Availability-enabled HTTP/TCP proxy
* Copyright 2000-2009 Willy Tarreau <w@1wt.eu>. * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -23,15 +23,6 @@
* *
* ChangeLog has moved to the CHANGELOG file. * ChangeLog has moved to the CHANGELOG file.
* *
* TODO:
* - handle properly intermediate incomplete server headers. Done ?
* - handle hot-reconfiguration
* - fix client/server state transition when server is in connect or headers state
* and client suddenly disconnects. The server *should* switch to SHUT_WR, but
* still handle HTTP headers.
* - remove MAX_NEWHDR
* - cut this huge file into several ones
*
*/ */
#include <stdio.h> #include <stdio.h>
@ -706,6 +697,7 @@ void deinit(void)
struct acl *acl, *aclb; struct acl *acl, *aclb;
struct switching_rule *rule, *ruleb; struct switching_rule *rule, *ruleb;
struct redirect_rule *rdr, *rdrb; struct redirect_rule *rdr, *rdrb;
struct wordlist *wl, *wlb;
struct uri_auth *uap, *ua = NULL; struct uri_auth *uap, *ua = NULL;
struct user_auth *user; struct user_auth *user;
int i; int i;
@ -722,11 +714,17 @@ void deinit(void)
for (i = 0; i < HTTP_ERR_SIZE; i++) for (i = 0; i < HTTP_ERR_SIZE; i++)
chunk_destroy(&p->errmsg[i]); chunk_destroy(&p->errmsg[i]);
for (i = 0; i < p->nb_reqadd; i++) list_for_each_entry_safe(wl, wlb, &p->req_add, list) {
free(p->req_add[i]); LIST_DEL(&wl->list);
free(wl->s);
free(wl);
}
for (i = 0; i < p->nb_rspadd; i++) list_for_each_entry_safe(wl, wlb, &p->rsp_add, list) {
free(p->rsp_add[i]); LIST_DEL(&wl->list);
free(wl->s);
free(wl);
}
list_for_each_entry_safe(cond, condb, &p->block_cond, list) { list_for_each_entry_safe(cond, condb, &p->block_cond, list) {
LIST_DEL(&cond->list); LIST_DEL(&cond->list);

View File

@ -1,7 +1,7 @@
/* /*
* HTTP protocol analyzer * HTTP protocol analyzer
* *
* Copyright 2000-2009 Willy Tarreau <w@1wt.eu> * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -2515,6 +2515,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
struct http_msg *msg = &txn->req; struct http_msg *msg = &txn->req;
struct acl_cond *cond; struct acl_cond *cond;
struct redirect_rule *rule; struct redirect_rule *rule;
struct wordlist *wl;
int cur_idx; int cur_idx;
if (unlikely(msg->msg_state < HTTP_MSG_BODY)) { if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
@ -2674,11 +2675,8 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
} /* if must close keep-alive */ } /* if must close keep-alive */
/* add request headers from the rule sets in the same order */ /* add request headers from the rule sets in the same order */
for (cur_idx = 0; cur_idx < px->nb_reqadd; cur_idx++) { list_for_each_entry(wl, &px->req_add, list) {
if (unlikely(http_header_add_tail(req, if (unlikely(http_header_add_tail(req, &txn->req, &txn->hdr_idx, wl->s) < 0))
&txn->req,
&txn->hdr_idx,
px->req_add[cur_idx]) < 0))
goto return_bad_req; goto return_bad_req;
} }
@ -4015,7 +4013,7 @@ int http_process_res_common(struct session *t, struct buffer *rep, int an_bit, s
struct http_txn *txn = &t->txn; struct http_txn *txn = &t->txn;
struct http_msg *msg = &txn->rsp; struct http_msg *msg = &txn->rsp;
struct proxy *cur_proxy; struct proxy *cur_proxy;
int cur_idx; struct wordlist *wl;
int conn_ka = 0, conn_cl = 0; int conn_ka = 0, conn_cl = 0;
int must_close = 0; int must_close = 0;
int must_del_close = 0, must_keep = 0; int must_del_close = 0, must_keep = 0;
@ -4228,11 +4226,10 @@ int http_process_res_common(struct session *t, struct buffer *rep, int an_bit, s
} }
/* add response headers from the rule sets in the same order */ /* add response headers from the rule sets in the same order */
for (cur_idx = 0; cur_idx < rule_set->nb_rspadd; cur_idx++) { list_for_each_entry(wl, &rule_set->rsp_add, list) {
if (txn->status < 200) if (txn->status < 200)
break; break;
if (unlikely(http_header_add_tail(rep, &txn->rsp, &txn->hdr_idx, if (unlikely(http_header_add_tail(rep, &txn->rsp, &txn->hdr_idx, wl->s) < 0))
rule_set->rsp_add[cur_idx]) < 0))
goto return_bad_resp; goto return_bad_resp;
} }