static void balancer_display_page()

in modules/proxy/mod_proxy_balancer.c [1408:1868]


static void balancer_display_page(request_rec *r, proxy_server_conf *conf,
                                  proxy_balancer *bsel,
                                  proxy_worker *wsel,
                                  int usexml)
{
    const char *action;
    proxy_balancer *balancer;
    proxy_worker *worker;
    proxy_worker **workers;
    int i, n;
    action = ap_construct_url(r->pool, r->uri, r);
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01204) "genning page");

    if (usexml) {
        char date[APR_RFC822_DATE_LEN];
        ap_set_content_type_ex(r, "text/xml", 1);
        ap_rputs("<?xml version='1.0' encoding='UTF-8' ?>\n", r);
        ap_rputs("<httpd:manager xmlns:httpd='http://httpd.apache.org'>\n", r);
        ap_rputs("  <httpd:balancers>\n", r);
        balancer = (proxy_balancer *)conf->balancers->elts;
        for (i = 0; i < conf->balancers->nelts; i++) {
            ap_rputs("    <httpd:balancer>\n", r);
            /* Start proxy_balancer */
            ap_rvputs(r, "      <httpd:name>", balancer->s->name, "</httpd:name>\n", NULL);
            ap_rvputs(r, "      <httpd:nonce>", balancer->s->nonce, "</httpd:nonce>\n", NULL);
            if (*balancer->s->sticky) {
                ap_rvputs(r, "      <httpd:stickysession>", ap_escape_html(r->pool, balancer->s->sticky),
                          "</httpd:stickysession>\n", NULL);
                ap_rprintf(r,
                           "      <httpd:nofailover>%s</httpd:nofailover>\n",
                           (balancer->s->sticky_force ? "On" : "Off"));
            }
            ap_rprintf(r,
                       "      <httpd:timeout>%" APR_TIME_T_FMT "</httpd:timeout>\n",
                       apr_time_sec(balancer->s->timeout));
            if (balancer->s->max_attempts_set) {
                ap_rprintf(r,
                           "      <httpd:maxattempts>%d</httpd:maxattempts>\n",
                           balancer->s->max_attempts);
            }
            ap_rvputs(r, "      <httpd:lbmethod>", balancer->lbmethod->name,
                      "</httpd:lbmethod>\n", NULL);
            if (*balancer->s->sticky) {
                ap_rprintf(r,
                           "      <httpd:scolonpathdelim>%s</httpd:scolonpathdelim>\n",
                           (balancer->s->scolonsep ? "On" : "Off"));
            }
            /* End proxy_balancer */
            ap_rputs("      <httpd:workers>\n", r);
            workers = (proxy_worker **)balancer->workers->elts;
            for (n = 0; n < balancer->workers->nelts; n++) {
                worker = *workers;
                /* Start proxy_worker */
                ap_rputs("        <httpd:worker>\n", r);
                ap_rvputs(r, "          <httpd:name>", ap_proxy_worker_get_name(worker),
                          "</httpd:name>\n", NULL);
                ap_rvputs(r, "          <httpd:scheme>", worker->s->scheme,
                          "</httpd:scheme>\n", NULL);
                ap_rvputs(r, "          <httpd:hostname>", worker->s->hostname_ex,
                          "</httpd:hostname>\n", NULL);
                ap_rprintf(r, "          <httpd:loadfactor>%.2f</httpd:loadfactor>\n",
                          (float)(worker->s->lbfactor)/100.0);
                ap_rprintf(r,
                           "          <httpd:port>%d</httpd:port>\n",
                           worker->s->port);
                ap_rprintf(r, "          <httpd:min>%d</httpd:min>\n",
                           worker->s->min);
                ap_rprintf(r, "          <httpd:smax>%d</httpd:smax>\n",
                           worker->s->smax);
                ap_rprintf(r, "          <httpd:max>%d</httpd:max>\n",
                           worker->s->hmax);
                ap_rprintf(r,
                           "          <httpd:ttl>%" APR_TIME_T_FMT "</httpd:ttl>\n",
                           apr_time_sec(worker->s->ttl));
                if (worker->s->timeout_set) {
                    ap_rprintf(r,
                               "          <httpd:timeout>%" APR_TIME_T_FMT "</httpd:timeout>\n",
                               apr_time_sec(worker->s->timeout));
                }
                if (worker->s->acquire_set) {
                    ap_rprintf(r,
                               "          <httpd:acquire>%" APR_TIME_T_FMT "</httpd:acquire>\n",
                               apr_time_msec(worker->s->acquire));
                }
                if (worker->s->recv_buffer_size_set) {
                    ap_rprintf(r,
                               "          <httpd:recv_buffer_size>%" APR_SIZE_T_FMT "</httpd:recv_buffer_size>\n",
                               worker->s->recv_buffer_size);
                }
                if (worker->s->io_buffer_size_set) {
                    ap_rprintf(r,
                               "          <httpd:io_buffer_size>%" APR_SIZE_T_FMT "</httpd:io_buffer_size>\n",
                               worker->s->io_buffer_size);
                }
                if (worker->s->keepalive_set) {
                    ap_rprintf(r,
                               "          <httpd:keepalive>%s</httpd:keepalive>\n",
                               (worker->s->keepalive ? "On" : "Off"));
                }
                /* Begin proxy_worker_stat */
                ap_rputs("          <httpd:status>", r);
                ap_rputs(ap_proxy_parse_wstatus(r->pool, worker), r);
                ap_rputs("</httpd:status>\n", r);
                if ((worker->s->error_time > 0) && apr_rfc822_date(date, worker->s->error_time) == APR_SUCCESS) {
                    ap_rvputs(r, "          <httpd:error_time>", date,
                              "</httpd:error_time>\n", NULL);
                }
                ap_rprintf(r,
                           "          <httpd:retries>%d</httpd:retries>\n",
                           worker->s->retries);
                ap_rprintf(r,
                           "          <httpd:lbstatus>%d</httpd:lbstatus>\n",
                           worker->s->lbstatus);
                ap_rprintf(r,
                           "          <httpd:loadfactor>%.2f</httpd:loadfactor>\n",
                           (float)(worker->s->lbfactor)/100.0);
                ap_rprintf(r,
                           "          <httpd:transferred>%" APR_OFF_T_FMT "</httpd:transferred>\n",
                           worker->s->transferred);
                ap_rprintf(r,
                           "          <httpd:read>%" APR_OFF_T_FMT "</httpd:read>\n",
                           worker->s->read);
                ap_rprintf(r,
                           "          <httpd:elected>%" APR_SIZE_T_FMT "</httpd:elected>\n",
                           worker->s->elected);
                ap_rvputs(r, "          <httpd:route>",
                          ap_escape_html(r->pool, worker->s->route),
                          "</httpd:route>\n", NULL);
                ap_rvputs(r, "          <httpd:redirect>",
                          ap_escape_html(r->pool, worker->s->redirect),
                          "</httpd:redirect>\n", NULL);
                ap_rprintf(r,
                           "          <httpd:busy>%" APR_SIZE_T_FMT "</httpd:busy>\n",
                           ap_proxy_get_busy_count(worker));
                ap_rprintf(r, "          <httpd:lbset>%d</httpd:lbset>\n",
                           worker->s->lbset);
                /* End proxy_worker_stat */
                if (!ap_cstr_casecmp(worker->s->scheme, "ajp")) {
                    ap_rputs("          <httpd:flushpackets>", r);
                    switch (worker->s->flush_packets) {
                        case flush_off:
                            ap_rputs("Off", r);
                            break;
                        case flush_on:
                            ap_rputs("On", r);
                            break;
                        case flush_auto:
                            ap_rputs("Auto", r);
                            break;
                    }
                    ap_rputs("</httpd:flushpackets>\n", r);
                    if (worker->s->flush_packets == flush_auto) {
                        ap_rprintf(r,
                                   "          <httpd:flushwait>%d</httpd:flushwait>\n",
                                   worker->s->flush_wait);
                    }
                    if (worker->s->ping_timeout_set) {
                        ap_rprintf(r,
                                   "          <httpd:ping>%" APR_TIME_T_FMT "</httpd:ping>",
                                   apr_time_msec(worker->s->ping_timeout));
                    }
                }
                if (worker->s->disablereuse_set) {
                    ap_rprintf(r,
                               "      <httpd:disablereuse>%s</httpd:disablereuse>\n",
                               (worker->s->disablereuse ? "On" : "Off"));
                }
                if (worker->s->conn_timeout_set) {
                    ap_rprintf(r,
                               "          <httpd:connectiontimeout>%" APR_TIME_T_FMT "</httpd:connectiontimeout>\n",
                               apr_time_msec(worker->s->conn_timeout));
                }
                if (worker->s->retry_set) {
                    ap_rprintf(r,
                               "          <httpd:retry>%" APR_TIME_T_FMT "</httpd:retry>\n",
                               apr_time_sec(worker->s->retry));
                }
                ap_rputs("        </httpd:worker>\n", r);
                ++workers;
            }
            ap_rputs("      </httpd:workers>\n", r);
            ap_rputs("    </httpd:balancer>\n", r);
            ++balancer;
        }
        ap_rputs("  </httpd:balancers>\n", r);
        ap_rputs("</httpd:manager>", r);
    }
    else {
        ap_set_content_type_ex(r, "text/html; charset=ISO-8859-1", 1);
        ap_rputs(DOCTYPE_HTML_4_01
                 "<html><head><title>Balancer Manager</title>\n", r);
        ap_rputs("<style type='text/css'>\n"
                 "table {\n"
                 " border-width: 1px;\n"
                 " border-spacing: 3px;\n"
                 " border-style: solid;\n"
                 " border-color: gray;\n"
                 " border-collapse: collapse;\n"
                 " background-color: white;\n"
                 " text-align: center;\n"
                 "}\n"
                 "th {\n"
                 " border-width: 1px;\n"
                 " padding: 2px;\n"
                 " border-style: dotted;\n"
                 " border-color: gray;\n"
                 " background-color: lightgray;\n"
                 " text-align: center;\n"
                 "}\n"
                 "td {\n"
                 " border-width: 1px;\n"
                 " padding: 2px;\n"
                 " border-style: dotted;\n"
                 " border-color: gray;\n"
                 " background-color: white;\n"
                 " text-align: center;\n"
                 "}\n"
                 "</style>\n</head>\n", r);
        ap_rputs("<body><h1>Load Balancer Manager for ", r);
        ap_rvputs(r, ap_escape_html(r->pool, ap_get_server_name(r)),
                  "</h1>\n\n", NULL);
        ap_rvputs(r, "<dl><dt>Server Version: ",
                  ap_get_server_description(), "</dt>\n", NULL);
        ap_rvputs(r, "<dt>Server Built: ",
                  ap_get_server_built(), "</dt>\n", NULL);
        ap_rvputs(r, "<dt>Balancer changes will ", conf->bal_persist ? "" : "NOT ",
                  "be persisted on restart.</dt>", NULL);
        ap_rvputs(r, "<dt>Balancers are ", conf->inherit ? "" : "NOT ",
                  "inherited from main server.</dt>", NULL);
        ap_rvputs(r, "<dt>ProxyPass settings are ", conf->ppinherit ? "" : "NOT ",
                  "inherited from main server.</dt>", NULL);
        ap_rputs("</dl>\n", r);
        balancer = (proxy_balancer *)conf->balancers->elts;
        for (i = 0; i < conf->balancers->nelts; i++) {

            ap_rputs("<hr />\n<h3>LoadBalancer Status for ", r);
            ap_rvputs(r, "<a href=\"", ap_escape_uri(r->pool, r->uri), "?b=",
                      balancer->s->name + sizeof(BALANCER_PREFIX) - 1,
                      "&amp;nonce=", balancer->s->nonce,
                      "\">", NULL);
            ap_rvputs(r, balancer->s->name, "</a> [",balancer->s->sname, "]</h3>\n", NULL);
            ap_rputs("\n\n<table><tr>"
                "<th>MaxMembers</th><th>StickySession</th><th>DisableFailover</th><th>Timeout</th><th>FailoverAttempts</th><th>Method</th>"
                "<th>Path</th><th>Active</th></tr>\n<tr>", r);
            /* the below is a safe cast, since the number of slots total will
             * never be more than max_workers, which is restricted to int */
            ap_rprintf(r, "<td>%d [%d Used]</td>\n", balancer->max_workers,
                       balancer->max_workers - (int)storage->num_free_slots(balancer->wslot));
            if (*balancer->s->sticky) {
                if (strcmp(balancer->s->sticky, balancer->s->sticky_path)) {
                    ap_rvputs(r, "<td>", ap_escape_html(r->pool, balancer->s->sticky), "|",
                              ap_escape_html(r->pool, balancer->s->sticky_path), NULL);
                }
                else {
                    ap_rvputs(r, "<td>", ap_escape_html(r->pool, balancer->s->sticky), NULL);
                }
            }
            else {
                ap_rputs("<td> (None) ", r);
            }
            ap_rprintf(r, "</td><td>%s</td>\n",
                       balancer->s->sticky_force ? "On" : "Off");
            ap_rprintf(r, "<td>%" APR_TIME_T_FMT "</td>",
                apr_time_sec(balancer->s->timeout));
            ap_rprintf(r, "<td>%d</td>\n", balancer->s->max_attempts);
            ap_rprintf(r, "<td>%s</td>\n",
                       balancer->s->lbpname);
            ap_rputs("<td>", r);
            if (*balancer->s->vhost) {
                ap_rvputs(r, balancer->s->vhost, " -> ", NULL);
            }
            ap_rvputs(r, balancer->s->vpath, "</td>\n", NULL);
            ap_rprintf(r, "<td>%s</td>\n",
                       !balancer->s->inactive ? "Yes" : "No");
            ap_rputs("</tr>\n</table>\n<br />", r);
            ap_rputs("\n\n<table><tr>"
                "<th>Worker URL</th>"
                "<th>Route</th><th>RouteRedir</th>"
                "<th>Factor</th><th>Set</th><th>Status</th>"
                "<th>Elected</th><th>Busy</th><th>Load</th><th>To</th><th>From</th>", r);
            if (set_worker_hc_param_f) {
                ap_rputs("<th>HC Method</th><th>HC Interval</th><th>Passes</th><th>Fails</th><th>HC uri</th><th>HC Expr</th>", r);
            }
            ap_rputs("</tr>\n", r);

            workers = (proxy_worker **)balancer->workers->elts;
            for (n = 0; n < balancer->workers->nelts; n++) {
                char fbuf[50];
                worker = *workers;
                ap_rvputs(r, "<tr>\n<td><a href=\"",
                          ap_escape_uri(r->pool, r->uri), "?b=",
                          balancer->s->name + sizeof(BALANCER_PREFIX) - 1, "&amp;w=",
                          ap_escape_uri(r->pool, worker->s->name),
                          "&amp;nonce=", balancer->s->nonce,
                          "\">", NULL);
                ap_rvputs(r, (*worker->s->uds_path ? "<i>" : ""), ap_proxy_worker_get_name(worker),
                          (*worker->s->uds_path ? "</i>" : ""), "</a></td>", NULL);
                ap_rvputs(r, "<td>", ap_escape_html(r->pool, worker->s->route),
                          NULL);
                ap_rvputs(r, "</td><td>",
                          ap_escape_html(r->pool, worker->s->redirect), NULL);
                ap_rprintf(r, "</td><td>%.2f</td>", (float)(worker->s->lbfactor)/100.0);
                ap_rprintf(r, "<td>%d</td><td>", worker->s->lbset);
                ap_rvputs(r, ap_proxy_parse_wstatus(r->pool, worker), NULL);
                ap_rputs("</td>", r);
                ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td>", worker->s->elected);
                ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td>", ap_proxy_get_busy_count(worker));
                ap_rprintf(r, "<td>%d</td><td>", worker->s->lbstatus);
                ap_rputs(apr_strfsize(worker->s->transferred, fbuf), r);
                ap_rputs("</td><td>", r);
                ap_rputs(apr_strfsize(worker->s->read, fbuf), r);
                if (set_worker_hc_param_f) {
                    ap_rprintf(r, "</td><td>%s</td>", ap_proxy_show_hcmethod(worker->s->method));
                    ap_rprintf(r, "<td>%" APR_TIME_T_FMT "ms</td>", apr_time_as_msec(worker->s->interval));
                    ap_rprintf(r, "<td>%d (%d)</td>", worker->s->passes,worker->s->pcount);
                    ap_rprintf(r, "<td>%d (%d)</td>", worker->s->fails, worker->s->fcount);
                    ap_rprintf(r, "<td>%s</td>", ap_escape_html(r->pool, worker->s->hcuri));
                    ap_rprintf(r, "<td>%s", worker->s->hcexpr);
                }
                ap_rputs("</td></tr>\n", r);

                ++workers;
            }
            ap_rputs("</table>\n", r);
            ++balancer;
        }
        ap_rputs("<hr />\n", r);
        if (hc_show_exprs_f) {
            hc_show_exprs_f(r);
        }
        if (wsel && bsel) {
            ap_rputs("<h3>Edit worker settings for ", r);
            ap_rvputs(r, (*wsel->s->uds_path?"<i>":""), ap_proxy_worker_get_name(wsel), (*wsel->s->uds_path?"</i>":""), "</h3>\n", NULL);
            ap_rputs("<form method='POST' enctype='application/x-www-form-urlencoded' action=\"", r);
            ap_rvputs(r, ap_escape_uri(r->pool, action), "\">\n", NULL);
            ap_rputs("<table><tr><td>Load factor:</td><td><input name='w_lf' id='w_lf' type=text ", r);
            ap_rprintf(r, "value='%.2f'></td></tr>\n", (float)(wsel->s->lbfactor)/100.0);
            ap_rputs("<tr><td>LB Set:</td><td><input name='w_ls' id='w_ls' type=text ", r);
            ap_rprintf(r, "value='%d'></td></tr>\n", wsel->s->lbset);
            ap_rputs("<tr><td>Route:</td><td><input name='w_wr' id='w_wr' type=text ", r);
            ap_rvputs(r, "value=\"", ap_escape_html(r->pool, wsel->s->route),
                      NULL);
            ap_rputs("\"></td></tr>\n", r);
            ap_rputs("<tr><td>Route Redirect:</td><td><input name='w_rr' id='w_rr' type=text ", r);
            ap_rvputs(r, "value=\"", ap_escape_html(r->pool, wsel->s->redirect),
                      NULL);
            ap_rputs("\"></td></tr>\n", r);
            ap_rputs("<tr><td>Status:</td>", r);
            ap_rputs("<td><table><tr>"
                     "<th>Ignore Errors</th>"
                     "<th>Draining Mode</th>"
                     "<th>Disabled</th>"
                     "<th>Hot Standby</th>"
                     "<th>Hot Spare</th>", r);
            if (hc_show_exprs_f) {
                ap_rputs("<th>HC Fail</th>", r);
            }
            ap_rputs("<th>Stopped</th></tr>\n<tr>", r);
            create_radio("w_status_I", (PROXY_WORKER_IS(wsel, PROXY_WORKER_IGNORE_ERRORS)), r);
            create_radio("w_status_N", (PROXY_WORKER_IS(wsel, PROXY_WORKER_DRAIN)), r);
            create_radio("w_status_D", (PROXY_WORKER_IS(wsel, PROXY_WORKER_DISABLED)), r);
            create_radio("w_status_H", (PROXY_WORKER_IS(wsel, PROXY_WORKER_HOT_STANDBY)), r);
            create_radio("w_status_R", (PROXY_WORKER_IS(wsel, PROXY_WORKER_HOT_SPARE)), r);
            if (hc_show_exprs_f) {
                create_radio("w_status_C", (PROXY_WORKER_IS(wsel, PROXY_WORKER_HC_FAIL)), r);
            }
            create_radio("w_status_S", (PROXY_WORKER_IS(wsel, PROXY_WORKER_STOPPED)), r);
            ap_rputs("</tr></table></td></tr>\n", r);
            if (hc_select_exprs_f) {
                proxy_hcmethods_t *method = proxy_hcmethods;
                ap_rputs("<tr><td colspan='2'>\n<table align='center'><tr><th>Health Check param</th><th>Value</th></tr>\n", r);
                ap_rputs("<tr><td>Method</td><td><select name='w_hm'>\n", r);
                for (; method->name; method++) {
                    if (method->implemented) {
                        ap_rprintf(r, "<option value='%s' %s >%s</option>\n",
                                method->name,
                                (wsel->s->method == method->method) ? "selected" : "",
                                method->name);
                    }
                }
                ap_rputs("</select>\n</td></tr>\n", r);
                ap_rputs("<tr><td>Expr</td><td><select name='w_he'>\n", r);
                hc_select_exprs_f(r, wsel->s->hcexpr);
                ap_rputs("</select>\n</td></tr>\n", r);
                ap_rprintf(r, "<tr><td>Interval (ms)</td><td><input name='w_hi' id='w_hi' type='text' "
                           "value='%" APR_TIME_T_FMT "'></td></tr>\n", apr_time_as_msec(wsel->s->interval));
                ap_rprintf(r, "<tr><td>Passes trigger</td><td><input name='w_hp' id='w_hp' type='text' "
                           "value='%d'></td></tr>\n", wsel->s->passes);
                ap_rprintf(r, "<tr><td>Fails trigger)</td><td><input name='w_hf' id='w_hf' type='text' "
                           "value='%d'></td></tr>\n", wsel->s->fails);
                ap_rprintf(r, "<tr><td>HC uri</td><td><input name='w_hu' id='w_hu' type='text' "
                           "value=\"%s\"></td></tr>\n", ap_escape_html(r->pool, wsel->s->hcuri));
                ap_rputs("</table>\n</td></tr>\n", r);
            }
            ap_rputs("<tr><td colspan='2'><input type=submit value='Submit'></td></tr>\n", r);
            ap_rvputs(r, "</table>\n<input type=hidden name='w' id='w' ",  NULL);
            ap_rvputs(r, "value=\"", ap_escape_uri(r->pool, wsel->s->name), "\">\n", NULL);
            ap_rvputs(r, "<input type=hidden name='b' id='b' ", NULL);
            ap_rvputs(r, "value=\"", ap_escape_html(r->pool, bsel->s->name + sizeof(BALANCER_PREFIX) - 1),
                      "\">\n", NULL);
            ap_rvputs(r, "<input type=hidden name='nonce' id='nonce' value='",
                      bsel->s->nonce, "'>\n", NULL);
            ap_rputs("</form>\n", r);
            ap_rputs("<hr />\n", r);
        } else if (bsel) {
            const apr_array_header_t *provs;
            const ap_list_provider_names_t *pname;
            int i;
            ap_rputs("<h3>Edit balancer settings for ", r);
            ap_rvputs(r, ap_escape_html(r->pool, bsel->s->name), "</h3>\n", NULL);
            ap_rputs("<form method='POST' enctype='application/x-www-form-urlencoded' action=\"", r);
            ap_rvputs(r, ap_escape_uri(r->pool, action), "\">\n", NULL);
            ap_rputs("<table>\n", r);
            provs = ap_list_provider_names(r->pool, PROXY_LBMETHOD, "0");
            if (provs) {
                ap_rputs("<tr><td>LBmethod:</td>", r);
                ap_rputs("<td>\n<select name='b_lbm' id='b_lbm'>", r);
                pname = (ap_list_provider_names_t *)provs->elts;
                for (i = 0; i < provs->nelts; i++, pname++) {
                    ap_rvputs(r,"<option value='", pname->provider_name, "'", NULL);
                    if (strcmp(pname->provider_name, bsel->s->lbpname) == 0)
                        ap_rputs(" selected ", r);
                    ap_rvputs(r, ">", pname->provider_name, "\n", NULL);
                }
                ap_rputs("</select>\n</td></tr>\n", r);
            }
            ap_rputs("<tr><td>Timeout:</td><td><input name='b_tmo' id='b_tmo' type=text ", r);
            ap_rprintf(r, "value='%" APR_TIME_T_FMT "'></td></tr>\n", apr_time_sec(bsel->s->timeout));
            ap_rputs("<tr><td>Failover Attempts:</td><td><input name='b_max' id='b_max' type=text ", r);
            ap_rprintf(r, "value='%d'></td></tr>\n", bsel->s->max_attempts);
            ap_rputs("<tr><td>Disable Failover:</td>", r);
            create_radio("b_sforce", bsel->s->sticky_force, r);
            ap_rputs("</tr>\n", r);
            ap_rputs("<tr><td>Sticky Session:</td><td><input name='b_ss' id='b_ss' size=64 type=text ", r);
            if (strcmp(bsel->s->sticky, bsel->s->sticky_path)) {
                ap_rvputs(r, "value =\"", ap_escape_html(r->pool, bsel->s->sticky), "|",
                          ap_escape_html(r->pool, bsel->s->sticky_path), NULL);
            }
            else {
                ap_rvputs(r, "value =\"", ap_escape_html(r->pool, bsel->s->sticky), NULL);
            }
            ap_rputs("\">&nbsp;&nbsp;&nbsp;&nbsp;(Use '-' to delete)</td></tr>\n", r);
            if (storage->num_free_slots(bsel->wslot) != 0) {
                ap_rputs("<tr><td>Add New Worker:</td><td><input name='b_nwrkr' id='b_nwrkr' size=32 type=text>"
                         "&nbsp;&nbsp;&nbsp;&nbsp;Are you sure? <input name='b_wyes' id='b_wyes' type=checkbox value='1'>"
                         "</td></tr>", r);
            }
            ap_rputs("<tr><td colspan=2><input type=submit value='Submit'></td></tr>\n", r);
            ap_rvputs(r, "</table>\n<input type=hidden name='b' id='b' ", NULL);
            ap_rvputs(r, "value=\"", ap_escape_html(r->pool, bsel->s->name + sizeof(BALANCER_PREFIX) - 1),
                      "\">\n", NULL);
            ap_rvputs(r, "<input type=hidden name='nonce' id='nonce' value='",
                      bsel->s->nonce, "'>\n", NULL);
            ap_rputs("</form>\n", r);
            ap_rputs("<hr />\n", r);
        }
        ap_rputs(ap_psignature("",r), r);
        ap_rputs("</body></html>\n", r);
        ap_rflush(r);
    }
}