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;
125 apr_array_header_t *proxies;
126 apr_array_header_t *sec_proxy;
127 apr_array_header_t *aliases;
128 apr_array_header_t *raliases;
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.
176 apr_array_header_t* cookie_paths;
177 apr_array_header_t* cookie_domains;
178 const apr_strmatch_pattern* cookie_path_str;
179 const apr_strmatch_pattern* cookie_domain_str;
184 } proxy_status; /* Status display options */
185 char proxy_status_set;
186 apr_pool_t *pool; /* Pool used for allocating this struct */
191 const char *p; /* The path */
192 int p_is_fnmatch; /* Is this path an fnmatch candidate? */
193 ap_regex_t *r; /* Is this a regex? */
197 conn_rec *connection;
198 const char *hostname;
201 apr_pool_t *pool; /* Subpool used for creating socket */
202 apr_socket_t *sock; /* Connection socket */
203 apr_sockaddr_t *addr; /* Preparsed remote address info */
204 apr_uint32_t flags; /* Conection flags */
205 int close; /* Close 'this' connection */
206 int close_on_recycle; /* Close the connection when returning to pool */
207 proxy_worker *worker; /* Connection pool this connection belogns to */
208 void *data; /* per scheme connection data */
212 float cache_completion; /* completion percentage */
213 int content_length; /* length of the content */
216 /* Connection pool */
217 struct proxy_conn_pool {
218 apr_pool_t *pool; /* The pool used in constructor and destructor calls */
219 apr_sockaddr_t *addr; /* Preparsed remote address info */
221 apr_reslist_t *res; /* Connection resource list */
223 proxy_conn_rec *conn; /* Single connection for prefork mpm's */
226 /* woker status flags */
227 #define PROXY_WORKER_INITIALIZED 0x0001
228 #define PROXY_WORKER_IGNORE_ERRORS 0x0002
229 #define PROXY_WORKER_IN_SHUTDOWN 0x0010
230 #define PROXY_WORKER_DISABLED 0x0020
231 #define PROXY_WORKER_IN_ERROR 0x0040
233 #define PROXY_WORKER_IS_USABLE(f) (!((f)->s->status & 0x00F0))
235 /* default worker retry timeout in seconds */
236 #define PROXY_WORKER_DEFAULT_RETRY 60
237 #define PROXY_WORKER_MAX_ROUTE_SIZ 63
239 /* Runtime worker status informations. Shared in scoreboard */
242 apr_time_t error_time; /* time of the last error */
243 int retries; /* number of retries on this worker */
244 int lbstatus; /* Current lbstatus */
245 int lbfactor; /* dynamic lbfactor */
246 apr_off_t transferred;/* Number of bytes transferred to remote */
247 apr_off_t read; /* Number of bytes read from remote */
248 apr_size_t elected; /* Number of times the worker was elected */
249 char route[PROXY_WORKER_MAX_ROUTE_SIZ+1];
250 char redirect[PROXY_WORKER_MAX_ROUTE_SIZ+1];
253 /* Worker configuration */
254 struct proxy_worker {
255 int id; /* scoreboard id */
256 apr_interval_time_t retry; /* retry interval */
257 int lbfactor; /* initial load balancing factor */
259 const char *scheme; /* scheme to use ajp|http|https */
260 const char *hostname; /* remote backend address */
261 const char *route; /* balancing route */
262 const char *redirect; /* temporary balancing redirection route */
264 int min; /* Desired minimum number of available connections */
265 int smax; /* Soft maximum on the total number of connections */
266 int hmax; /* Hard maximum on the total number of connections */
267 apr_interval_time_t ttl; /* maximum amount of time in seconds a connection
268 * may be available while exceeding the soft limit */
269 apr_interval_time_t timeout; /* connection timeout */
271 apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */
273 apr_size_t recv_buffer_size;
274 char recv_buffer_size_set;
275 apr_size_t io_buffer_size;
276 char io_buffer_size_set;
279 proxy_conn_pool *cp; /* Connection pool to use */
280 proxy_worker_stat *s; /* Shared data */
281 void *opaque; /* per scheme worker data */
282 int is_address_reusable;
284 apr_thread_mutex_t *mutex; /* Thread lock for updating address cache */
288 struct proxy_balancer {
289 apr_array_header_t *workers; /* array of proxy_workers */
290 const char *name; /* name of the load balancer */
291 const char *sticky; /* sticky session identifier */
292 int sticky_force; /* Disable failover for sticky sessions */
293 apr_interval_time_t timeout; /* Timeout for waiting on free connection */
294 int max_attempts; /* Number of attempts before failing */
295 char max_attempts_set;
297 lbmethod_requests = 1,
301 /* XXX: Perhaps we will need the proc mutex too.
302 * Altrough we are only using arithmetic operations
303 * it may lead to a incorrect calculations.
304 * For now use only the thread mutex.
307 apr_thread_mutex_t *mutex; /* Thread lock for updating lb params */
312 #define PROXY_THREAD_LOCK(x) apr_thread_mutex_lock((x)->mutex)
313 #define PROXY_THREAD_UNLOCK(x) apr_thread_mutex_unlock((x)->mutex)
315 #define PROXY_THREAD_LOCK(x) APR_SUCCESS
316 #define PROXY_THREAD_UNLOCK(x) APR_SUCCESS
321 /* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
322 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
325 #define PROXY_DECLARE(type) type
326 #define PROXY_DECLARE_NONSTD(type) type
327 #define PROXY_DECLARE_DATA
328 #elif defined(PROXY_DECLARE_STATIC)
329 #define PROXY_DECLARE(type) type __stdcall
330 #define PROXY_DECLARE_NONSTD(type) type
331 #define PROXY_DECLARE_DATA
332 #elif defined(PROXY_DECLARE_EXPORT)
333 #define PROXY_DECLARE(type) __declspec(dllexport) type __stdcall
334 #define PROXY_DECLARE_NONSTD(type) __declspec(dllexport) type
335 #define PROXY_DECLARE_DATA __declspec(dllexport)
337 #define PROXY_DECLARE(type) __declspec(dllimport) type __stdcall
338 #define PROXY_DECLARE_NONSTD(type) __declspec(dllimport) type
339 #define PROXY_DECLARE_DATA __declspec(dllimport)
343 * Hook an optional proxy hook. Unlike static hooks, this uses a macro
344 * instead of a function.
346 #define PROXY_OPTIONAL_HOOK(name,fn,pre,succ,order) \
347 APR_OPTIONAL_HOOK(proxy,name,fn,pre,succ,order)
349 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r,
350 proxy_worker *worker, proxy_server_conf *conf, char *url,
351 const char *proxyhost, apr_port_t proxyport))
352 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r,
355 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr))
356 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r))
360 * It will return the most suitable worker at the moment
361 * and coresponding balancer.
362 * The url is rewritten from balancer://cluster/uri to scheme://host:port/uri
363 * and then the scheme_handler is called.
366 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, pre_request, (proxy_worker **worker,
367 proxy_balancer **balancer,
369 proxy_server_conf *conf, char **url))
372 * It is called after request for updating runtime balancer status.
374 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, post_request, (proxy_worker *worker,
375 proxy_balancer *balancer, request_rec *r,
376 proxy_server_conf *conf))
381 PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r);
382 PROXY_DECLARE(int) ap_proxy_hex2c(const char *x);
383 PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x);
384 PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
385 int forcedec, int proxyreq);
386 PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
387 char **passwordp, char **hostp, apr_port_t *port);
388 PROXY_DECLARE(const char *)ap_proxy_date_canon(apr_pool_t *p, const char *x);
389 PROXY_DECLARE(int) ap_proxy_liststr(const char *list, const char *val);
390 PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val);
391 PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x);
392 PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y);
393 PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message);
394 PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p);
395 PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p);
396 PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p);
397 PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p);
398 PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
399 PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r);
400 PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos);
401 PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key);
402 /* DEPRECATED (will be replaced with ap_proxy_connect_backend */
403 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 *);
404 PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
405 PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
406 PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c);
407 PROXY_DECLARE(const char *) ap_proxy_ssl_val(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *var);
409 /* Header mapping functions, and a typedef of their signature */
410 PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, proxy_server_conf *conf, const char *url);
411 PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, proxy_server_conf *conf, const char *str);
414 typedef const char *(*ap_proxy_header_reverse_map_fn)(request_rec *,
415 proxy_server_conf *, const char *);
416 #elif defined(PROXY_DECLARE_STATIC)
417 typedef const char *(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
418 proxy_server_conf *, const char *);
419 #elif defined(PROXY_DECLARE_EXPORT)
420 typedef __declspec(dllexport) const char *
421 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
422 proxy_server_conf *, const char *);
424 typedef __declspec(dllimport) const char *
425 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
426 proxy_server_conf *, const char *);
430 /* Connection pool API */
432 * Get the worker from proxy configuration
433 * @param p memory pool used for finding worker
434 * @param conf current proxy server configuration
435 * @param url url to find the worker from
436 * @return proxy_worker or NULL if not found
438 PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
439 proxy_server_conf *conf,
442 * Add the worker to proxy configuration
443 * @param worker the new worker
444 * @param p memory pool to allocate worker from
445 * @param conf current proxy server configuration
446 * @param url url containing worker name
447 * @return error message or NULL if successfull
449 PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,
451 proxy_server_conf *conf,
456 * @param p memory pool to allocate worker from
459 PROXY_DECLARE(proxy_worker *) ap_proxy_create_worker(apr_pool_t *p);
462 * Initize the worker's shared data
463 * @param conf current proxy server configuration
464 * @param worker worker to initialize
465 * @param s current server record
466 * @param worker worker to initialize
468 PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
469 proxy_worker *worker,
475 * @param worker worker to initialize
476 * @param s current server record
477 * @return APR_SUCCESS or error code
479 PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker,
482 * Get the balancer from proxy configuration
483 * @param p memory pool used for finding balancer
484 * @param conf current proxy server configuration
485 * @param url url to find the worker from. Has to have balancer:// prefix
486 * @return proxy_balancer or NULL if not found
488 PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
489 proxy_server_conf *conf,
492 * Add the balancer to proxy configuration
493 * @param balancer the new balancer
494 * @param p memory pool to allocate balancer from
495 * @param conf current proxy server configuration
496 * @param url url containing balancer name
497 * @return error message or NULL if successfull
499 PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer,
501 proxy_server_conf *conf,
505 * Add the worker to the balancer
506 * @param pool memory pool for adding worker
507 * @param balancer balancer to add to
508 * @param balancer worker to add
509 * @note Single worker can be added to multiple balancers.
511 PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(apr_pool_t *pool,
512 proxy_balancer *balancer,
513 proxy_worker *worker);
515 * Get the most suitable worker and(or) balancer for the request
516 * @param worker worker used for processing request
517 * @param balancer balancer used for processing request
518 * @param r current request
519 * @param conf current proxy server configuration
520 * @param url request url that balancer can rewrite.
521 * @return OK or HTTP_XXX error
522 * @note It calls balancer pre_request hook if the url starts with balancer://
523 * The balancer then rewrites the url to particular worker, like http://host:port
525 PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
526 proxy_balancer **balancer,
528 proxy_server_conf *conf,
531 * Post request worker and balancer cleanup
532 * @param worker worker used for processing request
533 * @param balancer balancer used for processing request
534 * @param r current request
535 * @param conf current proxy server configuration
536 * @return OK or HTTP_XXX error
537 * @note When ever the pre_request is called, the post_request has to be
540 PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
541 proxy_balancer *balancer,
543 proxy_server_conf *conf);
545 * Deternime backend hostname and port
546 * @param p memory pool used for processing
547 * @param r current request
548 * @param conf current proxy server configuration
549 * @param worker worker used for processing request
550 * @param conn proxy connection struct
551 * @param uri processed uri
552 * @param url request url
553 * @param proxyname are we connecting directly or via s proxy
554 * @param proxyport proxy host port
555 * @param server_portstr Via headers server port
556 * @param server_portstr_size size of the server_portstr buffer
557 * @return OK or HTTP_XXX error
559 PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
560 proxy_server_conf *conf,
561 proxy_worker *worker,
562 proxy_conn_rec *conn,
565 const char *proxyname,
566 apr_port_t proxyport,
567 char *server_portstr,
568 int server_portstr_size);
570 * Mark a worker for retry
571 * @param proxy_function calling proxy scheme (http, ajp, ...)
572 * @param conf current proxy server configuration
573 * @param worker worker used for retrying
574 * @param s current server record
575 * @return OK if marked for retry, DECLINED otherwise
576 * @note Worker will be marker for retry if the time of the last retry
577 * has been ellapsed. In case there is no retry option set, defaults to
578 * number_of_retries seconds.
580 PROXY_DECLARE(int) ap_proxy_retry_worker(const char *proxy_function,
581 proxy_worker *worker,
584 * Acquire a connection from workers connection pool
585 * @param proxy_function calling proxy scheme (http, ajp, ...)
586 * @param conn acquired connection
587 * @param worker worker used for obtaining connection
588 * @param s current server record
589 * @return OK or HTTP_XXX error
590 * @note If the number of connections is exhaused the function will
591 * block untill the timeout is reached.
593 PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
594 proxy_conn_rec **conn,
595 proxy_worker *worker,
598 * Release a connection back to worker connection pool
599 * @param proxy_function calling proxy scheme (http, ajp, ...)
600 * @param conn acquired connection
601 * @param s current server record
602 * @return OK or HTTP_XXX error
603 * @note The connection will be closed if conn->close_on_release is set
605 PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
606 proxy_conn_rec *conn,
609 * Make a connection to the backend
610 * @param proxy_function calling proxy scheme (http, ajp, ...)
611 * @param conn acquired connection
612 * @param worker connection worker
613 * @param s current server record
614 * @return OK or HTTP_XXX error
615 * @note In case the socket already exists for conn, just check the link
618 PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
619 proxy_conn_rec *conn,
620 proxy_worker *worker,
623 * Make a connection record for backend connection
624 * @param proxy_function calling proxy scheme (http, ajp, ...)
625 * @param conn acquired connection
626 * @param c client connection record
627 * @param s current server record
628 * @return OK or HTTP_XXX error
630 PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
631 proxy_conn_rec *conn,
632 conn_rec *c, server_rec *s);
635 #if MODULE_MAGIC_NUMBER_MAJOR > 20020903
636 #define PROXY_HAS_SCOREBOARD 1
638 #define PROXY_HAS_SCOREBOARD 0
641 /* The number of dynamic workers that can be added when reconfiguring.
642 * If this limit is reached you must stop and restart the server.
644 #define PROXY_DYNAMIC_BALANCER_LIMIT 16
646 * Calculate number of maximum number of workers in scoreboard.
647 * @return number of workers to allocate in the scoreboard
649 int ap_proxy_lb_workers(void);
652 extern module PROXY_DECLARE_DATA proxy_module;
654 extern int PROXY_DECLARE_DATA proxy_lb_workers;
656 #endif /*MOD_PROXY_H*/