1215
1211
/* if the message is chunked, we skip the chunk size, but use the value as len */
1216
1212
http_find_header2("Transfer-Encoding", 17, msg->sol, &txn->hdr_idx, &ctx);
1217
if ( ctx.idx && strncasecmp(ctx.line+ctx.val,"chunked",ctx.vlen)==0) {
1213
if (ctx.idx && ctx.vlen >= 7 && strncasecmp(ctx.line+ctx.val, "chunked", 7) == 0) {
1218
1214
unsigned int chunk = 0;
1219
while ( params < req->rlim && !HTTP_IS_CRLF(*params)) {
1215
while ( params < (req->data+req->max_len) && !HTTP_IS_CRLF(*params)) {
1220
1216
char c = *params;
1221
1217
if (ishex(c)) {
1222
1218
unsigned int hex = toupper(c) - '0';
1282
* This function tries to find a running server for the proxy <px> following
1283
* the Header parameter hash method. It looks for a specific parameter in the
1284
* URL and hashes it to compute the server ID. This is useful to optimize
1285
* performance by avoiding bounces between servers in contexts where sessions
1286
* are shared but cookies are not usable. If the parameter is not found, NULL
1287
* is returned. If any server is found, it will be returned. If no valid server
1288
* is found, NULL is returned.
1290
struct server *get_server_hh(struct session *s)
1292
unsigned long hash = 0;
1293
struct http_txn *txn = &s->txn;
1294
struct http_msg *msg = &txn->req;
1295
struct proxy *px = s->be;
1296
unsigned int plen = px->hh_len;
1301
/* tot_weight appears to mean srv_count */
1302
if (px->lbprm.tot_weight == 0)
1305
if (px->lbprm.map.state & PR_MAP_RECALC)
1306
recalc_server_map(px);
1310
/* if the message is chunked, we skip the chunk size, but use the value as len */
1311
http_find_header2(px->hh_name, plen, msg->sol, &txn->hdr_idx, &ctx);
1313
/* if the header is not found or empty, let's fallback to round robin */
1314
if (!ctx.idx || !ctx.vlen)
1317
/* Found a the hh_name in the headers.
1318
* we will compute the hash based on this value ctx.val.
1321
p = (char *)ctx.line + ctx.val;
1322
if (!px->hh_match_domain) {
1324
hash = *p + (hash << 6) + (hash << 16) - hash;
1331
/* special computation, use only main domain name, not tld/host
1332
* going back from the end of string, start hashing at first
1334
* This is designed to work with the 'Host' header, and requires
1335
* a special option to activate this.
1345
hash = *p + (hash << 6) + (hash << 16) - hash;
1351
return px->lbprm.map.srv[hash % px->lbprm.tot_weight];
1286
1356
* This function applies the load-balancing algorithm to the session, as
1287
1357
* defined by the backend it is assigned to. The session is then marked as
1831
1927
s->be->lbprm.server_take_conn(s->srv);
1834
if (!tv_add_ifset(&s->req->cex, &now, &s->be->timeout.connect))
1835
tv_eternity(&s->req->cex);
1930
s->req->cons->exp = tick_add_ifset(now_ms, s->be->timeout.connect);
1836
1931
return SN_ERR_NONE; /* connection is OK */
1841
* This function checks the retry count during the connect() job.
1842
* It updates the session's srv_state and retries, so that the caller knows
1843
* what it has to do. It uses the last connection error to set the log when
1844
* it expires. It returns 1 when it has expired, and 0 otherwise.
1846
int srv_count_retry_down(struct session *t, int conn_err)
1848
/* we are in front of a retryable error */
1851
if (t->conn_retries < 0) {
1852
/* if not retryable anymore, let's abort */
1853
tv_eternity(&t->req->cex);
1854
srv_close_with_err(t, conn_err, SN_FINST_C,
1855
503, error_message(t, HTTP_ERR_503));
1857
t->srv->failed_conns++;
1858
t->be->failed_conns++;
1860
/* We used to have a free connection slot. Since we'll never use it,
1861
* we have to inform the server that it may be used by another session.
1863
if (may_dequeue_tasks(t->srv, t->be))
1864
process_srv_queue(t->srv);
1872
* This function performs the retryable part of the connect() job.
1873
* It updates the session's srv_state and retries, so that the caller knows
1874
* what it has to do. It returns 1 when it breaks out of the loop, or 0 if
1875
* it needs to redispatch.
1877
int srv_retryable_connect(struct session *t)
1881
/* This loop ensures that we stop before the last retry in case of a
1882
* redispatchable server.
1885
/* initiate a connection to the server */
1886
conn_err = connect_server(t);
1890
//fprintf(stderr,"0: c=%d, s=%d\n", c, s);
1891
t->srv_state = SV_STCONN;
1896
case SN_ERR_INTERNAL:
1897
tv_eternity(&t->req->cex);
1898
srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
1899
500, error_message(t, HTTP_ERR_500));
1903
t->srv->failed_conns++;
1904
t->be->failed_conns++;
1905
/* release other sessions waiting for this server */
1906
if (may_dequeue_tasks(t->srv, t->be))
1907
process_srv_queue(t->srv);
1910
/* ensure that we have enough retries left */
1911
if (srv_count_retry_down(t, conn_err)) {
1914
} while (t->srv == NULL || t->conn_retries > 0 || !(t->be->options & PR_O_REDISP));
1916
/* We're on our last chance, and the REDISP option was specified.
1917
* We will ignore cookie and force to balance or use the dispatcher.
1919
/* let's try to offer this slot to anybody */
1920
if (may_dequeue_tasks(t->srv, t->be))
1921
process_srv_queue(t->srv);
1924
t->srv->cum_sess++; //FIXME?
1926
/* it's left to the dispatcher to choose a server */
1927
t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
1928
t->prev_srv = t->srv;
1933
1935
/* This function performs the "redispatch" part of a connection attempt. It
1934
1936
* will assign a server if required, queue the connection if required, and
1935
1937
* handle errors that might arise at this level. It can change the server
1976
1979
case SRV_STATUS_NOSRV:
1977
1980
/* note: it is guaranteed that t->srv == NULL here */
1978
tv_eternity(&t->req->cex);
1979
srv_close_with_err(t, SN_ERR_SRVTO, SN_FINST_C,
1980
503, error_message(t, HTTP_ERR_503));
1981
if (!t->req->cons->err_type) {
1982
t->req->cons->err_type = SI_ET_CONN_ERR;
1983
t->req->cons->err_loc = NULL;
1982
1986
t->be->failed_conns++;
1985
1989
case SRV_STATUS_QUEUED:
1986
if (!tv_add_ifset(&t->req->cex, &now, &t->be->timeout.queue))
1987
tv_eternity(&t->req->cex);
1988
t->srv_state = SV_STIDLE;
1990
t->req->cons->exp = tick_add_ifset(now_ms, t->be->timeout.queue);
1991
t->req->cons->state = SI_ST_QUE;
1989
1992
/* do nothing else and do not wake any other session up */
1992
1995
case SRV_STATUS_INTERNAL:
1994
tv_eternity(&t->req->cex);
1995
srv_close_with_err(t, SN_ERR_INTERNAL, SN_FINST_C,
1996
500, error_message(t, HTTP_ERR_500));
1997
if (!t->req->cons->err_type) {
1998
t->req->cons->err_type = SI_ET_CONN_OTHER;
1999
t->req->cons->err_loc = t->srv;
2003
srv_inc_sess_ctr(t->srv);
2000
2005
t->srv->failed_conns++;
2001
2006
t->be->failed_conns++;
2047
2052
curproxy->lbprm.algo |= BE_LB_ALGO_SH;
2049
2054
else if (!strcmp(args[0], "uri")) {
2050
2057
curproxy->lbprm.algo &= ~BE_LB_ALGO;
2051
2058
curproxy->lbprm.algo |= BE_LB_ALGO_UH;
2060
while (*args[arg]) {
2061
if (!strcmp(args[arg], "len")) {
2062
if (!*args[arg+1] || (atoi(args[arg+1]) <= 0)) {
2063
snprintf(err, errlen, "'balance uri len' expects a positive integer (got '%s').", args[arg+1]);
2066
curproxy->uri_len_limit = atoi(args[arg+1]);
2069
else if (!strcmp(args[arg], "depth")) {
2070
if (!*args[arg+1] || (atoi(args[arg+1]) <= 0)) {
2071
snprintf(err, errlen, "'balance uri depth' expects a positive integer (got '%s').", args[arg+1]);
2074
/* hint: we store the position of the ending '/' (depth+1) so
2075
* that we avoid a comparison while computing the hash.
2077
curproxy->uri_dirs_depth1 = atoi(args[arg+1]) + 1;
2081
snprintf(err, errlen, "'balance uri' only accepts parameters 'len' and 'depth' (got '%s').", args[arg]);
2053
2086
else if (!strcmp(args[0], "url_param")) {
2054
2087
if (!*args[1]) {
2058
2091
curproxy->lbprm.algo &= ~BE_LB_ALGO;
2059
2092
curproxy->lbprm.algo |= BE_LB_ALGO_PH;
2060
if (curproxy->url_param_name)
2061
free(curproxy->url_param_name);
2094
free(curproxy->url_param_name);
2062
2095
curproxy->url_param_name = strdup(args[1]);
2063
curproxy->url_param_len = strlen(args[1]);
2096
curproxy->url_param_len = strlen(args[1]);
2065
2098
if (strcmp(args[2], "check_post")) {
2066
2099
snprintf(err, errlen, "'balance url_param' only accepts check_post modifier.");
2077
2110
curproxy->url_param_post_limit = 3; /* minimum example: S=3 or \r\nS=6& */
2113
else if (!strncmp(args[0], "hdr(", 4)) {
2114
const char *beg, *end;
2117
end = strchr(beg, ')');
2119
if (!end || end == beg) {
2120
snprintf(err, errlen, "'balance hdr(name)' requires an http header field name.");
2124
curproxy->lbprm.algo &= ~BE_LB_ALGO;
2125
curproxy->lbprm.algo |= BE_LB_ALGO_HH;
2127
free(curproxy->hh_name);
2128
curproxy->hh_len = end - beg;
2129
curproxy->hh_name = my_strndup(beg, end - beg);
2130
curproxy->hh_match_domain = 0;
2133
if (strcmp(args[1], "use_domain_only")) {
2134
snprintf(err, errlen, "'balance hdr(name)' only accepts 'use_domain_only' modifier.");
2137
curproxy->hh_match_domain = 1;
2081
snprintf(err, errlen, "'balance' only supports 'roundrobin', 'leastconn', 'source', 'uri' and 'url_param' options.");
2142
snprintf(err, errlen, "'balance' only supports 'roundrobin', 'leastconn', 'source', 'uri', 'url_param' and 'hdr(name)' options.");
2178
/* set test->i to the number of enabled servers on the proxy */
2180
acl_fetch_connslots(struct proxy *px, struct session *l4, void *l7, int dir,
2181
struct acl_expr *expr, struct acl_test *test)
2183
struct server *iterator;
2184
test->flags = ACL_TEST_F_VOL_TEST;
2185
if (expr->arg_len) {
2186
/* another proxy was designated, we must look for it */
2187
for (px = proxy; px; px = px->next)
2188
if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
2197
if ((iterator->state & 1) == 0) {
2198
iterator = iterator->next;
2201
if (iterator->maxconn == 0 || iterator->maxqueue == 0) {
2206
test->i += (iterator->maxconn - iterator->cur_sess)
2207
+ (iterator->maxqueue - iterator->nbpend);
2208
iterator = iterator->next;
2214
/* set test->i to the number of connections per second reaching the frontend */
2216
acl_fetch_fe_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
2217
struct acl_expr *expr, struct acl_test *test)
2219
test->flags = ACL_TEST_F_VOL_TEST;
2220
if (expr->arg_len) {
2221
/* another proxy was designated, we must look for it */
2222
for (px = proxy; px; px = px->next)
2223
if ((px->cap & PR_CAP_FE) && !strcmp(px->id, expr->arg.str))
2229
test->i = read_freq_ctr(&px->fe_sess_per_sec);
2233
/* set test->i to the number of connections per second reaching the backend */
2235
acl_fetch_be_sess_rate(struct proxy *px, struct session *l4, void *l7, int dir,
2236
struct acl_expr *expr, struct acl_test *test)
2238
test->flags = ACL_TEST_F_VOL_TEST;
2239
if (expr->arg_len) {
2240
/* another proxy was designated, we must look for it */
2241
for (px = proxy; px; px = px->next)
2242
if ((px->cap & PR_CAP_BE) && !strcmp(px->id, expr->arg.str))
2248
test->i = read_freq_ctr(&px->be_sess_per_sec);
2118
2253
/* Note: must not be declared <const> as its list will be overwritten */
2119
2254
static struct acl_kw_list acl_kws = {{ },{
2120
{ "nbsrv", acl_parse_int, acl_fetch_nbsrv, acl_match_int },
2255
{ "nbsrv", acl_parse_int, acl_fetch_nbsrv, acl_match_int, ACL_USE_NOTHING },
2256
{ "connslots", acl_parse_int, acl_fetch_connslots, acl_match_int, ACL_USE_NOTHING },
2257
{ "fe_sess_rate", acl_parse_int, acl_fetch_fe_sess_rate, acl_match_int, ACL_USE_NOTHING },
2258
{ "be_sess_rate", acl_parse_int, acl_fetch_be_sess_rate, acl_match_int, ACL_USE_NOTHING },
2121
2259
{ NULL, NULL, NULL, NULL },