1 /* Copyright 1999-2005 The Apache Software Foundation or its licensors, as
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 * @brief Proxy Extension Module for Apache
24 * @defgroup MOD_PROXY mod_proxy
25 * @ingroup APACHE_MODS
31 Also note numerous FIXMEs and CHECKMEs which should be eliminated.
33 This code is once again experimental!
37 1. Make it completely work (for FTP too)
41 Chuck Murcko <chuck@topsail.org> 02-06-01
47 #include "apr_hooks.h"
50 #include "apr_strings.h"
51 #include "apr_buckets.h"
53 #include "apr_network_io.h"
54 #include "apr_pools.h"
55 #include "apr_strings.h"
58 #include "apr_strmatch.h"
59 #include "apr_fnmatch.h"
60 #include "apr_reslist.h"
61 #define APR_WANT_STRFUNC
65 #include "http_config.h"
66 #include "ap_config.h"
67 #include "http_core.h"
68 #include "http_protocol.h"
69 #include "http_request.h"
70 #include "http_vhost.h"
71 #include "http_main.h"
73 #include "http_connection.h"
74 #include "util_filter.h"
75 #include "util_ebcdic.h"
76 #include "ap_provider.h"
78 #if APR_HAVE_NETINET_IN_H
79 #include <netinet/in.h>
81 #if APR_HAVE_ARPA_INET_H
82 #include <arpa/inet.h>
85 /* for proxy_canonenc() */
87 enc_path, enc_search, enc_user, enc_fpath, enc_parm
90 #if APR_CHARSET_EBCDIC
92 #else /*APR_CHARSET_EBCDIC*/
93 #define CRLF "\015\012"
94 #endif /*APR_CHARSET_EBCDIC*/
96 /* default Max-Forwards header setting */
97 #define DEFAULT_MAX_FORWARDS 10
99 /* static information about a remote proxy */
100 struct proxy_remote {
101 const char *scheme; /* the schemes handled by this proxy, or '*' */
102 const char *protocol; /* the scheme used to talk to this proxy */
103 const char *hostname; /* the hostname of this proxy */
104 apr_port_t port; /* the port for this proxy */
105 ap_regex_t *regexp; /* compiled regex (if any) for the remote */
106 int use_regex; /* simple boolean. True if we have a regex pattern */
114 struct dirconn_entry {
116 struct in_addr addr, mask;
117 struct apr_sockaddr_t *hostaddr;
118 int (*matcher) (struct dirconn_entry * This, request_rec *r);
121 struct noproxy_entry {
123 struct apr_sockaddr_t *addr;
126 typedef struct proxy_balancer proxy_balancer;
127 typedef struct proxy_worker proxy_worker;
128 typedef struct proxy_conn_pool proxy_conn_pool;
129 typedef struct proxy_balancer_method proxy_balancer_method;
132 apr_array_header_t *proxies;
133 apr_array_header_t *sec_proxy;
134 apr_array_header_t *aliases;
135 apr_array_header_t *noproxies;
136 apr_array_header_t *dirconn;
137 apr_array_header_t *allowed_connect_ports;
138 apr_array_header_t *workers;
139 apr_array_header_t *balancers;
140 proxy_worker *forward; /* forward proxy worker */
141 proxy_worker *reverse; /* reverse "module-driven" proxy worker */
142 const char *domain; /* domain name to use in absence of a domain name in the request */
143 int req; /* true if proxy requests are enabled */
150 } viaopt; /* how to deal with proxy Via: headers */
152 apr_size_t recv_buffer_size;
153 char recv_buffer_size_set;
154 apr_size_t io_buffer_size;
155 char io_buffer_size_set;
159 * the following setting masks the error page
160 * returned from the 'proxied server' and just
161 * forwards the status code upwards.
162 * This allows the main server (us) to generate
163 * the error page, (so it will look like a error
164 * returned from the rest of the system
167 int error_override_set;
169 int preserve_host_set;
170 apr_interval_time_t timeout;
176 } badopt; /* how to deal with bad headers */
178 /* putting new stuff on the end maximises binary back-compatibility.
179 * the strmatch_patterns are really a const just to have a
180 * case-independent strstr.
186 } proxy_status; /* Status display options */
187 char proxy_status_set;
188 apr_pool_t *pool; /* Pool used for allocating this struct */
193 const char *p; /* The path */
194 int p_is_fnmatch; /* Is this path an fnmatch candidate? */
195 ap_regex_t *r; /* Is this a regex? */
197 /* ProxyPassReverse and friends are documented as working inside
198 * <Location>. But in fact they never have done in the case of
199 * more than one <Location>, because the server_conf can't see it.
200 * We need to move them to the per-dir config.
201 * Discussed in February:
202 * http://marc.theaimsgroup.com/?l=apache-httpd-dev&m=110726027118798&w=2
204 apr_array_header_t *raliases;
205 apr_array_header_t* cookie_paths;
206 apr_array_header_t* cookie_domains;
207 const apr_strmatch_pattern* cookie_path_str;
208 const apr_strmatch_pattern* cookie_domain_str;
212 conn_rec *connection;
213 const char *hostname;
216 apr_pool_t *pool; /* Subpool used for creating socket */
217 apr_socket_t *sock; /* Connection socket */
218 apr_sockaddr_t *addr; /* Preparsed remote address info */
219 apr_uint32_t flags; /* Conection flags */
220 int close; /* Close 'this' connection */
221 int close_on_recycle; /* Close the connection when returning to pool */
222 proxy_worker *worker; /* Connection pool this connection belogns to */
223 void *data; /* per scheme connection data */
227 float cache_completion; /* completion percentage */
228 int content_length; /* length of the content */
231 /* Connection pool */
232 struct proxy_conn_pool {
233 apr_pool_t *pool; /* The pool used in constructor and destructor calls */
234 apr_sockaddr_t *addr; /* Preparsed remote address info */
236 apr_reslist_t *res; /* Connection resource list */
238 proxy_conn_rec *conn; /* Single connection for prefork mpm's */
241 /* woker status flags */
242 #define PROXY_WORKER_INITIALIZED 0x0001
243 #define PROXY_WORKER_IGNORE_ERRORS 0x0002
244 #define PROXY_WORKER_IN_SHUTDOWN 0x0010
245 #define PROXY_WORKER_DISABLED 0x0020
246 #define PROXY_WORKER_STOPPED 0x0040
247 #define PROXY_WORKER_IN_ERROR 0x0080
249 #define PROXY_WORKER_IS_USABLE(f) (!((f)->s->status & 0x00F0))
251 /* default worker retry timeout in seconds */
252 #define PROXY_WORKER_DEFAULT_RETRY 60
253 #define PROXY_WORKER_MAX_ROUTE_SIZ 63
255 /* Runtime worker status informations. Shared in scoreboard */
258 apr_time_t error_time; /* time of the last error */
259 int retries; /* number of retries on this worker */
260 int lbstatus; /* Current lbstatus */
261 int lbfactor; /* dynamic lbfactor */
262 apr_off_t transferred;/* Number of bytes transferred to remote */
263 apr_off_t read; /* Number of bytes read from remote */
264 apr_size_t elected; /* Number of times the worker was elected */
265 char route[PROXY_WORKER_MAX_ROUTE_SIZ+1];
266 char redirect[PROXY_WORKER_MAX_ROUTE_SIZ+1];
267 void *context; /* general purpose storage */
270 /* Worker configuration */
271 struct proxy_worker {
272 int id; /* scoreboard id */
273 apr_interval_time_t retry; /* retry interval */
274 int lbfactor; /* initial load balancing factor */
276 const char *scheme; /* scheme to use ajp|http|https */
277 const char *hostname; /* remote backend address */
278 const char *route; /* balancing route */
279 const char *redirect; /* temporary balancing redirection route */
280 int status; /* temporary worker status */
282 int min; /* Desired minimum number of available connections */
283 int smax; /* Soft maximum on the total number of connections */
284 int hmax; /* Hard maximum on the total number of connections */
285 apr_interval_time_t ttl; /* maximum amount of time in seconds a connection
286 * may be available while exceeding the soft limit */
287 apr_interval_time_t timeout; /* connection timeout */
289 apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */
291 apr_size_t recv_buffer_size;
292 char recv_buffer_size_set;
293 apr_size_t io_buffer_size;
294 char io_buffer_size_set;
297 proxy_conn_pool *cp; /* Connection pool to use */
298 proxy_worker_stat *s; /* Shared data */
299 void *opaque; /* per scheme worker data */
300 int is_address_reusable;
302 apr_thread_mutex_t *mutex; /* Thread lock for updating address cache */
304 void *context; /* general purpose storage */
307 struct proxy_balancer {
308 apr_array_header_t *workers; /* array of proxy_workers */
309 const char *name; /* name of the load balancer */
310 const char *sticky; /* sticky session identifier */
311 int sticky_force; /* Disable failover for sticky sessions */
312 apr_interval_time_t timeout; /* Timeout for waiting on free connection */
313 int max_attempts; /* Number of attempts before failing */
314 char max_attempts_set;
315 proxy_balancer_method *lbmethod;
317 /* XXX: Perhaps we will need the proc mutex too.
318 * Altrough we are only using arithmetic operations
319 * it may lead to a incorrect calculations.
320 * For now use only the thread mutex.
323 apr_thread_mutex_t *mutex; /* Thread lock for updating lb params */
325 void *context; /* general purpose storage */
328 struct proxy_balancer_method {
329 const char *name; /* name of the load balancer method*/
330 proxy_worker *(*finder)(proxy_balancer *balancer,
332 void *context; /* general purpose storage */
336 #define PROXY_THREAD_LOCK(x) apr_thread_mutex_lock((x)->mutex)
337 #define PROXY_THREAD_UNLOCK(x) apr_thread_mutex_unlock((x)->mutex)
339 #define PROXY_THREAD_LOCK(x) APR_SUCCESS
340 #define PROXY_THREAD_UNLOCK(x) APR_SUCCESS
345 /* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
346 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
349 #define PROXY_DECLARE(type) type
350 #define PROXY_DECLARE_NONSTD(type) type
351 #define PROXY_DECLARE_DATA
352 #elif defined(PROXY_DECLARE_STATIC)
353 #define PROXY_DECLARE(type) type __stdcall
354 #define PROXY_DECLARE_NONSTD(type) type
355 #define PROXY_DECLARE_DATA
356 #elif defined(PROXY_DECLARE_EXPORT)
357 #define PROXY_DECLARE(type) __declspec(dllexport) type __stdcall
358 #define PROXY_DECLARE_NONSTD(type) __declspec(dllexport) type
359 #define PROXY_DECLARE_DATA __declspec(dllexport)
361 #define PROXY_DECLARE(type) __declspec(dllimport) type __stdcall
362 #define PROXY_DECLARE_NONSTD(type) __declspec(dllimport) type
363 #define PROXY_DECLARE_DATA __declspec(dllimport)
367 * Hook an optional proxy hook. Unlike static hooks, this uses a macro
368 * instead of a function.
370 #define PROXY_OPTIONAL_HOOK(name,fn,pre,succ,order) \
371 APR_OPTIONAL_HOOK(proxy,name,fn,pre,succ,order)
373 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r,
374 proxy_worker *worker, proxy_server_conf *conf, char *url,
375 const char *proxyhost, apr_port_t proxyport))
376 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r,
379 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr))
380 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r))
384 * It will return the most suitable worker at the moment
385 * and coresponding balancer.
386 * The url is rewritten from balancer://cluster/uri to scheme://host:port/uri
387 * and then the scheme_handler is called.
390 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, pre_request, (proxy_worker **worker,
391 proxy_balancer **balancer,
393 proxy_server_conf *conf, char **url))
396 * It is called after request for updating runtime balancer status.
398 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, post_request, (proxy_worker *worker,
399 proxy_balancer *balancer, request_rec *r,
400 proxy_server_conf *conf))
403 * request status hook
404 * It is called after all proxy processing has been done. This gives other
405 * modules a chance to create default content on failure, for example
407 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, request_status,
408 (int *status, request_rec *r))
412 PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r);
413 PROXY_DECLARE(int) ap_proxy_hex2c(const char *x);
414 PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x);
415 PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
416 int forcedec, int proxyreq);
417 PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
418 char **passwordp, char **hostp, apr_port_t *port);
419 PROXY_DECLARE(const char *)ap_proxy_date_canon(apr_pool_t *p, const char *x);
420 PROXY_DECLARE(int) ap_proxy_liststr(const char *list, const char *val);
421 PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val);
422 PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x);
423 PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y);
424 PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message);
425 PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p);
426 PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p);
427 PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p);
428 PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p);
429 PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
430 PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r);
431 PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos);
432 PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key);
433 /* DEPRECATED (will be replaced with ap_proxy_connect_backend */
434 PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, apr_sockaddr_t *, const char *, proxy_server_conf *, server_rec *, apr_pool_t *);
435 PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
436 PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
437 PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c);
438 PROXY_DECLARE(const char *) ap_proxy_ssl_val(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *var);
440 /* Header mapping functions, and a typedef of their signature */
441 PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *url);
442 PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *str);
445 typedef const char *(*ap_proxy_header_reverse_map_fn)(request_rec *,
446 proxy_dir_conf *, const char *);
447 #elif defined(PROXY_DECLARE_STATIC)
448 typedef const char *(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
449 proxy_dir_conf *, const char *);
450 #elif defined(PROXY_DECLARE_EXPORT)
451 typedef __declspec(dllexport) const char *
452 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
453 proxy_dir_conf *, const char *);
455 typedef __declspec(dllimport) const char *
456 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
457 proxy_dir_conf *, const char *);
461 /* Connection pool API */
463 * Get the worker from proxy configuration
464 * @param p memory pool used for finding worker
465 * @param conf current proxy server configuration
466 * @param url url to find the worker from
467 * @return proxy_worker or NULL if not found
469 PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
470 proxy_server_conf *conf,
473 * Add the worker to proxy configuration
474 * @param worker the new worker
475 * @param p memory pool to allocate worker from
476 * @param conf current proxy server configuration
477 * @param url url containing worker name
478 * @return error message or NULL if successfull
480 PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,
482 proxy_server_conf *conf,
487 * @param p memory pool to allocate worker from
490 PROXY_DECLARE(proxy_worker *) ap_proxy_create_worker(apr_pool_t *p);
493 * Initize the worker's shared data
494 * @param conf current proxy server configuration
495 * @param worker worker to initialize
496 * @param s current server record
497 * @param worker worker to initialize
499 PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
500 proxy_worker *worker,
506 * @param worker worker to initialize
507 * @param s current server record
508 * @return APR_SUCCESS or error code
510 PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker,
513 * Get the balancer from proxy configuration
514 * @param p memory pool used for finding balancer
515 * @param conf current proxy server configuration
516 * @param url url to find the worker from. Has to have balancer:// prefix
517 * @return proxy_balancer or NULL if not found
519 PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
520 proxy_server_conf *conf,
523 * Add the balancer to proxy configuration
524 * @param balancer the new balancer
525 * @param p memory pool to allocate balancer from
526 * @param conf current proxy server configuration
527 * @param url url containing balancer name
528 * @return error message or NULL if successfull
530 PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer,
532 proxy_server_conf *conf,
536 * Add the worker to the balancer
537 * @param pool memory pool for adding worker
538 * @param balancer balancer to add to
539 * @param balancer worker to add
540 * @note Single worker can be added to multiple balancers.
542 PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(apr_pool_t *pool,
543 proxy_balancer *balancer,
544 proxy_worker *worker);
546 * Get the most suitable worker and(or) balancer for the request
547 * @param worker worker used for processing request
548 * @param balancer balancer used for processing request
549 * @param r current request
550 * @param conf current proxy server configuration
551 * @param url request url that balancer can rewrite.
552 * @return OK or HTTP_XXX error
553 * @note It calls balancer pre_request hook if the url starts with balancer://
554 * The balancer then rewrites the url to particular worker, like http://host:port
556 PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
557 proxy_balancer **balancer,
559 proxy_server_conf *conf,
562 * Post request worker and balancer cleanup
563 * @param worker worker used for processing request
564 * @param balancer balancer used for processing request
565 * @param r current request
566 * @param conf current proxy server configuration
567 * @return OK or HTTP_XXX error
568 * @note When ever the pre_request is called, the post_request has to be
571 PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
572 proxy_balancer *balancer,
574 proxy_server_conf *conf);
577 * Request status function
578 * @param status status of proxy request
579 * @return OK or DECLINED
581 PROXY_DECLARE(int) ap_proxy_request_status(int *status, request_rec *r);
584 * Deternime backend hostname and port
585 * @param p memory pool used for processing
586 * @param r current request
587 * @param conf current proxy server configuration
588 * @param worker worker used for processing request
589 * @param conn proxy connection struct
590 * @param uri processed uri
591 * @param url request url
592 * @param proxyname are we connecting directly or via s proxy
593 * @param proxyport proxy host port
594 * @param server_portstr Via headers server port
595 * @param server_portstr_size size of the server_portstr buffer
596 * @return OK or HTTP_XXX error
598 PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
599 proxy_server_conf *conf,
600 proxy_worker *worker,
601 proxy_conn_rec *conn,
604 const char *proxyname,
605 apr_port_t proxyport,
606 char *server_portstr,
607 int server_portstr_size);
609 * Mark a worker for retry
610 * @param proxy_function calling proxy scheme (http, ajp, ...)
611 * @param conf current proxy server configuration
612 * @param worker worker used for retrying
613 * @param s current server record
614 * @return OK if marked for retry, DECLINED otherwise
615 * @note Worker will be marker for retry if the time of the last retry
616 * has been ellapsed. In case there is no retry option set, defaults to
617 * number_of_retries seconds.
619 PROXY_DECLARE(int) ap_proxy_retry_worker(const char *proxy_function,
620 proxy_worker *worker,
623 * Acquire a connection from workers connection pool
624 * @param proxy_function calling proxy scheme (http, ajp, ...)
625 * @param conn acquired connection
626 * @param worker worker used for obtaining connection
627 * @param s current server record
628 * @return OK or HTTP_XXX error
629 * @note If the number of connections is exhaused the function will
630 * block untill the timeout is reached.
632 PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
633 proxy_conn_rec **conn,
634 proxy_worker *worker,
637 * Release a connection back to worker connection pool
638 * @param proxy_function calling proxy scheme (http, ajp, ...)
639 * @param conn acquired connection
640 * @param s current server record
641 * @return OK or HTTP_XXX error
642 * @note The connection will be closed if conn->close_on_release is set
644 PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
645 proxy_conn_rec *conn,
648 * Make a connection to the backend
649 * @param proxy_function calling proxy scheme (http, ajp, ...)
650 * @param conn acquired connection
651 * @param worker connection worker
652 * @param s current server record
653 * @return OK or HTTP_XXX error
654 * @note In case the socket already exists for conn, just check the link
657 PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
658 proxy_conn_rec *conn,
659 proxy_worker *worker,
662 * Make a connection record for backend connection
663 * @param proxy_function calling proxy scheme (http, ajp, ...)
664 * @param conn acquired connection
665 * @param c client connection record
666 * @param s current server record
667 * @return OK or HTTP_XXX error
669 PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
670 proxy_conn_rec *conn,
671 conn_rec *c, server_rec *s);
673 * Signal the upstream chain that the connection to the backend broke in the
674 * middle of the response. This is done by sending an error bucket with
675 * status HTTP_BAD_GATEWAY and an EOS bucket up the filter chain.
676 * @param r current request record of client request
677 * @param brigade The brigade that is sent through the output filter chain
679 PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
680 apr_bucket_brigade *brigade);
683 #if MODULE_MAGIC_NUMBER_MAJOR > 20020903
684 #define PROXY_HAS_SCOREBOARD 1
686 #define PROXY_HAS_SCOREBOARD 0
689 #define PROXY_LBMETHOD "proxylbmethod"
691 /* The number of dynamic workers that can be added when reconfiguring.
692 * If this limit is reached you must stop and restart the server.
694 #define PROXY_DYNAMIC_BALANCER_LIMIT 16
696 * Calculate number of maximum number of workers in scoreboard.
697 * @return number of workers to allocate in the scoreboard
699 int ap_proxy_lb_workers(void);
702 extern module PROXY_DECLARE_DATA proxy_module;
704 extern int PROXY_DECLARE_DATA proxy_lb_workers;
706 #endif /*MOD_PROXY_H*/