diff --git a/doc/configuration.txt b/doc/configuration.txt index 900b9a719..0e409881e 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -3844,24 +3844,6 @@ port inetd for instance. This parameter is ignored if the "check" parameter is not set. See also the "addr" parameter. -redir - The "redir" parameter enables the redirection mode for all GET and HEAD - requests addressing this server. This means that instead of having HAProxy - forward the request to the server, it will send an "HTTP 302" response with - the "Location" header composed of this prefix immediately followed by the - requested URI beginning at the leading '/' of the path component. That means - that no trailing slash should be used after . All invalid requests - will be rejected, and all non-GET or HEAD requests will be normally served by - the server. Note that since the response is completely forged, no header - mangling nor cookie insertion is possible in the respose. However, cookies in - requests are still analysed, making this solution completely usable to direct - users to a remote location in case of local disaster. Main use consists in - increasing bandwidth for static servers by having the clients directly - connect to them. Note: never use a relative location here, it would cause a - loop between the client and HAProxy! - - Example : server srv1 192.168.1.1:80 redir http://image1.mydomain.com check - rise The "rise" parameter states that a server will be considered as operational after consecutive successful health checks. This value defaults to 2 diff --git a/include/types/server.h b/include/types/server.h index c93236cb4..cfc4d7d83 100644 --- a/include/types/server.h +++ b/include/types/server.h @@ -2,7 +2,7 @@ include/types/server.h This file defines everything related to servers. - Copyright (C) 2000-2008 Willy Tarreau - w@1wt.eu + Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -73,9 +73,7 @@ struct server { int state; /* server state (SRV_*) */ int prev_state; /* server state before last change (SRV_*) */ int cklen; /* the len of the cookie, to speed up checks */ - int rdr_len; /* the length of the redirection prefix */ char *cookie; /* the id set in the cookie */ - char *rdr_pfx; /* the redirection prefix */ struct proxy *proxy; /* the proxy this server belongs to */ int cur_sess, cur_sess_max; /* number of currently active sessions (including syn_sent) */ diff --git a/include/types/session.h b/include/types/session.h index 9437198d9..46569a571 100644 --- a/include/types/session.h +++ b/include/types/session.h @@ -50,7 +50,7 @@ #define SN_FRT_ADDR_SET 0x00000080 /* set if the frontend address has been filled */ #define SN_REDISP 0x00000100 /* set if this session was redispatched from one server to another */ #define SN_CONN_TAR 0x00000200 /* set if this session is turning around before reconnecting */ -#define SN_REDIRECTABLE 0x00000400 /* set if this session is redirectable (GET or HEAD) */ +/* unused: 0x00000400 */ /* unused: 0x00000800 */ /* session termination conditions, bits values 0x1000 to 0x7000 (0-7 shift 12) */ diff --git a/src/backend.c b/src/backend.c index 20e3a040d..a9d42a64c 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1059,13 +1059,6 @@ int assign_server_and_queue(struct session *s) return SRV_STATUS_INTERNAL; if (s->flags & SN_ASSIGNED) { - if ((s->flags & SN_REDIRECTABLE) && s->srv && s->srv->rdr_len) { - /* server scheduled for redirection, and already assigned. We - * don't want to go further nor check the queue. - */ - return SRV_STATUS_OK; - } - if (s->srv && s->srv->maxqueue > 0 && s->srv->nbpend >= s->srv->maxqueue) { s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET); s->srv = NULL; @@ -1091,13 +1084,6 @@ int assign_server_and_queue(struct session *s) err = assign_server(s); switch (err) { case SRV_STATUS_OK: - if ((s->flags & SN_REDIRECTABLE) && s->srv && s->srv->rdr_len) { - /* server supporting redirection and it is possible. - * Let's report that and ignore maxconn ! - */ - return SRV_STATUS_OK; - } - /* in balance mode, we might have servers with connection limits */ if (s->srv && s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) { @@ -1203,6 +1189,7 @@ int connect_server(struct session *s) struct sockaddr_in *remote = NULL; int ret, flags = 0; +#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) switch (s->srv->state & SRV_TPROXY_MASK) { case SRV_TPROXY_ADDR: remote = (struct sockaddr_in *)&s->srv->tproxy_addr; @@ -1217,6 +1204,7 @@ int connect_server(struct session *s) remote = (struct sockaddr_in *)&s->cli_addr; break; } +#endif ret = tcpv4_bind_socket(fd, flags, &s->srv->source_addr, remote); if (ret) { close(fd); @@ -1240,6 +1228,7 @@ int connect_server(struct session *s) struct sockaddr_in *remote = NULL; int ret, flags = 0; +#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) switch (s->be->options & PR_O_TPXY_MASK) { case PR_O_TPXY_ADDR: remote = (struct sockaddr_in *)&s->be->tproxy_addr; @@ -1254,7 +1243,7 @@ int connect_server(struct session *s) remote = (struct sockaddr_in *)&s->cli_addr; break; } - +#endif ret = tcpv4_bind_socket(fd, flags, &s->be->source_addr, remote); if (ret) { close(fd); diff --git a/src/cfgparse.c b/src/cfgparse.c index 9329df3eb..1815ed487 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -1547,11 +1547,6 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv) newsrv->cklen = strlen(args[cur_arg + 1]); cur_arg += 2; } - else if (!strcmp(args[cur_arg], "redir")) { - newsrv->rdr_pfx = strdup(args[cur_arg + 1]); - newsrv->rdr_len = strlen(args[cur_arg + 1]); - cur_arg += 2; - } else if (!strcmp(args[cur_arg], "rise")) { newsrv->rise = atol(args[cur_arg + 1]); newsrv->health = newsrv->rise; @@ -1696,7 +1691,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv) return -1; } else { - Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'check', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n", + Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n", file, linenum, newsrv->id); return -1; } @@ -2909,19 +2904,6 @@ int readcfgfile(const char *file) if (curproxy->options & PR_O_LOGASAP) curproxy->to_log &= ~LW_BYTES; - /* - * ensure that we're not cross-dressing a TCP server into HTTP. - */ - newsrv = curproxy->srv; - while (newsrv != NULL) { - if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) { - Alert("parsing %s, %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n", - file, proxy_type_str(curproxy), curproxy->id, linenum); - goto err; - } - newsrv = newsrv->next; - } - /* * If this server supports a maxconn parameter, it needs a dedicated * tasks to fill the emptied slots when a connection leaves. diff --git a/src/checks.c b/src/checks.c index 124f40c53..0fbe16678 100644 --- a/src/checks.c +++ b/src/checks.c @@ -422,10 +422,12 @@ void process_chk(struct task *t, struct timeval *next) struct sockaddr_in *remote = NULL; int ret, flags = 0; +#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) if ((s->state & SRV_TPROXY_MASK) == SRV_TPROXY_ADDR) { remote = (struct sockaddr_in *)&s->tproxy_addr; flags = 3; } +#endif ret = tcpv4_bind_socket(fd, flags, &s->source_addr, remote); if (ret) { s->result |= SRV_CHK_ERROR; @@ -445,10 +447,12 @@ void process_chk(struct task *t, struct timeval *next) struct sockaddr_in *remote = NULL; int ret, flags = 0; +#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) if ((s->proxy->options & PR_O_TPXY_MASK) == PR_O_TPXY_ADDR) { remote = (struct sockaddr_in *)&s->proxy->tproxy_addr; flags = 3; } +#endif ret = tcpv4_bind_socket(fd, flags, &s->proxy->source_addr, remote); if (ret) { s->result |= SRV_CHK_ERROR; diff --git a/src/proto_http.c b/src/proto_http.c index 429f57142..16b2f075d 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -592,54 +592,6 @@ static http_meth_t find_http_meth(const char *str, const int len) } -/* Parse the URI from the given transaction (which is assumed to be in request - * phase) and look for the "/" beginning the PATH. If not found, return NULL. - * It is returned otherwise. - */ -static char * -http_get_path(struct http_txn *txn) -{ - char *ptr, *end; - - ptr = txn->req.sol + txn->req.sl.rq.u; - end = ptr + txn->req.sl.rq.u_l; - - if (ptr >= end) - return NULL; - - /* RFC2616, par. 5.1.2 : - * Request-URI = "*" | absuri | abspath | authority - */ - - if (*ptr == '*') - return NULL; - - if (isalpha((unsigned char)*ptr)) { - /* this is a scheme as described by RFC3986, par. 3.1 */ - ptr++; - while (ptr < end && - (isalnum((unsigned char)*ptr) || *ptr == '+' || *ptr == '-' || *ptr == '.')) - ptr++; - /* skip '://' */ - if (ptr == end || *ptr++ != ':') - return NULL; - if (ptr == end || *ptr++ != '/') - return NULL; - if (ptr == end || *ptr++ != '/') - return NULL; - } - /* skip [user[:passwd]@]host[:[port]] */ - - while (ptr < end && *ptr != '/') - ptr++; - - if (ptr == end) - return NULL; - - /* OK, we got the '/' ! */ - return ptr; -} - /* Processes the client and server jobs of a session task, then * puts it back to the wait queue in a clean state, or * cleans up its resources if it must be deleted. Returns @@ -2499,59 +2451,9 @@ int process_srv(struct session *t) do { /* first, get a connection */ - if (txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD) - t->flags |= SN_REDIRECTABLE; - if (srv_redispatch_connect(t)) return t->srv_state != SV_STIDLE; - if ((t->flags & SN_REDIRECTABLE) && t->srv && t->srv->rdr_len) { - /* Server supporting redirection and it is possible. - * Invalid requests are reported as such. It concerns all - * the largest ones. - */ - struct chunk rdr; - char *path; - int len; - - /* 1: create the response header */ - rdr.len = strlen(HTTP_302); - rdr.str = trash; - memcpy(rdr.str, HTTP_302, rdr.len); - - /* 2: add the server's prefix */ - if (rdr.len + t->srv->rdr_len > sizeof(trash)) - goto cancel_redir; - - memcpy(rdr.str + rdr.len, t->srv->rdr_pfx, t->srv->rdr_len); - rdr.len += t->srv->rdr_len; - - /* 3: add the request URI */ - path = http_get_path(txn); - if (!path) - goto cancel_redir; - len = txn->req.sl.rq.u_l + (txn->req.sol+txn->req.sl.rq.u) - path; - if (rdr.len + len > sizeof(trash) - 4) /* 4 for CRLF-CRLF */ - goto cancel_redir; - - memcpy(rdr.str + rdr.len, path, len); - rdr.len += len; - memcpy(rdr.str + rdr.len, "\r\n\r\n", 4); - rdr.len += 4; - - srv_close_with_err(t, SN_ERR_PRXCOND, SN_FINST_C, 302, &rdr); - /* FIXME: we should increase a counter of redirects per server and per backend. */ - if (t->srv) - t->srv->cum_sess++; - return 1; - cancel_redir: - txn->status = 400; - t->fe->failed_req++; - srv_close_with_err(t, SN_ERR_PRXCOND, SN_FINST_C, - 400, error_message(t, HTTP_ERR_400)); - return 1; - } - /* try to (re-)connect to the server, and fail if we expire the * number of retries. */ @@ -5324,9 +5226,39 @@ acl_fetch_path(struct proxy *px, struct session *l4, void *l7, int dir, /* ensure the indexes are not affected */ return 0; - end = txn->req.sol + txn->req.sl.rq.u + txn->req.sl.rq.u_l; - ptr = http_get_path(txn); - if (!ptr) + ptr = txn->req.sol + txn->req.sl.rq.u; + end = ptr + txn->req.sl.rq.u_l; + + if (ptr >= end) + return 0; + + /* RFC2616, par. 5.1.2 : + * Request-URI = "*" | absuri | abspath | authority + */ + + if (*ptr == '*') + return 0; + + if (isalpha((unsigned char)*ptr)) { + /* this is a scheme as described by RFC3986, par. 3.1 */ + ptr++; + while (ptr < end && + (isalnum((unsigned char)*ptr) || *ptr == '+' || *ptr == '-' || *ptr == '.')) + ptr++; + /* skip '://' */ + if (ptr == end || *ptr++ != ':') + return 0; + if (ptr == end || *ptr++ != '/') + return 0; + if (ptr == end || *ptr++ != '/') + return 0; + } + /* skip [user[:passwd]@]host[:[port]] */ + + while (ptr < end && *ptr != '/') + ptr++; + + if (ptr == end) return 0; /* OK, we got the '/' ! */ diff --git a/tests/test-redir.cfg b/tests/test-redir.cfg deleted file mode 100644 index 4aebafd15..000000000 --- a/tests/test-redir.cfg +++ /dev/null @@ -1,35 +0,0 @@ -# This is a test configuration. -# It makes use of a farm built from 4 servers, 3 of which are remote and -# referenced only via an HTTP redirect (302), and the 4th one is normal. -# HTTP requests different from GET/HEAD should reach the servers directly -# while GET/HEAD should get redirected for the 3 first ones. - -global - #log /dev/log local0 - maxconn 1000 - stats socket /tmp/sock1 mode 600 - stats timeout 3000 - stats maxconn 2000 - -listen sample1 - #log global - #option httplog - mode http - retries 1 - option redispatch - contimeout 1000 - clitimeout 5000 - srvtimeout 5000 - maxconn 40000 - bind :8080 - #balance source - balance roundrobin - option allbackups - server rdr1 127.0.0.1:80 redir http://static1:80 weight 10 check inter 1000 fall 4 - server rdr2 127.0.0.2:80 redir http://static2:80 weight 20 check inter 1000 fall 4 - server rdr3 127.0.0.3:80 redir http://static3:80 weight 30 check inter 1000 fall 4 - server dir4 127.0.0.4:80 redir weight 30 check inter 1000 fall 4 - option httpclose - stats uri /stats - stats refresh 5 -