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.
21 * Main include file for the Apache proxy
26 Also note numerous FIXMEs and CHECKMEs which should be eliminated.
28 This code is once again experimental!
32 1. Make it completely work (for FTP too)
36 Chuck Murcko <chuck@topsail.org> 02-06-01
42 #include "apr_hooks.h"
45 #include "apr_strings.h"
46 #include "apr_buckets.h"
48 #include "apr_network_io.h"
49 #include "apr_pools.h"
50 #include "apr_strings.h"
53 #include "apr_strmatch.h"
54 #include "apr_fnmatch.h"
55 #include "apr_reslist.h"
56 #define APR_WANT_STRFUNC
60 #include "http_config.h"
61 #include "ap_config.h"
62 #include "http_core.h"
63 #include "http_protocol.h"
64 #include "http_request.h"
65 #include "http_vhost.h"
66 #include "http_main.h"
68 #include "http_connection.h"
69 #include "util_filter.h"
70 #include "util_ebcdic.h"
72 #if APR_HAVE_NETINET_IN_H
73 #include <netinet/in.h>
75 #if APR_HAVE_ARPA_INET_H
76 #include <arpa/inet.h>
79 /* for proxy_canonenc() */
81 enc_path, enc_search, enc_user, enc_fpath, enc_parm
84 #if APR_CHARSET_EBCDIC
86 #else /*APR_CHARSET_EBCDIC*/
87 #define CRLF "\015\012"
88 #endif /*APR_CHARSET_EBCDIC*/
90 /* default Max-Forwards header setting */
91 #define DEFAULT_MAX_FORWARDS 10
93 /* static information about a remote proxy */
95 const char *scheme; /* the schemes handled by this proxy, or '*' */
96 const char *protocol; /* the scheme used to talk to this proxy */
97 const char *hostname; /* the hostname of this proxy */
98 apr_port_t port; /* the port for this proxy */
99 ap_regex_t *regexp; /* compiled regex (if any) for the remote */
100 int use_regex; /* simple boolean. True if we have a regex pattern */
108 struct dirconn_entry {
110 struct in_addr addr, mask;
111 struct apr_sockaddr_t *hostaddr;
112 int (*matcher) (struct dirconn_entry * This, request_rec *r);
115 struct noproxy_entry {
117 struct apr_sockaddr_t *addr;
120 typedef struct proxy_balancer proxy_balancer;
121 typedef struct proxy_worker proxy_worker;
122 typedef struct proxy_conn_pool proxy_conn_pool;
123 typedef struct proxy_balancer_method proxy_balancer_method;
126 apr_array_header_t *proxies;
127 apr_array_header_t *sec_proxy;
128 apr_array_header_t *aliases;
129 apr_array_header_t *noproxies;
130 apr_array_header_t *dirconn;
131 apr_array_header_t *allowed_connect_ports;
132 apr_array_header_t *workers;
133 apr_array_header_t *balancers;
134 proxy_worker *forward; /* forward proxy worker */
135 proxy_worker *reverse; /* reverse "module-driven" proxy worker */
136 const char *domain; /* domain name to use in absence of a domain name in the request */
137 int req; /* true if proxy requests are enabled */
144 } viaopt; /* how to deal with proxy Via: headers */
146 apr_size_t recv_buffer_size;
147 char recv_buffer_size_set;
148 apr_size_t io_buffer_size;
149 char io_buffer_size_set;
153 * the following setting masks the error page
154 * returned from the 'proxied server' and just
155 * forwards the status code upwards.
156 * This allows the main server (us) to generate
157 * the error page, (so it will look like a error
158 * returned from the rest of the system
161 int error_override_set;
163 int preserve_host_set;
164 apr_interval_time_t timeout;
170 } badopt; /* how to deal with bad headers */
172 /* putting new stuff on the end maximises binary back-compatibility.
173 * the strmatch_patterns are really a const just to have a
174 * case-independent strstr.
180 } proxy_status; /* Status display options */
181 char proxy_status_set;
182 apr_pool_t *pool; /* Pool used for allocating this struct */
183 apr_array_header_t *lbmethods;
188 const char *p; /* The path */
189 int p_is_fnmatch; /* Is this path an fnmatch candidate? */
190 ap_regex_t *r; /* Is this a regex? */
192 /* ProxyPassReverse and friends are documented as working inside
193 * <Location>. But in fact they never have done in the case of
194 * more than one <Location>, because the server_conf can't see it.
195 * We need to move them to the per-dir config.
196 * Discussed in February:
197 * http://marc.theaimsgroup.com/?l=apache-httpd-dev&m=110726027118798&w=2
199 apr_array_header_t *raliases;
200 apr_array_header_t* cookie_paths;
201 apr_array_header_t* cookie_domains;
202 const apr_strmatch_pattern* cookie_path_str;
203 const apr_strmatch_pattern* cookie_domain_str;
207 conn_rec *connection;
208 const char *hostname;
211 apr_pool_t *pool; /* Subpool used for creating socket */
212 apr_socket_t *sock; /* Connection socket */
213 apr_sockaddr_t *addr; /* Preparsed remote address info */
214 apr_uint32_t flags; /* Conection flags */
215 int close; /* Close 'this' connection */
216 int close_on_recycle; /* Close the connection when returning to pool */
217 proxy_worker *worker; /* Connection pool this connection belogns to */
218 void *data; /* per scheme connection data */
222 float cache_completion; /* completion percentage */
223 int content_length; /* length of the content */
226 /* Connection pool */
227 struct proxy_conn_pool {
228 apr_pool_t *pool; /* The pool used in constructor and destructor calls */
229 apr_sockaddr_t *addr; /* Preparsed remote address info */
231 apr_reslist_t *res; /* Connection resource list */
233 proxy_conn_rec *conn; /* Single connection for prefork mpm's */
236 /* woker status flags */
237 #define PROXY_WORKER_INITIALIZED 0x0001
238 #define PROXY_WORKER_IGNORE_ERRORS 0x0002
239 #define PROXY_WORKER_IN_SHUTDOWN 0x0010
240 #define PROXY_WORKER_DISABLED 0x0020
241 #define PROXY_WORKER_STOPPED 0x0040
242 #define PROXY_WORKER_IN_ERROR 0x0080
244 #define PROXY_WORKER_IS_USABLE(f) (!((f)->s->status & 0x00F0))
246 /* default worker retry timeout in seconds */
247 #define PROXY_WORKER_DEFAULT_RETRY 60
248 #define PROXY_WORKER_MAX_ROUTE_SIZ 63
250 /* Runtime worker status informations. Shared in scoreboard */
253 apr_time_t error_time; /* time of the last error */
254 int retries; /* number of retries on this worker */
255 int lbstatus; /* Current lbstatus */
256 int lbfactor; /* dynamic lbfactor */
257 apr_off_t transferred;/* Number of bytes transferred to remote */
258 apr_off_t read; /* Number of bytes read from remote */
259 apr_size_t elected; /* Number of times the worker was elected */
260 char route[PROXY_WORKER_MAX_ROUTE_SIZ+1];
261 char redirect[PROXY_WORKER_MAX_ROUTE_SIZ+1];
262 void *context; /* general purpose storage */
265 /* Worker configuration */
266 struct proxy_worker {
267 int id; /* scoreboard id */
268 apr_interval_time_t retry; /* retry interval */
269 int lbfactor; /* initial load balancing factor */
271 const char *scheme; /* scheme to use ajp|http|https */
272 const char *hostname; /* remote backend address */
273 const char *route; /* balancing route */
274 const char *redirect; /* temporary balancing redirection route */
275 int status; /* temporary worker status */
277 int min; /* Desired minimum number of available connections */
278 int smax; /* Soft maximum on the total number of connections */
279 int hmax; /* Hard maximum on the total number of connections */
280 apr_interval_time_t ttl; /* maximum amount of time in seconds a connection
281 * may be available while exceeding the soft limit */
282 apr_interval_time_t timeout; /* connection timeout */
284 apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */
286 apr_size_t recv_buffer_size;
287 char recv_buffer_size_set;
288 apr_size_t io_buffer_size;
289 char io_buffer_size_set;
292 proxy_conn_pool *cp; /* Connection pool to use */
293 proxy_worker_stat *s; /* Shared data */
294 void *opaque; /* per scheme worker data */
295 int is_address_reusable;
297 apr_thread_mutex_t *mutex; /* Thread lock for updating address cache */
299 void *context; /* general purpose storage */
302 struct proxy_balancer {
303 apr_array_header_t *workers; /* array of proxy_workers */
304 const char *name; /* name of the load balancer */
305 const char *sticky; /* sticky session identifier */
306 int sticky_force; /* Disable failover for sticky sessions */
307 apr_interval_time_t timeout; /* Timeout for waiting on free connection */
308 int max_attempts; /* Number of attempts before failing */
309 char max_attempts_set;
310 proxy_balancer_method *lbmethod;
312 /* XXX: Perhaps we will need the proc mutex too.
313 * Altrough we are only using arithmetic operations
314 * it may lead to a incorrect calculations.
315 * For now use only the thread mutex.
318 apr_thread_mutex_t *mutex; /* Thread lock for updating lb params */
320 void *context; /* general purpose storage */
323 struct proxy_balancer_method {
324 const char *name; /* name of the load balancer method*/
325 proxy_worker *(*finder)(proxy_balancer *balancer,
327 void *context; /* general purpose storage */
331 #define PROXY_THREAD_LOCK(x) apr_thread_mutex_lock((x)->mutex)
332 #define PROXY_THREAD_UNLOCK(x) apr_thread_mutex_unlock((x)->mutex)
334 #define PROXY_THREAD_LOCK(x) APR_SUCCESS
335 #define PROXY_THREAD_UNLOCK(x) APR_SUCCESS
340 /* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
341 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
344 #define PROXY_DECLARE(type) type
345 #define PROXY_DECLARE_NONSTD(type) type
346 #define PROXY_DECLARE_DATA
347 #elif defined(PROXY_DECLARE_STATIC)
348 #define PROXY_DECLARE(type) type __stdcall
349 #define PROXY_DECLARE_NONSTD(type) type
350 #define PROXY_DECLARE_DATA
351 #elif defined(PROXY_DECLARE_EXPORT)
352 #define PROXY_DECLARE(type) __declspec(dllexport) type __stdcall
353 #define PROXY_DECLARE_NONSTD(type) __declspec(dllexport) type
354 #define PROXY_DECLARE_DATA __declspec(dllexport)
356 #define PROXY_DECLARE(type) __declspec(dllimport) type __stdcall
357 #define PROXY_DECLARE_NONSTD(type) __declspec(dllimport) type
358 #define PROXY_DECLARE_DATA __declspec(dllimport)
362 * Hook an optional proxy hook. Unlike static hooks, this uses a macro
363 * instead of a function.
365 #define PROXY_OPTIONAL_HOOK(name,fn,pre,succ,order) \
366 APR_OPTIONAL_HOOK(proxy,name,fn,pre,succ,order)
368 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r,
369 proxy_worker *worker, proxy_server_conf *conf, char *url,
370 const char *proxyhost, apr_port_t proxyport))
371 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r,
374 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr))
375 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r))
378 * Useful hook run within the create per-server phase which
379 * adds the required lbmethod structs, so they exist at
382 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, load_lbmethods,
383 (proxy_server_conf *conf))
387 * It will return the most suitable worker at the moment
388 * and coresponding balancer.
389 * The url is rewritten from balancer://cluster/uri to scheme://host:port/uri
390 * and then the scheme_handler is called.
393 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, pre_request, (proxy_worker **worker,
394 proxy_balancer **balancer,
396 proxy_server_conf *conf, char **url))
399 * It is called after request for updating runtime balancer status.
401 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, post_request, (proxy_worker *worker,
402 proxy_balancer *balancer, request_rec *r,
403 proxy_server_conf *conf))
406 * request status hook
407 * It is called after all proxy processing has been done. This gives other
408 * modules a chance to create default content on failure, for example
410 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, request_status,
411 (int *status, request_rec *r))
415 PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r);
416 PROXY_DECLARE(int) ap_proxy_hex2c(const char *x);
417 PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x);
418 PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
419 int forcedec, int proxyreq);
420 PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
421 char **passwordp, char **hostp, apr_port_t *port);
422 PROXY_DECLARE(const char *)ap_proxy_date_canon(apr_pool_t *p, const char *x);
423 PROXY_DECLARE(int) ap_proxy_liststr(const char *list, const char *val);
424 PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val);
425 PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x);
426 PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y);
427 PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message);
428 PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p);
429 PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p);
430 PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p);
431 PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p);
432 PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
433 PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r);
434 PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos);
435 PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key);
436 /* DEPRECATED (will be replaced with ap_proxy_connect_backend */
437 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 *);
438 PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
439 PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
440 PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c);
441 PROXY_DECLARE(const char *) ap_proxy_ssl_val(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *var);
443 /* Header mapping functions, and a typedef of their signature */
444 PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *url);
445 PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, proxy_dir_conf *conf, const char *str);
448 typedef const char *(*ap_proxy_header_reverse_map_fn)(request_rec *,
449 proxy_dir_conf *, const char *);
450 #elif defined(PROXY_DECLARE_STATIC)
451 typedef const char *(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
452 proxy_dir_conf *, const char *);
453 #elif defined(PROXY_DECLARE_EXPORT)
454 typedef __declspec(dllexport) const char *
455 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
456 proxy_dir_conf *, const char *);
458 typedef __declspec(dllimport) const char *
459 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
460 proxy_dir_conf *, const char *);
464 /* Connection pool API */
466 * Get the worker from proxy configuration
467 * @param p memory pool used for finding worker
468 * @param conf current proxy server configuration
469 * @param url url to find the worker from
470 * @return proxy_worker or NULL if not found
472 PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
473 proxy_server_conf *conf,
476 * Add the worker to proxy configuration
477 * @param worker the new worker
478 * @param p memory pool to allocate worker from
479 * @param conf current proxy server configuration
480 * @param url url containing worker name
481 * @return error message or NULL if successfull
483 PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,
485 proxy_server_conf *conf,
490 * @param p memory pool to allocate worker from
493 PROXY_DECLARE(proxy_worker *) ap_proxy_create_worker(apr_pool_t *p);
496 * Initize the worker's shared data
497 * @param conf current proxy server configuration
498 * @param worker worker to initialize
499 * @param s current server record
500 * @param worker worker to initialize
502 PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
503 proxy_worker *worker,
509 * @param worker worker to initialize
510 * @param s current server record
511 * @return APR_SUCCESS or error code
513 PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker,
516 * Get the balancer from proxy configuration
517 * @param p memory pool used for finding balancer
518 * @param conf current proxy server configuration
519 * @param url url to find the worker from. Has to have balancer:// prefix
520 * @return proxy_balancer or NULL if not found
522 PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
523 proxy_server_conf *conf,
526 * Add the balancer to proxy configuration
527 * @param balancer the new balancer
528 * @param p memory pool to allocate balancer from
529 * @param conf current proxy server configuration
530 * @param url url containing balancer name
531 * @return error message or NULL if successfull
533 PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer,
535 proxy_server_conf *conf,
539 * Add the worker to the balancer
540 * @param pool memory pool for adding worker
541 * @param balancer balancer to add to
542 * @param balancer worker to add
543 * @note Single worker can be added to multiple balancers.
545 PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(apr_pool_t *pool,
546 proxy_balancer *balancer,
547 proxy_worker *worker);
549 * Get the most suitable worker and(or) balancer for the request
550 * @param worker worker used for processing request
551 * @param balancer balancer used for processing request
552 * @param r current request
553 * @param conf current proxy server configuration
554 * @param url request url that balancer can rewrite.
555 * @return OK or HTTP_XXX error
556 * @note It calls balancer pre_request hook if the url starts with balancer://
557 * The balancer then rewrites the url to particular worker, like http://host:port
559 PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
560 proxy_balancer **balancer,
562 proxy_server_conf *conf,
565 * Post request worker and balancer cleanup
566 * @param worker worker used for processing request
567 * @param balancer balancer used for processing request
568 * @param r current request
569 * @param conf current proxy server configuration
570 * @return OK or HTTP_XXX error
571 * @note When ever the pre_request is called, the post_request has to be
574 PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
575 proxy_balancer *balancer,
577 proxy_server_conf *conf);
580 * Request status function
581 * @param status status of proxy request
582 * @return OK or DECLINED
584 PROXY_DECLARE(int) ap_proxy_request_status(int *status, request_rec *r);
587 * Deternime backend hostname and port
588 * @param p memory pool used for processing
589 * @param r current request
590 * @param conf current proxy server configuration
591 * @param worker worker used for processing request
592 * @param conn proxy connection struct
593 * @param uri processed uri
594 * @param url request url
595 * @param proxyname are we connecting directly or via s proxy
596 * @param proxyport proxy host port
597 * @param server_portstr Via headers server port
598 * @param server_portstr_size size of the server_portstr buffer
599 * @return OK or HTTP_XXX error
601 PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
602 proxy_server_conf *conf,
603 proxy_worker *worker,
604 proxy_conn_rec *conn,
607 const char *proxyname,
608 apr_port_t proxyport,
609 char *server_portstr,
610 int server_portstr_size);
612 * Mark a worker for retry
613 * @param proxy_function calling proxy scheme (http, ajp, ...)
614 * @param conf current proxy server configuration
615 * @param worker worker used for retrying
616 * @param s current server record
617 * @return OK if marked for retry, DECLINED otherwise
618 * @note Worker will be marker for retry if the time of the last retry
619 * has been ellapsed. In case there is no retry option set, defaults to
620 * number_of_retries seconds.
622 PROXY_DECLARE(int) ap_proxy_retry_worker(const char *proxy_function,
623 proxy_worker *worker,
626 * Acquire a connection from workers connection pool
627 * @param proxy_function calling proxy scheme (http, ajp, ...)
628 * @param conn acquired connection
629 * @param worker worker used for obtaining connection
630 * @param s current server record
631 * @return OK or HTTP_XXX error
632 * @note If the number of connections is exhaused the function will
633 * block untill the timeout is reached.
635 PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
636 proxy_conn_rec **conn,
637 proxy_worker *worker,
640 * Release a connection back to worker connection pool
641 * @param proxy_function calling proxy scheme (http, ajp, ...)
642 * @param conn acquired connection
643 * @param s current server record
644 * @return OK or HTTP_XXX error
645 * @note The connection will be closed if conn->close_on_release is set
647 PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
648 proxy_conn_rec *conn,
651 * Make a connection to the backend
652 * @param proxy_function calling proxy scheme (http, ajp, ...)
653 * @param conn acquired connection
654 * @param worker connection worker
655 * @param s current server record
656 * @return OK or HTTP_XXX error
657 * @note In case the socket already exists for conn, just check the link
660 PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
661 proxy_conn_rec *conn,
662 proxy_worker *worker,
665 * Make a connection record for backend connection
666 * @param proxy_function calling proxy scheme (http, ajp, ...)
667 * @param conn acquired connection
668 * @param c client connection record
669 * @param s current server record
670 * @return OK or HTTP_XXX error
672 PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
673 proxy_conn_rec *conn,
674 conn_rec *c, server_rec *s);
677 #if MODULE_MAGIC_NUMBER_MAJOR > 20020903
678 #define PROXY_HAS_SCOREBOARD 1
680 #define PROXY_HAS_SCOREBOARD 0
683 /* The number of dynamic workers that can be added when reconfiguring.
684 * If this limit is reached you must stop and restart the server.
686 #define PROXY_DYNAMIC_BALANCER_LIMIT 16
688 * Calculate number of maximum number of workers in scoreboard.
689 * @return number of workers to allocate in the scoreboard
691 int ap_proxy_lb_workers(void);
694 extern module PROXY_DECLARE_DATA proxy_module;
696 extern int PROXY_DECLARE_DATA proxy_lb_workers;
698 #endif /*MOD_PROXY_H*/