~ubuntu-branches/ubuntu/intrepid/haproxy/intrepid

« back to all changes in this revision

Viewing changes to src/proto_http.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Cornet
  • Date: 2008-03-09 21:30:29 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080309213029-8oupnrc607mg5uqw
Tags: 1.3.14.3-1
* New Upstream Version
* Add status argument support to init-script to conform to LSB.
* Cleanup pidfile after stop in init script. Init script return code fixups.

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
#include <proto/acl.h>
47
47
#include <proto/backend.h>
48
48
#include <proto/buffers.h>
 
49
#include <proto/dumpstats.h>
49
50
#include <proto/fd.h>
50
51
#include <proto/log.h>
51
52
#include <proto/hdr_idx.h>
52
53
#include <proto/proto_http.h>
53
54
#include <proto/queue.h>
 
55
#include <proto/senddata.h>
54
56
#include <proto/session.h>
55
57
#include <proto/task.h>
56
58
 
533
535
        return http_find_header2(name, strlen(name), sol, idx, ctx);
534
536
}
535
537
 
536
 
/*
537
 
 * returns a message to the client ; the connection is shut down for read,
538
 
 * and the request is cleared so that no server connection can be initiated.
539
 
 * The client must be in a valid state for this (HEADER, DATA ...).
540
 
 * Nothing is performed on the server side. The message is contained in a
541
 
 * "chunk". If it is null, then an empty message is used.
542
 
 * The reply buffer doesn't need to be empty before this.
543
 
 */
544
 
void client_retnclose(struct session *s, const struct chunk *msg)
545
 
{
546
 
        EV_FD_CLR(s->cli_fd, DIR_RD);
547
 
        EV_FD_SET(s->cli_fd, DIR_WR);
548
 
        buffer_shutr(s->req);
549
 
        if (!tv_add_ifset(&s->rep->wex, &now, &s->fe->clitimeout))
550
 
                tv_eternity(&s->rep->wex);
551
 
        s->cli_state = CL_STSHUTR;
552
 
        buffer_flush(s->rep);
553
 
        if (msg->len)
554
 
                buffer_write(s->rep, msg->str, msg->len);
555
 
        s->req->l = 0;
556
 
}
557
 
 
558
 
 
559
 
/*
560
 
 * returns a message into the rep buffer, and flushes the req buffer.
561
 
 * The reply buffer doesn't need to be empty before this. The message
562
 
 * is contained in a "chunk". If it is null, then an empty message is
563
 
 * used.
564
 
 */
565
 
void client_return(struct session *s, const struct chunk *msg)
566
 
{
567
 
        buffer_flush(s->rep);
568
 
        if (msg->len)
569
 
                buffer_write(s->rep, msg->str, msg->len);
570
 
        s->req->l = 0;
571
 
}
572
 
 
573
 
 
574
538
/* This function turns the server state into the SV_STCLOSE, and sets
575
539
 * indicators accordingly. Note that if <status> is 0, or if the message
576
540
 * pointer is NULL, then no message is returned.
649
613
        } while (fsm_resync);
650
614
 
651
615
        if (likely(s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE)) {
 
616
 
 
617
                if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
 
618
                        session_process_counters(s);
 
619
 
652
620
                s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
653
621
                s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
654
622
 
655
 
                t->expire = s->req->rex;
656
623
                tv_min(&t->expire, &s->req->rex, &s->req->wex);
657
624
                tv_bound(&t->expire, &s->req->cex);
658
625
                tv_bound(&t->expire, &s->rep->rex);
659
626
                tv_bound(&t->expire, &s->rep->wex);
 
627
                if (s->cli_state == CL_STHEADERS)
 
628
                        tv_bound(&t->expire, &s->txn.exp);
660
629
 
661
630
                /* restore t to its place in the task list */
662
631
                task_queue(t);
665
634
                /* DEBUG code : this should never ever happen, otherwise it indicates
666
635
                 * that a task still has something to do and will provoke a quick loop.
667
636
                 */
668
 
                if (tv_remain2(&now, &t->expire) <= 0)
 
637
                if (tv_ms_remain2(&now, &t->expire) <= 0)
669
638
                        exit(100);
670
639
#endif
671
640
                *next = t->expire;
687
656
        }
688
657
 
689
658
        s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
690
 
        if (s->req != NULL)
691
 
                s->logs.bytes_in = s->req->total;
692
 
        if (s->rep != NULL)
693
 
                s->logs.bytes_out = s->rep->total;
694
 
 
695
 
        s->fe->bytes_in  += s->logs.bytes_in;
696
 
        s->fe->bytes_out += s->logs.bytes_out;
697
 
        if (s->be != s->fe) {
698
 
                s->be->bytes_in  += s->logs.bytes_in;
699
 
                s->be->bytes_out += s->logs.bytes_out;
700
 
        }
701
 
        if (s->srv) {
702
 
                s->srv->bytes_in  += s->logs.bytes_in;
703
 
                s->srv->bytes_out += s->logs.bytes_out;
704
 
        }
 
659
        session_process_counters(s);
705
660
 
706
661
        /* let's do a final log if we need it */
707
662
        if (s->logs.logwait && 
745
700
        int tolog;
746
701
        char *uri, *h;
747
702
        char *svid;
748
 
        struct tm *tm;
 
703
        struct tm tm;
749
704
        static char tmpline[MAX_SYSLOG_LEN];
750
705
        int hdr;
751
706
 
762
717
                          (const void *)&((struct sockaddr_in6 *)(&s->cli_addr))->sin6_addr,
763
718
                          pn, sizeof(pn));
764
719
 
765
 
        tm = localtime((time_t *)&s->logs.tv_accept.tv_sec);
766
 
 
 
720
        get_localtime(s->logs.tv_accept.tv_sec, &tm);
767
721
 
768
722
        /* FIXME: let's limit ourselves to frontend logging for now. */
769
723
        tolog = fe->to_log;
821
775
                 (s->cli_addr.ss_family == AF_INET) ?
822
776
                 ntohs(((struct sockaddr_in *)&s->cli_addr)->sin_port) :
823
777
                 ntohs(((struct sockaddr_in6 *)&s->cli_addr)->sin6_port),
824
 
                 tm->tm_mday, monthname[tm->tm_mon], tm->tm_year+1900,
825
 
                 tm->tm_hour, tm->tm_min, tm->tm_sec, s->logs.tv_accept.tv_usec/1000,
 
778
                 tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900,
 
779
                 tm.tm_hour, tm.tm_min, tm.tm_sec, s->logs.tv_accept.tv_usec/1000,
826
780
                 fe->id, be->id, svid,
827
781
                 s->logs.t_request,
828
782
                 (s->logs.t_queue >= 0) ? s->logs.t_queue - s->logs.t_request : -1,
830
784
                 (s->logs.t_data >= 0) ? s->logs.t_data - s->logs.t_connect : -1,
831
785
                 (tolog & LW_BYTES) ? "" : "+", s->logs.t_close,
832
786
                 txn->status,
833
 
                 (tolog & LW_BYTES) ? "" : "+", s->logs.bytes_in,
 
787
                 (tolog & LW_BYTES) ? "" : "+", s->logs.bytes_out,
834
788
                 txn->cli_cookie ? txn->cli_cookie : "-",
835
789
                 txn->srv_cookie ? txn->srv_cookie : "-",
836
790
                 sess_term_cond[(s->flags & SN_ERR_MASK) >> SN_ERR_SHIFT],
1523
1477
        msg->msg_state = HTTP_MSG_ERROR;
1524
1478
        return;
1525
1479
}
1526
 
    
 
1480
 
1527
1481
/*
1528
1482
 * manages the client FSM and its socket. BTW, it also tries to handle the
1529
1483
 * cookie. It returns 1 if a state has changed (and a resync may be needed),
1632
1586
                        }
1633
1587
 
1634
1588
                        /* 3: has the read timeout expired ? */
1635
 
                        else if (unlikely(tv_isle(&req->rex, &now))) {
 
1589
                        else if (unlikely(tv_isle(&req->rex, &now) ||
 
1590
                                          tv_isle(&txn->exp, &now))) {
1636
1591
                                /* read timeout : give up with an error message. */
1637
1592
                                txn->status = 408;
1638
1593
                                client_retnclose(t, error_message(t, HTTP_ERR_408));
1650
1605
                                 * full. We cannot loop here since stream_sock_read will disable it only if
1651
1606
                                 * req->l == rlim-data
1652
1607
                                 */
1653
 
                                if (!tv_add_ifset(&req->rex, &now, &t->fe->clitimeout))
 
1608
                                if (!tv_add_ifset(&req->rex, &now, &t->fe->timeout.client))
1654
1609
                                        tv_eternity(&req->rex);
1655
1610
                        }
1656
1611
                        return t->cli_state != CL_STHEADERS;
1684
1639
                        /*
1685
1640
                         * We have found the monitor URI
1686
1641
                         */
 
1642
                        struct acl_cond *cond;
 
1643
                        cur_proxy = t->fe;
 
1644
 
1687
1645
                        t->flags |= SN_MONITOR;
 
1646
 
 
1647
                        /* Check if we want to fail this monitor request or not */
 
1648
                        list_for_each_entry(cond, &cur_proxy->mon_fail_cond, list) {
 
1649
                                int ret = acl_exec_cond(cond, cur_proxy, t, txn, ACL_DIR_REQ);
 
1650
                                if (cond->pol == ACL_COND_UNLESS)
 
1651
                                        ret = !ret;
 
1652
 
 
1653
                                if (ret) {
 
1654
                                        /* we fail this request, let's return 503 service unavail */
 
1655
                                        txn->status = 503;
 
1656
                                        client_retnclose(t, error_message(t, HTTP_ERR_503));
 
1657
                                        goto return_prx_cond;
 
1658
                                }
 
1659
                        }
 
1660
 
 
1661
                        /* nothing to fail, let's reply normaly */
1688
1662
                        txn->status = 200;
1689
1663
                        client_retnclose(t, &http_200_chunk);
1690
1664
                        goto return_prx_cond;
1823
1797
                        }
1824
1798
 
1825
1799
                        /* We might have to check for "Connection:" */
1826
 
                        if (((t->fe->options | t->be->options) & PR_O_HTTP_CLOSE) &&
 
1800
                        if (((t->fe->options | t->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO)) &&
1827
1801
                            !(t->flags & SN_CONN_CLOSED)) {
1828
1802
                                char *cur_ptr, *cur_end, *cur_next;
1829
1803
                                int cur_idx, old_idx, delta, val;
1905
1879
                                                if (t->be->beconn > t->be->beconn_max)
1906
1880
                                                        t->be->beconn_max = t->be->beconn;
1907
1881
                                                t->be->cum_beconn++;
 
1882
 
 
1883
                                                /* assign new parameters to the session from the new backend */
 
1884
                                                t->rep->rto = t->req->wto = t->be->timeout.server;
 
1885
                                                t->req->cto = t->be->timeout.connect;
 
1886
                                                t->conn_retries = t->be->conn_retries;
1908
1887
                                                t->flags |= SN_BE_ASSIGNED;
1909
1888
                                                break;
1910
1889
                                        }
1921
1900
                                if (t->be->beconn > t->be->beconn_max)
1922
1901
                                        t->be->beconn_max = t->be->beconn;
1923
1902
                                t->be->cum_beconn++;
 
1903
 
 
1904
                                /* assign new parameters to the session from the new backend */
 
1905
                                t->rep->rto = t->req->wto = t->be->timeout.server;
 
1906
                                t->req->cto = t->be->timeout.connect;
 
1907
                                t->conn_retries = t->be->conn_retries;
1924
1908
                                t->flags |= SN_BE_ASSIGNED;
1925
1909
                        }
1926
1910
                } while (t->be != cur_proxy);  /* we loop only if t->be has changed */
1945
1929
                 * may have separate values for ->fe, ->be.
1946
1930
                 */
1947
1931
 
1948
 
 
1949
 
 
 
1932
                /*
 
1933
                 * If HTTP PROXY is set we simply get remote server address
 
1934
                 * parsing incoming request.
 
1935
                 */
 
1936
                if ((t->be->options & PR_O_HTTP_PROXY) && !(t->flags & SN_ADDR_SET)) {
 
1937
                        url2sa(req->data + msg->sl.rq.u, msg->sl.rq.u_l, &t->srv_addr);
 
1938
                }
1950
1939
 
1951
1940
                /*
1952
1941
                 * 7: the appsession cookie was looked up very early in 1.2,
1965
1954
                 * the fields will stay coherent and the URI will not move.
1966
1955
                 * This should only be performed in the backend.
1967
1956
                 */
1968
 
                if (!(txn->flags & (TX_CLDENY|TX_CLTARPIT)))
 
1957
                if ((t->be->cookie_name || t->be->appsession_name || t->be->capture_name)
 
1958
                    && !(txn->flags & (TX_CLDENY|TX_CLTARPIT)))
1969
1959
                        manage_client_side_cookies(t, req);
1970
1960
 
1971
1961
 
2017
2007
                 * Note that we do not need to add it in case of HTTP/1.0.
2018
2008
                 */
2019
2009
                if (!(t->flags & SN_CONN_CLOSED) &&
2020
 
                    ((t->fe->options | t->be->options) & PR_O_HTTP_CLOSE)) {
 
2010
                    ((t->fe->options | t->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO))) {
2021
2011
                        if ((unlikely(msg->sl.rq.v_l != 8) ||
2022
2012
                             unlikely(req->data[msg->som + msg->sl.rq.v + 7] != '0')) &&
2023
2013
                            unlikely(http_header_add_tail2(req, &txn->req, &txn->hdr_idx,
2036
2026
 
2037
2027
                t->logs.t_request = tv_ms_elapsed(&t->logs.tv_accept, &now);
2038
2028
 
2039
 
                if (!tv_isset(&t->fe->clitimeout) ||
2040
 
                    (t->srv_state < SV_STDATA && tv_isset(&t->be->srvtimeout))) {
 
2029
                if (!tv_isset(&t->fe->timeout.client) ||
 
2030
                    (t->srv_state < SV_STDATA && tv_isset(&t->be->timeout.server))) {
2041
2031
                        /* If the client has no timeout, or if the server is not ready yet,
2042
2032
                         * and we know for sure that it can expire, then it's cleaner to
2043
2033
                         * disable the timeout on the client side so that too low values
2050
2040
                        tv_eternity(&req->rex);
2051
2041
                }
2052
2042
 
2053
 
                /* When a connection is tarpitted, we use the queue timeout for the
2054
 
                 * tarpit delay, which currently happens to be the server's connect
2055
 
                 * timeout. If unset, then set it to zero because we really want it
2056
 
                 * to expire at one moment.
 
2043
                /* When a connection is tarpitted, we use the tarpit timeout,
 
2044
                 * which may be the same as the connect timeout if unspecified.
 
2045
                 * If unset, then set it to zero because we really want it to
 
2046
                 * eventually expire.
2057
2047
                 */
2058
2048
                if (txn->flags & TX_CLTARPIT) {
2059
2049
                        t->req->l = 0;
2060
2050
                        /* flush the request so that we can drop the connection early
2061
2051
                         * if the client closes first.
2062
2052
                         */
2063
 
                        if (!tv_add_ifset(&req->cex, &now, &t->be->contimeout))
 
2053
                        if (!tv_add_ifset(&req->cex, &now, &t->be->timeout.tarpit))
2064
2054
                                req->cex = now;
2065
2055
                }
2066
2056
 
2120
2110
                        /* We must ensure that the read part is still alive when switching
2121
2111
                         * to shutw */
2122
2112
                        EV_FD_SET(t->cli_fd, DIR_RD);
2123
 
                        tv_add_ifset(&req->rex, &now, &t->fe->clitimeout);
 
2113
                        tv_add_ifset(&req->rex, &now, &t->fe->timeout.client);
2124
2114
                        t->cli_state = CL_STSHUTW;
2125
2115
                        //fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
2126
2116
                        return 1;
2150
2140
                        /* We must ensure that the read part is still alive when switching
2151
2141
                         * to shutw */
2152
2142
                        EV_FD_SET(t->cli_fd, DIR_RD);
2153
 
                        tv_add_ifset(&req->rex, &now, &t->fe->clitimeout);
 
2143
                        tv_add_ifset(&req->rex, &now, &t->fe->timeout.client);
2154
2144
 
2155
2145
                        t->cli_state = CL_STSHUTW;
2156
2146
                        if (!(t->flags & SN_ERR_MASK))
2175
2165
                } else {
2176
2166
                        /* there's still some space in the buffer */
2177
2167
                        if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
2178
 
                                if (!tv_isset(&t->fe->clitimeout) ||
2179
 
                                    (t->srv_state < SV_STDATA && tv_isset(&t->be->srvtimeout)))
 
2168
                                if (!tv_isset(&t->fe->timeout.client) ||
 
2169
                                    (t->srv_state < SV_STDATA && tv_isset(&t->be->timeout.server)))
2180
2170
                                        /* If the client has no timeout, or if the server not ready yet, and we
2181
2171
                                         * know for sure that it can expire, then it's cleaner to disable the
2182
2172
                                         * timeout on the client side so that too low values cannot make the
2184
2174
                                         */
2185
2175
                                        tv_eternity(&req->rex);
2186
2176
                                else
2187
 
                                        tv_add(&req->rex, &now, &t->fe->clitimeout);
 
2177
                                        tv_add(&req->rex, &now, &t->fe->timeout.client);
2188
2178
                        }
2189
2179
                }
2190
2180
 
2198
2188
                        /* buffer not empty */
2199
2189
                        if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
2200
2190
                                /* restart writing */
2201
 
                                if (tv_add_ifset(&rep->wex, &now, &t->fe->clitimeout)) {
 
2191
                                if (tv_add_ifset(&rep->wex, &now, &t->fe->timeout.client)) {
2202
2192
                                        /* FIXME: to prevent the client from expiring read timeouts during writes,
2203
2193
                                         * we refresh it. */
2204
2194
                                        req->rex = rep->wex;
2270
2260
                        /* buffer not empty */
2271
2261
                        if (EV_FD_COND_S(t->cli_fd, DIR_WR)) {
2272
2262
                                /* restart writing */
2273
 
                                if (!tv_add_ifset(&rep->wex, &now, &t->fe->clitimeout))
 
2263
                                if (!tv_add_ifset(&rep->wex, &now, &t->fe->timeout.client))
2274
2264
                                        tv_eternity(&rep->wex);
2275
2265
                        }
2276
2266
                }
2330
2320
                } else {
2331
2321
                        /* there's still some space in the buffer */
2332
2322
                        if (EV_FD_COND_S(t->cli_fd, DIR_RD)) {
2333
 
                                if (!tv_add_ifset(&req->rex, &now, &t->fe->clitimeout))
 
2323
                                if (!tv_add_ifset(&req->rex, &now, &t->fe->timeout.client))
2334
2324
                                        tv_eternity(&req->rex);
2335
2325
                                //fprintf(stderr,"%p:%s(%d), c=%d, s=%d\n", t, __FUNCTION__, __LINE__, t->cli_state, t->cli_state);
2336
2326
                        }
2369
2359
#if 0
2370
2360
        fprintf(stderr,"%s:%d  fe->clito=%d.%d, fe->conto=%d.%d, fe->srvto=%d.%d\n",
2371
2361
                __FUNCTION__, __LINE__,
2372
 
                t->fe->clitimeout.tv_sec, t->fe->clitimeout.tv_usec, 
2373
 
                t->fe->contimeout.tv_sec, t->fe->contimeout.tv_usec, 
2374
 
                t->fe->srvtimeout.tv_sec, t->fe->srvtimeout.tv_usec);
 
2362
                t->fe->timeout.client.tv_sec, t->fe->timeout.client.tv_usec, 
 
2363
                t->fe->timeout.connect.tv_sec, t->fe->timeout.connect.tv_usec, 
 
2364
                t->fe->timeout.server.tv_sec, t->fe->timeout.server.tv_usec);
2375
2365
        fprintf(stderr,"%s:%d  be->clito=%d.%d, be->conto=%d.%d, be->srvto=%d.%d\n",
2376
2366
                __FUNCTION__, __LINE__,
2377
 
                t->be->clitimeout.tv_sec, t->be->clitimeout.tv_usec, 
2378
 
                t->be->contimeout.tv_sec, t->be->contimeout.tv_usec, 
2379
 
                t->be->srvtimeout.tv_sec, t->be->srvtimeout.tv_usec);
 
2367
                t->be->timeout.client.tv_sec, t->be->timeout.client.tv_usec, 
 
2368
                t->be->timeout.connect.tv_sec, t->be->timeout.connect.tv_usec, 
 
2369
                t->be->timeout.server.tv_sec, t->be->timeout.server.tv_usec);
2380
2370
 
2381
2371
        fprintf(stderr,"%s:%d  req->cto=%d.%d, req->rto=%d.%d, req->wto=%d.%d\n",
2382
2372
                __FUNCTION__, __LINE__,
2452
2442
                                                           503, error_message(t, HTTP_ERR_503));
2453
2443
                                        if (t->srv)
2454
2444
                                                t->srv->failed_conns++;
2455
 
                                        t->fe->failed_conns++;
 
2445
                                        t->be->failed_conns++;
2456
2446
                                        return 1;
2457
2447
                                }
2458
2448
                        }
2519
2509
 
2520
2510
                                if (t->srv)
2521
2511
                                        t->srv->failed_conns++;
2522
 
                                t->be->failed_conns++;
 
2512
                                t->be->redispatches++;
2523
2513
 
2524
2514
                                t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
2525
2515
                                t->srv = NULL; /* it's left to the dispatcher to choose a server */
2527
2517
 
2528
2518
                                /* first, get a connection */
2529
2519
                                if (srv_redispatch_connect(t))
2530
 
                                        return t->srv_state != SV_STIDLE;
 
2520
                                        return t->srv_state != SV_STCONN;
 
2521
                        } else {
 
2522
                                if (t->srv)
 
2523
                                        t->srv->retries++;
 
2524
                                t->be->retries++;
2531
2525
                        }
2532
2526
 
2533
2527
                        do {
2555
2549
                                tv_eternity(&req->wex);
2556
2550
                        } else  /* need the right to write */ {
2557
2551
                                EV_FD_SET(t->srv_fd, DIR_WR);
2558
 
                                if (tv_add_ifset(&req->wex, &now, &t->be->srvtimeout)) {
 
2552
                                if (tv_add_ifset(&req->wex, &now, &t->be->timeout.server)) {
2559
2553
                                        /* FIXME: to prevent the server from expiring read timeouts during writes,
2560
2554
                                         * we refresh it. */
2561
2555
                                        rep->rex = req->wex;
2566
2560
 
2567
2561
                        if (t->be->mode == PR_MODE_TCP) { /* let's allow immediate data connection in this case */
2568
2562
                                EV_FD_SET(t->srv_fd, DIR_RD);
2569
 
                                if (!tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout))
 
2563
                                if (!tv_add_ifset(&rep->rex, &now, &t->be->timeout.server))
2570
2564
                                        tv_eternity(&rep->rex);
2571
2565
                
2572
2566
                                t->srv_state = SV_STDATA;
2573
 
                                if (t->srv)
2574
 
                                        t->srv->cum_sess++;
2575
2567
                                rep->rlim = rep->data + BUFSIZE; /* no rewrite needed */
2576
2568
 
2577
2569
                                /* if the user wants to log as soon as possible, without counting
2589
2581
                        }
2590
2582
                        else {
2591
2583
                                t->srv_state = SV_STHEADERS;
2592
 
                                if (t->srv)
2593
 
                                        t->srv->cum_sess++;
2594
2584
                                rep->rlim = rep->data + BUFSIZE - MAXREWRITE; /* rewrite needed */
2595
2585
                                t->txn.rsp.msg_state = HTTP_MSG_RPBEFORE;
2596
2586
                                /* reset hdr_idx which was already initialized by the request.
2653
2643
                         * full. We cannot loop here since stream_sock_read will disable it only if
2654
2644
                         * rep->l == rlim-data
2655
2645
                         */
2656
 
                        if (!tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout))
 
2646
                        if (!tv_add_ifset(&rep->rex, &now, &t->be->timeout.server))
2657
2647
                                tv_eternity(&rep->rex);
2658
2648
                }
2659
2649
 
2758
2748
                                /* We must ensure that the read part is still
2759
2749
                                 * alive when switching to shutw */
2760
2750
                                EV_FD_SET(t->srv_fd, DIR_RD);
2761
 
                                tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout);
 
2751
                                tv_add_ifset(&rep->rex, &now, &t->be->timeout.server);
2762
2752
 
2763
2753
                                shutdown(t->srv_fd, SHUT_WR);
2764
2754
                                t->srv_state = SV_STSHUTW;
2778
2768
                                /* We must ensure that the read part is still alive
2779
2769
                                 * when switching to shutw */
2780
2770
                                EV_FD_SET(t->srv_fd, DIR_RD);
2781
 
                                tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout);
 
2771
                                tv_add_ifset(&rep->rex, &now, &t->be->timeout.server);
2782
2772
 
2783
2773
                                t->srv_state = SV_STSHUTW;
2784
2774
                                if (!(t->flags & SN_ERR_MASK))
2799
2789
                        else if (likely(req->l)) {
2800
2790
                                if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
2801
2791
                                        /* restart writing */
2802
 
                                        if (tv_add_ifset(&req->wex, &now, &t->be->srvtimeout)) {
 
2792
                                        if (tv_add_ifset(&req->wex, &now, &t->be->timeout.server)) {
2803
2793
                                                /* FIXME: to prevent the server from expiring read timeouts during writes,
2804
2794
                                                 * we refresh it. */
2805
2795
                                                rep->rex = req->wex;
2856
2846
                         *    Cache-Control or Expires header fields."
2857
2847
                         */
2858
2848
                        if (likely(txn->meth != HTTP_METH_POST) &&
2859
 
                            unlikely(t->be->options & PR_O_CHK_CACHE))
 
2849
                            (t->be->options & (PR_O_CHK_CACHE|PR_O_COOK_NOC)))
2860
2850
                                txn->flags |= TX_CACHEABLE | TX_CACHE_COOK;
2861
2851
                        break;
2862
2852
                default:
2926
2916
                        }
2927
2917
 
2928
2918
                        /* We might have to check for "Connection:" */
2929
 
                        if (((t->fe->options | t->be->options) & PR_O_HTTP_CLOSE) &&
 
2919
                        if (((t->fe->options | t->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO)) &&
2930
2920
                            !(t->flags & SN_CONN_CLOSED)) {
2931
2921
                                char *cur_ptr, *cur_end, *cur_next;
2932
2922
                                int cur_idx, old_idx, delta, val;
2991
2981
                /*
2992
2982
                 * 4: check for server cookie.
2993
2983
                 */
2994
 
                manage_server_side_cookies(t, rep);
2995
 
 
2996
 
                /*
2997
 
                 * 5: add server cookie in the response if needed
 
2984
                if (t->be->cookie_name || t->be->appsession_name || t->be->capture_name
 
2985
                    || (t->be->options & PR_O_CHK_CACHE))
 
2986
                        manage_server_side_cookies(t, rep);
 
2987
 
 
2988
 
 
2989
                /*
 
2990
                 * 5: check for cache-control or pragma headers if required.
 
2991
                 */
 
2992
                if ((t->be->options & (PR_O_COOK_NOC | PR_O_CHK_CACHE)) != 0)
 
2993
                        check_response_for_cacheability(t, rep);
 
2994
 
 
2995
                /*
 
2996
                 * 6: add server cookie in the response if needed
2998
2997
                 */
2999
2998
                if ((t->srv) && !(t->flags & SN_DIRECT) && (t->be->options & PR_O_COOK_INS) &&
3000
2999
                    (!(t->be->options & PR_O_COOK_POST) || (txn->meth == HTTP_METH_POST))) {
3019
3018
                         * Some caches understand the correct form: 'no-cache="set-cookie"', but
3020
3019
                         * others don't (eg: apache <= 1.3.26). So we use 'private' instead.
3021
3020
                         */
3022
 
                        if (t->be->options & PR_O_COOK_NOC) {
 
3021
                        if ((t->be->options & PR_O_COOK_NOC) && (txn->flags & TX_CACHEABLE)) {
 
3022
 
 
3023
                                txn->flags &= ~TX_CACHEABLE & ~TX_CACHE_COOK;
 
3024
 
3023
3025
                                if (unlikely(http_header_add_tail2(rep, &txn->rsp, &txn->hdr_idx,
3024
3026
                                                                   "Cache-control: private", 22)) < 0)
3025
3027
                                        goto return_bad_resp;
3028
3030
 
3029
3031
 
3030
3032
                /*
3031
 
                 * 6: check for cache-control or pragma headers.
3032
 
                 */
3033
 
                check_response_for_cacheability(t, rep);
3034
 
 
3035
 
 
3036
 
                /*
3037
3033
                 * 7: check if result will be cacheable with a cookie.
3038
3034
                 * We'll block the response if security checks have caught
3039
3035
                 * nasty things such as a cacheable cookie.
3065
3061
                 * Note that we do not need to add it in case of HTTP/1.0.
3066
3062
                 */
3067
3063
                if (!(t->flags & SN_CONN_CLOSED) &&
3068
 
                    ((t->fe->options | t->be->options) & PR_O_HTTP_CLOSE)) {
 
3064
                    ((t->fe->options | t->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO))) {
3069
3065
                        if ((unlikely(msg->sl.st.v_l != 8) ||
3070
3066
                             unlikely(req->data[msg->som + 7] != '0')) &&
3071
3067
                            unlikely(http_header_add_tail2(rep, &txn->rsp, &txn->hdr_idx,
3095
3091
                        /* We must ensure that the read part is still alive when switching
3096
3092
                         * to shutw */
3097
3093
                        EV_FD_SET(t->srv_fd, DIR_RD);
3098
 
                        tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout);
 
3094
                        tv_add_ifset(&rep->rex, &now, &t->be->timeout.server);
3099
3095
 
3100
3096
                        shutdown(t->srv_fd, SHUT_WR);
3101
3097
                        t->srv_state = SV_STSHUTW;
3108
3104
                }
3109
3105
#endif
3110
3106
                /* if the user wants to log as soon as possible, without counting
3111
 
                   bytes from the server, then this is the right moment. */
 
3107
                 * bytes from the server, then this is the right moment. We have
 
3108
                 * to temporarily assign bytes_out to log what we currently have.
 
3109
                 */
3112
3110
                if (t->fe->to_log && !(t->logs.logwait & LW_BYTES)) {
3113
3111
                        t->logs.t_close = t->logs.t_data; /* to get a valid end date */
3114
 
                        t->logs.bytes_in = txn->rsp.eoh;
 
3112
                        t->logs.bytes_out = txn->rsp.eoh;
3115
3113
                        if (t->fe->to_log & LW_REQ)
3116
3114
                                http_sess_log(t);
3117
3115
                        else
3118
3116
                                tcp_sess_log(t);
 
3117
                        t->logs.bytes_out = 0;
3119
3118
                }
3120
3119
 
3121
3120
                /* Note: we must not try to cheat by jumping directly to DATA,
3164
3163
                        /* We must ensure that the read part is still alive when switching
3165
3164
                         * to shutw */
3166
3165
                        EV_FD_SET(t->srv_fd, DIR_RD);
3167
 
                        tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout);
 
3166
                        tv_add_ifset(&rep->rex, &now, &t->be->timeout.server);
3168
3167
 
3169
3168
                        t->srv_state = SV_STSHUTW;
3170
3169
                        return 1;
3188
3187
                        /* We must ensure that the read part is still alive when switching
3189
3188
                         * to shutw */
3190
3189
                        EV_FD_SET(t->srv_fd, DIR_RD);
3191
 
                        tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout);
 
3190
                        tv_add_ifset(&rep->rex, &now, &t->be->timeout.server);
3192
3191
                        t->srv_state = SV_STSHUTW;
3193
3192
                        if (!(t->flags & SN_ERR_MASK))
3194
3193
                                t->flags |= SN_ERR_SRVTO;
3207
3206
                else { /* buffer not empty, there are still data to be transferred */
3208
3207
                        if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
3209
3208
                                /* restart writing */
3210
 
                                if (tv_add_ifset(&req->wex, &now, &t->be->srvtimeout)) {
 
3209
                                if (tv_add_ifset(&req->wex, &now, &t->be->timeout.server)) {
3211
3210
                                        /* FIXME: to prevent the server from expiring read timeouts during writes,
3212
3211
                                         * we refresh it. */
3213
3212
                                        rep->rex = req->wex;
3225
3224
                }
3226
3225
                else {
3227
3226
                        if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
3228
 
                                if (!tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout))
 
3227
                                if (!tv_add_ifset(&rep->rex, &now, &t->be->timeout.server))
3229
3228
                                        tv_eternity(&rep->rex);
3230
3229
                        }
3231
3230
                }
3301
3300
                else { /* buffer not empty */
3302
3301
                        if (EV_FD_COND_S(t->srv_fd, DIR_WR)) {
3303
3302
                                /* restart writing */
3304
 
                                if (!tv_add_ifset(&req->wex, &now, &t->be->srvtimeout))
 
3303
                                if (!tv_add_ifset(&req->wex, &now, &t->be->timeout.server))
3305
3304
                                        tv_eternity(&req->wex);
3306
3305
                        }
3307
3306
                }
3374
3373
                }
3375
3374
                else {
3376
3375
                        if (EV_FD_COND_S(t->srv_fd, DIR_RD)) {
3377
 
                                if (!tv_add_ifset(&rep->rex, &now, &t->be->srvtimeout))
 
3376
                                if (!tv_add_ifset(&rep->rex, &now, &t->be->timeout.server))
3378
3377
                                        tv_eternity(&rep->rex);
3379
3378
                        }
3380
3379
                }
3409
3408
        }
3410
3409
        else if (s->data_source == DATA_SRC_STATS) {
3411
3410
                /* dump server statistics */
3412
 
                return produce_content_stats(s);
3413
 
        }
3414
 
        else {
3415
 
                /* unknown data source */
3416
 
                s->txn.status = 500;
3417
 
                client_retnclose(s, error_message(s, HTTP_ERR_500));
3418
 
                if (!(s->flags & SN_ERR_MASK))
3419
 
                        s->flags |= SN_ERR_PRXCOND;
3420
 
                if (!(s->flags & SN_FINST_MASK))
3421
 
                        s->flags |= SN_FINST_R;
3422
 
                s->flags &= ~SN_SELF_GEN;
3423
 
                return 1;
3424
 
        }
3425
 
}
3426
 
 
3427
 
 
3428
 
/*
3429
 
 * Produces statistics data for the session <s>. Expects to be called with
3430
 
 * s->cli_state == CL_STSHUTR. It stops by itself by unsetting the SN_SELF_GEN
3431
 
 * flag from the session, which it uses to keep on being called when there is
3432
 
 * free space in the buffer, of simply by letting an empty buffer upon return.
3433
 
 * It returns 1 if it changes the session state from CL_STSHUTR, otherwise 0.
3434
 
 */
3435
 
int produce_content_stats(struct session *s)
3436
 
{
3437
 
        struct buffer *rep = s->rep;
3438
 
        struct proxy *px;
3439
 
        struct chunk msg;
3440
 
        unsigned int up;
3441
 
 
3442
 
        msg.len = 0;
3443
 
        msg.str = trash;
3444
 
 
3445
 
        switch (s->data_state) {
3446
 
        case DATA_ST_INIT:
3447
 
                /* the function had not been called yet */
3448
 
                s->flags |= SN_SELF_GEN;  // more data will follow
3449
 
 
3450
 
                chunk_printf(&msg, sizeof(trash),
3451
 
                             "HTTP/1.0 200 OK\r\n"
3452
 
                             "Cache-Control: no-cache\r\n"
3453
 
                             "Connection: close\r\n"
3454
 
                             "Content-Type: text/html\r\n"
3455
 
                             "\r\n");
3456
 
 
3457
 
                s->txn.status = 200;
3458
 
                client_retnclose(s, &msg); // send the start of the response.
3459
 
                msg.len = 0;
3460
 
 
3461
 
                if (!(s->flags & SN_ERR_MASK))  // this is not really an error but it is
3462
 
                        s->flags |= SN_ERR_PRXCOND; // to mark that it comes from the proxy
3463
 
                if (!(s->flags & SN_FINST_MASK))
3464
 
                        s->flags |= SN_FINST_R;
3465
 
 
3466
 
                if (s->txn.meth == HTTP_METH_HEAD) {
3467
 
                        /* that's all we return in case of HEAD request */
3468
 
                        s->data_state = DATA_ST_FIN;
3469
 
                        s->flags &= ~SN_SELF_GEN;
3470
 
                        return 1;
3471
 
                }
3472
 
 
3473
 
                s->data_state = DATA_ST_HEAD; /* let's start producing data */
3474
 
                /* fall through */
3475
 
 
3476
 
        case DATA_ST_HEAD:
3477
 
                /* WARNING! This must fit in the first buffer !!! */        
3478
 
                chunk_printf(&msg, sizeof(trash),
3479
 
                             "<html><head><title>Statistics Report for " PRODUCT_NAME "</title>\n"
3480
 
                             "<meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\">\n"
3481
 
                             "<style type=\"text/css\"><!--\n"
3482
 
                             "body {"
3483
 
                             " font-family: helvetica, arial;"
3484
 
                             " font-size: 12px;"
3485
 
                             " font-weight: normal;"
3486
 
                             " color: black;"
3487
 
                             " background: white;"
3488
 
                             "}\n"
3489
 
                             "th,td {"
3490
 
                             " font-size: 0.8em;"
3491
 
                             " align: center;"
3492
 
                             "}\n"
3493
 
                             "h1 {"
3494
 
                             " font-size: xx-large;"
3495
 
                             " margin-bottom: 0.5em;"
3496
 
                             "}\n"
3497
 
                             "h2 {"
3498
 
                             " font-family: helvetica, arial;"
3499
 
                             " font-size: x-large;"
3500
 
                             " font-weight: bold;"
3501
 
                             " font-style: italic;"
3502
 
                             " color: #6020a0;"
3503
 
                             " margin-top: 0em;"
3504
 
                             " margin-bottom: 0em;"
3505
 
                             "}\n"
3506
 
                             "h3 {"
3507
 
                             " font-family: helvetica, arial;"
3508
 
                             " font-size: 16px;"
3509
 
                             " font-weight: bold;"
3510
 
                             " color: #b00040;"
3511
 
                             " background: #e8e8d0;"
3512
 
                             " margin-top: 0em;"
3513
 
                             " margin-bottom: 0em;"
3514
 
                             "}\n"
3515
 
                             "li {"
3516
 
                             " margin-top: 0.25em;"
3517
 
                             " margin-right: 2em;"
3518
 
                             "}\n"
3519
 
                             ".hr {margin-top: 0.25em;"
3520
 
                             " border-color: black;"
3521
 
                             " border-bottom-style: solid;"
3522
 
                             "}\n"
3523
 
                             ".pxname   {background: #b00040;color: #ffff40;font-weight: bold;}\n"
3524
 
                             ".titre    {background: #20D0D0;color: #000000;font-weight: bold;}\n"
3525
 
                             ".total    {background: #20D0D0;color: #ffff80;}\n"
3526
 
                             ".frontend {background: #e8e8d0;}\n"
3527
 
                             ".backend  {background: #e8e8d0;}\n"
3528
 
                             ".active0  {background: #ff9090;}\n"
3529
 
                             ".active1  {background: #ffd020;}\n"
3530
 
                             ".active2  {background: #ffffa0;}\n"
3531
 
                             ".active3  {background: #c0ffc0;}\n"
3532
 
                             ".active4  {background: #e0e0e0;}\n"
3533
 
                             ".backup0  {background: #ff9090;}\n"
3534
 
                             ".backup1  {background: #ff80ff;}\n"
3535
 
                             ".backup2  {background: #c060ff;}\n"
3536
 
                             ".backup3  {background: #b0d0ff;}\n"
3537
 
                             ".backup4  {background: #e0e0e0;}\n"
3538
 
                             "table.tbl { border-collapse: collapse; border-style: none;}\n"
3539
 
                             "table.tbl td { border-width: 1px 1px 1px 1px; border-style: solid solid solid solid; padding: 2px 3px; border-color: gray;}\n"
3540
 
                             "table.tbl th { border-width: 1px; border-style: solid solid solid solid; border-color: gray;}\n"
3541
 
                             "table.tbl th.empty { border-style: none; empty-cells: hide;}\n"
3542
 
                             "table.lgd { border-collapse: collapse; border-width: 1px; border-style: none none none solid; border-color: black;}\n"
3543
 
                             "table.lgd td { border-width: 1px; border-style: solid solid solid solid; border-color: gray; padding: 2px;}\n"
3544
 
                             "table.lgd td.noborder { border-style: none; padding: 2px; white-space: nowrap;}\n"
3545
 
                             "-->\n"
3546
 
                             "</style></head>\n");
3547
 
                        
3548
 
                if (buffer_write_chunk(rep, &msg) != 0)
3549
 
                        return 0;
3550
 
 
3551
 
                s->data_state = DATA_ST_INFO;
3552
 
                /* fall through */
3553
 
 
3554
 
        case DATA_ST_INFO:
3555
 
                up = (now.tv_sec - start_date.tv_sec);
3556
 
 
3557
 
                /* WARNING! this has to fit the first packet too.
3558
 
                         * We are around 3.5 kB, add adding entries will
3559
 
                         * become tricky if we want to support 4kB buffers !
3560
 
                         */
3561
 
                chunk_printf(&msg, sizeof(trash),
3562
 
                             "<body><h1><a href=\"" PRODUCT_URL "\" style=\"text-decoration: none;\">"
3563
 
                             PRODUCT_NAME "</a></h1>\n"
3564
 
                             "<h2>Statistics Report for pid %d</h2>\n"
3565
 
                             "<hr width=\"100%%\" class=\"hr\">\n"
3566
 
                             "<h3>&gt; General process information</h3>\n"
3567
 
                             "<table border=0 cols=3><tr><td align=\"left\" nowrap width=\"1%%\">\n"
3568
 
                             "<p><b>pid = </b> %d (nbproc = %d)<br>\n"
3569
 
                             "<b>uptime = </b> %dd %dh%02dm%02ds<br>\n"
3570
 
                             "<b>system limits :</b> memmax = %s%s ; ulimit-n = %d<br>\n"
3571
 
                             "<b>maxsock = </b> %d<br>\n"
3572
 
                             "<b>maxconn = </b> %d (current conns = %d)<br>\n"
3573
 
                             "</td><td align=\"center\" nowrap>\n"
3574
 
                             "<table class=\"lgd\"><tr>\n"
3575
 
                             "<td class=\"active3\">&nbsp;</td><td class=\"noborder\">active UP </td>"
3576
 
                             "<td class=\"backup3\">&nbsp;</td><td class=\"noborder\">backup UP </td>"
3577
 
                             "</tr><tr>\n"
3578
 
                             "<td class=\"active2\"></td><td class=\"noborder\">active UP, going down </td>"
3579
 
                             "<td class=\"backup2\"></td><td class=\"noborder\">backup UP, going down </td>"
3580
 
                             "</tr><tr>\n"
3581
 
                             "<td class=\"active1\"></td><td class=\"noborder\">active DOWN, going up </td>"
3582
 
                             "<td class=\"backup1\"></td><td class=\"noborder\">backup DOWN, going up </td>"
3583
 
                             "</tr><tr>\n"
3584
 
                             "<td class=\"active0\"></td><td class=\"noborder\">active or backup DOWN &nbsp;</td>"
3585
 
                             "<td class=\"active4\"></td><td class=\"noborder\">not checked </td>"
3586
 
                             "</tr></table>\n"
3587
 
                             "</td>"
3588
 
                             "<td align=\"left\" nowrap width=\"1%%\">"
3589
 
                             "<b>External ressources:</b><ul style=\"margin-top: 0.25em;\">\n"
3590
 
                             "<li><a href=\"" PRODUCT_URL "\">Primary site</a><br>\n"
3591
 
                             "<li><a href=\"" PRODUCT_URL_UPD "\">Updates (v" PRODUCT_BRANCH ")</a><br>\n"
3592
 
                             "<li><a href=\"" PRODUCT_URL_DOC "\">Online manual</a><br>\n"
3593
 
                             "</ul>"
3594
 
                             "</td>"
3595
 
                             "</tr></table>\n"
3596
 
                             "",
3597
 
                             pid, pid, global.nbproc,
3598
 
                             up / 86400, (up % 86400) / 3600,
3599
 
                             (up % 3600) / 60, (up % 60),
3600
 
                             global.rlimit_memmax ? ultoa(global.rlimit_memmax) : "unlimited",
3601
 
                             global.rlimit_memmax ? " MB" : "",
3602
 
                             global.rlimit_nofile,
3603
 
                             global.maxsock,
3604
 
                             global.maxconn,
3605
 
                             actconn
3606
 
                             );
3607
 
            
3608
 
                if (buffer_write_chunk(rep, &msg) != 0)
3609
 
                        return 0;
3610
 
 
3611
 
                memset(&s->data_ctx, 0, sizeof(s->data_ctx));
3612
 
 
3613
 
                s->data_ctx.stats.px = proxy;
3614
 
                s->data_ctx.stats.px_st = DATA_ST_PX_INIT;
3615
 
                s->data_state = DATA_ST_LIST;
3616
 
                /* fall through */
3617
 
 
3618
 
        case DATA_ST_LIST:
3619
 
                /* dump proxies */
3620
 
                while (s->data_ctx.stats.px) {
3621
 
                        px = s->data_ctx.stats.px;
3622
 
                        /* skip the disabled proxies and non-networked ones */
3623
 
                        if (px->state != PR_STSTOPPED && (px->cap & (PR_CAP_FE | PR_CAP_BE)))
3624
 
                                if (produce_content_stats_proxy(s, px) == 0)
3625
 
                                        return 0;
3626
 
 
3627
 
                        s->data_ctx.stats.px = px->next;
3628
 
                        s->data_ctx.stats.px_st = DATA_ST_PX_INIT;
3629
 
                }
3630
 
                /* here, we just have reached the last proxy */
3631
 
 
3632
 
                s->data_state = DATA_ST_END;
3633
 
                /* fall through */
3634
 
 
3635
 
        case DATA_ST_END:
3636
 
                chunk_printf(&msg, sizeof(trash), "</body></html>\n");
3637
 
                if (buffer_write_chunk(rep, &msg) != 0)
3638
 
                        return 0;
3639
 
 
3640
 
                s->data_state = DATA_ST_FIN;
3641
 
                /* fall through */
3642
 
 
3643
 
        case DATA_ST_FIN:
3644
 
                s->flags &= ~SN_SELF_GEN;
3645
 
                return 1;
3646
 
 
3647
 
        default:
3648
 
                /* unknown state ! */
3649
 
                s->txn.status = 500;
3650
 
                client_retnclose(s, error_message(s, HTTP_ERR_500));
3651
 
                if (!(s->flags & SN_ERR_MASK))
3652
 
                        s->flags |= SN_ERR_PRXCOND;
3653
 
                if (!(s->flags & SN_FINST_MASK))
3654
 
                        s->flags |= SN_FINST_R;
3655
 
                s->flags &= ~SN_SELF_GEN;
3656
 
                return 1;
3657
 
        }
3658
 
}
3659
 
 
3660
 
 
3661
 
/*
3662
 
 * Dumps statistics for a proxy.
3663
 
 * Returns 0 if it had to stop dumping data because of lack of buffer space,
3664
 
 * ot non-zero if everything completed.
3665
 
 */
3666
 
int produce_content_stats_proxy(struct session *s, struct proxy *px)
3667
 
{
3668
 
        struct buffer *rep = s->rep;
3669
 
        struct server *sv;
3670
 
        struct chunk msg;
3671
 
 
3672
 
        msg.len = 0;
3673
 
        msg.str = trash;
3674
 
 
3675
 
        switch (s->data_ctx.stats.px_st) {
3676
 
        case DATA_ST_PX_INIT:
3677
 
                /* we are on a new proxy */
3678
 
 
3679
 
                if (s->be->uri_auth && s->be->uri_auth->scope) {
3680
 
                        /* we have a limited scope, we have to check the proxy name */
3681
 
                        struct stat_scope *scope;
3682
 
                        int len;
3683
 
 
3684
 
                        len = strlen(px->id);
3685
 
                        scope = s->be->uri_auth->scope;
3686
 
 
3687
 
                        while (scope) {
3688
 
                                /* match exact proxy name */
3689
 
                                if (scope->px_len == len && !memcmp(px->id, scope->px_id, len))
3690
 
                                        break;
3691
 
 
3692
 
                                /* match '.' which means 'self' proxy */
3693
 
                                if (!strcmp(scope->px_id, ".") && px == s->fe)
3694
 
                                        break;
3695
 
                                scope = scope->next;
3696
 
                        }
3697
 
 
3698
 
                        /* proxy name not found : don't dump anything */
3699
 
                        if (scope == NULL)
3700
 
                                return 1;
3701
 
                }
3702
 
 
3703
 
                s->data_ctx.stats.px_st = DATA_ST_PX_TH;
3704
 
                /* fall through */
3705
 
 
3706
 
        case DATA_ST_PX_TH:
3707
 
                /* print a new table */
3708
 
                chunk_printf(&msg, sizeof(trash),
3709
 
                             "<table cols=\"20\" class=\"tbl\" width=\"100%%\">\n"
3710
 
                             "<tr align=\"center\" class=\"titre\">"
3711
 
                             "<th colspan=2 class=\"pxname\">%s</th>"
3712
 
                             "<th colspan=18 class=\"empty\"></th>"
3713
 
                             "</tr>\n"
3714
 
                             "<tr align=\"center\" class=\"titre\">"
3715
 
                             "<th rowspan=2></th>"
3716
 
                             "<th colspan=2>Queue</th><th colspan=4>Sessions</th>"
3717
 
                             "<th colspan=2>Bytes</th><th colspan=2>Denied</th>"
3718
 
                             "<th colspan=3>Errors</th><th colspan=6>Server</th>"
3719
 
                             "</tr>\n"
3720
 
                             "<tr align=\"center\" class=\"titre\">"
3721
 
                             "<th>Cur</th><th>Max</th><th>Cur</th><th>Max</th>"
3722
 
                             "<th>Limit</th><th>Cumul</th><th>In</th><th>Out</th>"
3723
 
                             "<th>Req</th><th>Resp</th><th>Req</th><th>Conn</th>"
3724
 
                             "<th>Resp</th><th>Status</th><th>Weight</th><th>Act</th>"
3725
 
                             "<th>Bck</th><th>Check</th><th>Down</th></tr>\n"
3726
 
                             "",
3727
 
                             px->id);
3728
 
                
3729
 
                if (buffer_write_chunk(rep, &msg) != 0)
3730
 
                        return 0;
3731
 
 
3732
 
                s->data_ctx.stats.px_st = DATA_ST_PX_FE;
3733
 
                /* fall through */
3734
 
 
3735
 
        case DATA_ST_PX_FE:
3736
 
                /* print the frontend */
3737
 
                if (px->cap & PR_CAP_FE) {
3738
 
                        chunk_printf(&msg, sizeof(trash),
3739
 
                                     /* name, queue */
3740
 
                                     "<tr align=center class=\"frontend\"><td>Frontend</td><td colspan=2></td>"
3741
 
                                     /* sessions : current, max, limit, cumul. */
3742
 
                                     "<td align=right>%d</td><td align=right>%d</td><td align=right>%d</td><td align=right>%d</td>"
3743
 
                                     /* bytes : in, out */
3744
 
                                     "<td align=right>%lld</td><td align=right>%lld</td>"
3745
 
                                     /* denied: req, resp */
3746
 
                                     "<td align=right>%d</td><td align=right>%d</td>"
3747
 
                                     /* errors : request, connect, response */
3748
 
                                     "<td align=right>%d</td><td align=right></td><td align=right></td>"
3749
 
                                     /* server status : reflect backend status */
3750
 
                                     "<td align=center>%s</td>"
3751
 
                                     /* rest of server: nothing */
3752
 
                                     "<td align=center colspan=5></td></tr>"
3753
 
                                     "",
3754
 
                                     px->feconn, px->feconn_max, px->maxconn, px->cum_feconn,
3755
 
                                     px->bytes_in, px->bytes_out,
3756
 
                                     px->denied_req, px->denied_resp,
3757
 
                                     px->failed_req,
3758
 
                                     px->state == PR_STRUN ? "OPEN" :
3759
 
                                     px->state == PR_STIDLE ? "FULL" : "STOP");
3760
 
 
3761
 
                        if (buffer_write_chunk(rep, &msg) != 0)
3762
 
                                return 0;
3763
 
                }
3764
 
 
3765
 
                s->data_ctx.stats.sv = px->srv; /* may be NULL */
3766
 
                s->data_ctx.stats.px_st = DATA_ST_PX_SV;
3767
 
                /* fall through */
3768
 
 
3769
 
        case DATA_ST_PX_SV:
3770
 
                /* stats.sv has been initialized above */
3771
 
                while (s->data_ctx.stats.sv != NULL) {
3772
 
                        static char *srv_hlt_st[5] = { "DOWN", "DN %d/%d &uarr;", "UP %d/%d &darr;", "UP", "<i>no check</i>" };
3773
 
                        int sv_state; /* 0=DOWN, 1=going up, 2=going down, 3=UP, 4=unchecked */
3774
 
 
3775
 
                        sv = s->data_ctx.stats.sv;
3776
 
 
3777
 
                        /* FIXME: produce some small strings for "UP/DOWN x/y &#xxxx;" */
3778
 
                        if (!(sv->state & SRV_CHECKED))
3779
 
                                sv_state = 4;
3780
 
                        else if (sv->state & SRV_RUNNING)
3781
 
                                if (sv->health == sv->rise + sv->fall - 1)
3782
 
                                        sv_state = 3; /* UP */
3783
 
                                else
3784
 
                                        sv_state = 2; /* going down */
3785
 
                        else
3786
 
                                if (sv->health)
3787
 
                                        sv_state = 1; /* going up */
3788
 
                                else
3789
 
                                        sv_state = 0; /* DOWN */
3790
 
 
3791
 
                        chunk_printf(&msg, sizeof(trash),
3792
 
                                     /* name */
3793
 
                                     "<tr align=\"center\" class=\"%s%d\"><td>%s</td>"
3794
 
                                     /* queue : current, max */
3795
 
                                     "<td align=right>%d</td><td align=right>%d</td>"
3796
 
                                     /* sessions : current, max, limit, cumul */
3797
 
                                     "<td align=right>%d</td><td align=right>%d</td><td align=right>%s</td><td align=right>%d</td>"
3798
 
                                     /* bytes : in, out */
3799
 
                                     "<td align=right>%lld</td><td align=right>%lld</td>"
3800
 
                                     /* denied: req, resp */
3801
 
                                     "<td align=right></td><td align=right>%d</td>"
3802
 
                                     /* errors : request, connect, response */
3803
 
                                     "<td align=right></td><td align=right>%d</td><td align=right>%d</td>\n"
3804
 
                                     "",
3805
 
                                     (sv->state & SRV_BACKUP) ? "backup" : "active",
3806
 
                                     sv_state, sv->id,
3807
 
                                     sv->nbpend, sv->nbpend_max,
3808
 
                                     sv->cur_sess, sv->cur_sess_max, sv->maxconn ? ultoa(sv->maxconn) : "-", sv->cum_sess,
3809
 
                                     sv->bytes_in, sv->bytes_out,
3810
 
                                     sv->failed_secu,
3811
 
                                     sv->failed_conns, sv->failed_resp);
3812
 
                                     
3813
 
                        /* status */
3814
 
                        chunk_printf(&msg, sizeof(trash), "<td nowrap>");
3815
 
                        chunk_printf(&msg, sizeof(trash),
3816
 
                                     srv_hlt_st[sv_state],
3817
 
                                     (sv->state & SRV_RUNNING) ? (sv->health - sv->rise + 1) : (sv->health),
3818
 
                                     (sv->state & SRV_RUNNING) ? (sv->fall) : (sv->rise));
3819
 
 
3820
 
                        chunk_printf(&msg, sizeof(trash),
3821
 
                                     /* weight */
3822
 
                                     "</td><td>%d</td>"
3823
 
                                     /* act, bck */
3824
 
                                     "<td>%s</td><td>%s</td>"
3825
 
                                     "",
3826
 
                                     sv->uweight,
3827
 
                                     (sv->state & SRV_BACKUP) ? "-" : "Y",
3828
 
                                     (sv->state & SRV_BACKUP) ? "Y" : "-");
3829
 
 
3830
 
                        /* check failures : unique, fatal */
3831
 
                        if (sv->state & SRV_CHECKED)
3832
 
                                chunk_printf(&msg, sizeof(trash),
3833
 
                                             "<td align=right>%d</td><td align=right>%d</td></tr>\n",
3834
 
                                             sv->failed_checks, sv->down_trans);
3835
 
                        else
3836
 
                                chunk_printf(&msg, sizeof(trash),
3837
 
                                             "<td colspan=2></td></tr>\n");
3838
 
 
3839
 
                        if (buffer_write_chunk(rep, &msg) != 0)
3840
 
                                return 0;
3841
 
 
3842
 
                        s->data_ctx.stats.sv = sv->next;
3843
 
                } /* while sv */
3844
 
 
3845
 
                s->data_ctx.stats.px_st = DATA_ST_PX_BE;
3846
 
                /* fall through */
3847
 
 
3848
 
        case DATA_ST_PX_BE:
3849
 
                /* print the backend */
3850
 
                if (px->cap & PR_CAP_BE) {
3851
 
                        chunk_printf(&msg, sizeof(trash),
3852
 
                                     /* name */
3853
 
                                     "<tr align=center class=\"backend\"><td>Backend</td>"
3854
 
                                     /* queue : current, max */
3855
 
                                     "<td align=right>%d</td><td align=right>%d</td>"
3856
 
                                     /* sessions : current, max, limit, cumul. */
3857
 
                                     "<td align=right>%d</td><td align=right>%d</td><td align=right>%d</td><td align=right>%d</td>"
3858
 
                                     /* bytes : in, out */
3859
 
                                     "<td align=right>%lld</td><td align=right>%lld</td>"
3860
 
                                     /* denied: req, resp */
3861
 
                                     "<td align=right>%d</td><td align=right>%d</td>"
3862
 
                                     /* errors : request, connect, response */
3863
 
                                     "<td align=right></td><td align=right>%d</td><td align=right>%d</td>\n"
3864
 
                                     /* server status : reflect backend status (up/down) : we display UP
3865
 
                                      * if the backend has known working servers or if it has no server at
3866
 
                                      * all (eg: for stats). Tthen we display the total weight, number of
3867
 
                                      * active and backups. */
3868
 
                                     "<td align=center>%s</td><td align=center>%d</td>"
3869
 
                                     "<td align=center>%d</td><td align=center>%d</td>"
3870
 
                                     /* rest of server: nothing */
3871
 
                                     "<td align=center colspan=2></td></tr>"
3872
 
                                     "",
3873
 
                                     px->nbpend /* or px->totpend ? */, px->nbpend_max,
3874
 
                                     px->beconn, px->beconn_max, px->fullconn, px->cum_beconn,
3875
 
                                     px->bytes_in, px->bytes_out,
3876
 
                                     px->denied_req, px->denied_resp,
3877
 
                                     px->failed_conns, px->failed_resp,
3878
 
                                     (px->srv_map_sz > 0 || !px->srv) ? "UP" : "DOWN",
3879
 
                                     px->srv_map_sz, px->srv_act, px->srv_bck);
3880
 
 
3881
 
                        if (buffer_write_chunk(rep, &msg) != 0)
3882
 
                                return 0;
3883
 
                }
3884
 
                
3885
 
                s->data_ctx.stats.px_st = DATA_ST_PX_END;
3886
 
                /* fall through */
3887
 
 
3888
 
        case DATA_ST_PX_END:
3889
 
                chunk_printf(&msg, sizeof(trash), "</table><p>\n");
3890
 
 
3891
 
                if (buffer_write_chunk(rep, &msg) != 0)
3892
 
                        return 0;
3893
 
 
3894
 
                s->data_ctx.stats.px_st = DATA_ST_PX_FIN;
3895
 
                /* fall through */
3896
 
 
3897
 
        case DATA_ST_PX_FIN:
3898
 
                return 1;
3899
 
 
3900
 
        default:
3901
 
                /* unknown state, we should put an abort() here ! */
3902
 
                return 1;
3903
 
        }
 
3411
                int ret = stats_dump_http(s, s->be->uri_auth,
 
3412
                                          (s->flags & SN_STAT_FMTCSV) ? 0 : STAT_FMT_HTML);
 
3413
                if (ret >= 0)
 
3414
                        return ret;
 
3415
                /* -1 indicates an error */
 
3416
        }
 
3417
 
 
3418
        /* unknown data source or internal error */
 
3419
        s->txn.status = 500;
 
3420
        client_retnclose(s, error_message(s, HTTP_ERR_500));
 
3421
        if (!(s->flags & SN_ERR_MASK))
 
3422
                s->flags |= SN_ERR_PRXCOND;
 
3423
        if (!(s->flags & SN_FINST_MASK))
 
3424
                s->flags |= SN_FINST_R;
 
3425
        s->flags &= ~SN_SELF_GEN;
 
3426
        return 1;
3904
3427
}
3905
3428
 
3906
3429
 
3971
3494
                                 * frontend, and the beconn will be updated later.
3972
3495
                                 */
3973
3496
 
3974
 
                                t->rep->rto = t->req->wto = t->be->srvtimeout;
3975
 
                                t->req->cto = t->be->contimeout;
 
3497
                                t->rep->rto = t->req->wto = t->be->timeout.server;
 
3498
                                t->req->cto = t->be->timeout.connect;
 
3499
                                t->conn_retries = t->be->conn_retries;
3976
3500
                                last_hdr = 1;
3977
3501
                                break;
3978
3502
 
4091
3615
                         * frontend, and the beconn will be updated later.
4092
3616
                         */
4093
3617
 
4094
 
                        t->rep->rto = t->req->wto = t->be->srvtimeout;
4095
 
                        t->req->cto = t->be->contimeout;
 
3618
                        t->rep->rto = t->req->wto = t->be->timeout.server;
 
3619
                        t->req->cto = t->be->timeout.connect;
 
3620
                        t->conn_retries = t->be->conn_retries;
4096
3621
                        done = 1;
4097
3622
                        break;
4098
3623
 
4193
3718
 
4194
3719
 
4195
3720
/*
4196
 
 * Manager client-side cookie
 
3721
 * Manage client-side cookie. It can impact performance by about 2% so it is
 
3722
 * desirable to call it only when needed.
4197
3723
 */
4198
3724
void manage_client_side_cookies(struct session *t, struct buffer *req)
4199
3725
{
4208
3734
        char *cur_ptr, *cur_end, *cur_next;
4209
3735
        int cur_idx, old_idx;
4210
3736
 
4211
 
        if (t->be->cookie_name == NULL &&
4212
 
            t->be->appsession_name == NULL &&
4213
 
            t->be->capture_name == NULL)
4214
 
                return;
4215
 
 
4216
3737
        /* Iterate through the headers.
4217
3738
         * we start with the start line.
4218
3739
         */
4492
4013
                                                }/* end while(srv) */
4493
4014
                                        }/* end else if server == NULL */
4494
4015
 
4495
 
                                        tv_add(&asession_temp->expire, &now, &t->be->appsession_timeout);
 
4016
                                        tv_add(&asession_temp->expire, &now, &t->be->timeout.appsession);
4496
4017
                                }/* end if ((t->proxy->appsession_name != NULL) ... */
4497
4018
                        }
4498
4019
 
4758
4279
 
4759
4280
 
4760
4281
/*
4761
 
 * Manager server-side cookies
 
4282
 * Manage server-side cookies. It can impact performance by about 2% so it is
 
4283
 * desirable to call it only when needed.
4762
4284
 */
4763
4285
void manage_server_side_cookies(struct session *t, struct buffer *rtr)
4764
4286
{
4771
4293
        char *cur_ptr, *cur_end, *cur_next;
4772
4294
        int cur_idx, old_idx, delta;
4773
4295
 
4774
 
        if (t->be->cookie_name == NULL &&
4775
 
            t->be->appsession_name == NULL &&
4776
 
            t->be->capture_name == NULL &&
4777
 
            !(t->be->options & PR_O_CHK_CACHE))
4778
 
                return;
4779
 
 
4780
4296
        /* Iterate through the headers.
4781
4297
         * we start with the start line.
4782
4298
         */
4925
4441
                                asession_temp->serverid = NULL;
4926
4442
 
4927
4443
                                /* only do insert, if lookup fails */
4928
 
                                if (appsession_hash_lookup(&(t->be->htbl_proxy), asession_temp->sessid) == NULL) {
 
4444
                                asession_temp = appsession_hash_lookup(&(t->be->htbl_proxy), asession_temp->sessid);
 
4445
                                if (asession_temp == NULL) {
4929
4446
                                        if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) {
4930
4447
                                                Alert("Not enough Memory process_srv():asession:calloc().\n");
4931
4448
                                                send_log(t->be, LOG_ALERT, "Not enough Memory process_srv():asession:calloc().\n");
4951
4468
                                if (asession_temp->serverid[0] == '\0')
4952
4469
                                        memcpy(asession_temp->serverid, t->srv->id, server_id_len);
4953
4470
                      
4954
 
                                tv_add(&asession_temp->expire, &now, &t->be->appsession_timeout);
 
4471
                                tv_add(&asession_temp->expire, &now, &t->be->timeout.appsession);
4955
4472
 
4956
4473
#if defined(DEBUG_HASH)
4957
4474
                                appsession_hash_dump(&(t->be->htbl_proxy));
4978
4495
        char *cur_ptr, *cur_end, *cur_next;
4979
4496
        int cur_idx;
4980
4497
 
4981
 
        if (!txn->flags & TX_CACHEABLE)
 
4498
        if (!(txn->flags & TX_CACHEABLE))
4982
4499
                return;
4983
4500
 
4984
4501
        /* Iterate through the headers.
5096
4613
        asession_temp->serverid = NULL;
5097
4614
        
5098
4615
        /* only do insert, if lookup fails */
5099
 
        if (appsession_hash_lookup(&(t->be->htbl_proxy), asession_temp->sessid) == NULL) {
 
4616
        asession_temp = appsession_hash_lookup(&(t->be->htbl_proxy), asession_temp->sessid);
 
4617
        if (asession_temp == NULL) {
5100
4618
                if ((asession_temp = pool_alloc2(pool2_appsess)) == NULL) {
5101
4619
                        /* free previously allocated memory */
5102
4620
                        pool_free2(apools.sessid, local_asession.sessid);
5113
4631
                pool_free2(apools.sessid, local_asession.sessid);
5114
4632
        }
5115
4633
 
5116
 
        tv_add(&asession_temp->expire, &now, &t->be->appsession_timeout);
 
4634
        tv_add(&asession_temp->expire, &now, &t->be->timeout.appsession);
5117
4635
        asession_temp->request_count++;
5118
4636
 
5119
4637
#if defined(DEBUG_HASH)
5171
4689
        if (memcmp(h, uri_auth->uri_prefix, uri_auth->uri_len) != 0)
5172
4690
                return 0;
5173
4691
 
 
4692
        h += uri_auth->uri_len;
 
4693
        while (h <= t->req->data + txn->req.sl.rq.u + txn->req.sl.rq.u_l - 3) {
 
4694
                if (memcmp(h, ";up", 3) == 0) {
 
4695
                        t->flags |= SN_STAT_HIDEDWN;
 
4696
                        break;
 
4697
                }
 
4698
                h++;
 
4699
        }
 
4700
 
 
4701
        if (uri_auth->refresh) {
 
4702
                h = t->req->data + txn->req.sl.rq.u + uri_auth->uri_len;
 
4703
                while (h <= t->req->data + txn->req.sl.rq.u + txn->req.sl.rq.u_l - 10) {
 
4704
                        if (memcmp(h, ";norefresh", 10) == 0) {
 
4705
                                t->flags |= SN_STAT_NORFRSH;
 
4706
                                break;
 
4707
                        }
 
4708
                        h++;
 
4709
                }
 
4710
        }
 
4711
 
 
4712
        h = t->req->data + txn->req.sl.rq.u + uri_auth->uri_len;
 
4713
        while (h <= t->req->data + txn->req.sl.rq.u + txn->req.sl.rq.u_l - 4) {
 
4714
                if (memcmp(h, ";csv", 4) == 0) {
 
4715
                        t->flags |= SN_STAT_FMTCSV;
 
4716
                        break;
 
4717
                }
 
4718
                h++;
 
4719
        }
 
4720
 
5174
4721
        /* we are in front of a interceptable URI. Let's check
5175
4722
         * if there's an authentication and if it's valid.
5176
4723
         */
5433
4980
        return 1;
5434
4981
}
5435
4982
 
 
4983
static int
 
4984
acl_fetch_url_ip(struct proxy *px, struct session *l4, void *l7, int dir,
 
4985
                 struct acl_expr *expr, struct acl_test *test)
 
4986
{
 
4987
        struct http_txn *txn = l7;
 
4988
 
 
4989
        if (txn->req.msg_state != HTTP_MSG_BODY)
 
4990
                return 0;
 
4991
        if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
 
4992
                /* ensure the indexes are not affected */
 
4993
                return 0;
 
4994
 
 
4995
        /* Parse HTTP request */
 
4996
        url2sa(txn->req.sol + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->srv_addr);
 
4997
        test->ptr = (void *)&((struct sockaddr_in *)&l4->srv_addr)->sin_addr;
 
4998
        test->i = AF_INET;
 
4999
 
 
5000
        /*
 
5001
         * If we are parsing url in frontend space, we prepare backend stage
 
5002
         * to not parse again the same url ! optimization lazyness...
 
5003
         */
 
5004
        if (px->options & PR_O_HTTP_PROXY)
 
5005
                l4->flags |= SN_ADDR_SET;
 
5006
 
 
5007
        test->flags = ACL_TEST_F_READ_ONLY;
 
5008
        return 1;
 
5009
}
 
5010
 
 
5011
static int
 
5012
acl_fetch_url_port(struct proxy *px, struct session *l4, void *l7, int dir,
 
5013
                   struct acl_expr *expr, struct acl_test *test)
 
5014
{
 
5015
        struct http_txn *txn = l7;
 
5016
 
 
5017
        if (txn->req.msg_state != HTTP_MSG_BODY)
 
5018
                return 0;
 
5019
        if (txn->rsp.msg_state != HTTP_MSG_RPBEFORE)
 
5020
                /* ensure the indexes are not affected */
 
5021
                return 0;
 
5022
 
 
5023
        /* Same optimization as url_ip */
 
5024
        url2sa(txn->req.sol + txn->req.sl.rq.u, txn->req.sl.rq.u_l, &l4->srv_addr);
 
5025
        test->i = ntohs(((struct sockaddr_in *)&l4->srv_addr)->sin_port);
 
5026
 
 
5027
        if (px->options & PR_O_HTTP_PROXY)
 
5028
                l4->flags |= SN_ADDR_SET;
 
5029
 
 
5030
        test->flags = ACL_TEST_F_READ_ONLY;
 
5031
        return 1;
 
5032
}
 
5033
 
5436
5034
/* 5. Check on HTTP header. A pointer to the beginning of the value is returned.
5437
5035
 * This generic function is used by both acl_fetch_chdr() and acl_fetch_shdr().
5438
5036
 */
5669
5267
        { "resp_ver",   acl_parse_ver,   acl_fetch_stver,  acl_match_str  },
5670
5268
        { "status",     acl_parse_int,   acl_fetch_stcode, acl_match_int  },
5671
5269
 
5672
 
        { "url",        acl_parse_str,   acl_fetch_url,    acl_match_str  },
5673
 
        { "url_beg",    acl_parse_str,   acl_fetch_url,    acl_match_beg  },
5674
 
        { "url_end",    acl_parse_str,   acl_fetch_url,    acl_match_end  },
5675
 
        { "url_sub",    acl_parse_str,   acl_fetch_url,    acl_match_sub  },
5676
 
        { "url_dir",    acl_parse_str,   acl_fetch_url,    acl_match_dir  },
5677
 
        { "url_dom",    acl_parse_str,   acl_fetch_url,    acl_match_dom  },
5678
 
        { "url_reg",    acl_parse_reg,   acl_fetch_url,    acl_match_reg  },
 
5270
        { "url",        acl_parse_str,   acl_fetch_url,      acl_match_str  },
 
5271
        { "url_beg",    acl_parse_str,   acl_fetch_url,      acl_match_beg  },
 
5272
        { "url_end",    acl_parse_str,   acl_fetch_url,      acl_match_end  },
 
5273
        { "url_sub",    acl_parse_str,   acl_fetch_url,      acl_match_sub  },
 
5274
        { "url_dir",    acl_parse_str,   acl_fetch_url,      acl_match_dir  },
 
5275
        { "url_dom",    acl_parse_str,   acl_fetch_url,      acl_match_dom  },
 
5276
        { "url_reg",    acl_parse_reg,   acl_fetch_url,      acl_match_reg  },
 
5277
        { "url_ip",     acl_parse_ip,    acl_fetch_url_ip,   acl_match_ip   },
 
5278
        { "url_port",   acl_parse_int,   acl_fetch_url_port, acl_match_int  },
5679
5279
 
5680
5280
        { "hdr",        acl_parse_str,   acl_fetch_chdr,    acl_match_str },
5681
5281
        { "hdr_reg",    acl_parse_reg,   acl_fetch_chdr,    acl_match_reg },