1 /* Copyright 1999-2004 The Apache Software Foundation
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
20 * Main include file for the Apache proxy
25 Also note numerous FIXMEs and CHECKMEs which should be eliminated.
27 This code is once again experimental!
31 1. Make it completely work (for FTP too)
35 Chuck Murcko <chuck@topsail.org> 02-06-01
41 #include "apr_hooks.h"
44 #include "apr_strings.h"
45 #include "apr_buckets.h"
47 #include "apr_network_io.h"
48 #include "apr_pools.h"
49 #include "apr_strings.h"
52 #include "apr_strmatch.h"
53 #include "apr_fnmatch.h"
54 #include "apr_reslist.h"
55 #define APR_WANT_STRFUNC
59 #include "http_config.h"
60 #include "ap_config.h"
61 #include "http_core.h"
62 #include "http_protocol.h"
63 #include "http_request.h"
64 #include "http_vhost.h"
65 #include "http_main.h"
67 #include "http_connection.h"
68 #include "util_filter.h"
69 #include "util_ebcdic.h"
71 #if APR_HAVE_NETINET_IN_H
72 #include <netinet/in.h>
74 #if APR_HAVE_ARPA_INET_H
75 #include <arpa/inet.h>
78 /* for proxy_canonenc() */
80 enc_path, enc_search, enc_user, enc_fpath, enc_parm
83 #if APR_CHARSET_EBCDIC
85 #else /*APR_CHARSET_EBCDIC*/
86 #define CRLF "\015\012"
87 #endif /*APR_CHARSET_EBCDIC*/
89 /* default Max-Forwards header setting */
90 #define DEFAULT_MAX_FORWARDS 10
92 /* static information about a remote proxy */
94 const char *scheme; /* the schemes handled by this proxy, or '*' */
95 const char *protocol; /* the scheme used to talk to this proxy */
96 const char *hostname; /* the hostname of this proxy */
97 apr_port_t port; /* the port for this proxy */
98 regex_t *regexp; /* compiled regex (if any) for the remote */
99 int use_regex; /* simple boolean. True if we have a regex pattern */
107 struct dirconn_entry {
109 struct in_addr addr, mask;
110 struct apr_sockaddr_t *hostaddr;
111 int (*matcher) (struct dirconn_entry * This, request_rec *r);
114 struct noproxy_entry {
116 struct apr_sockaddr_t *addr;
119 typedef struct proxy_balancer proxy_balancer;
120 typedef struct proxy_worker proxy_worker;
121 typedef struct proxy_conn_pool proxy_conn_pool;
124 apr_array_header_t *proxies;
125 apr_array_header_t *sec_proxy;
126 apr_array_header_t *aliases;
127 apr_array_header_t *raliases;
128 apr_array_header_t *noproxies;
129 apr_array_header_t *dirconn;
130 apr_array_header_t *allowed_connect_ports;
131 apr_array_header_t *workers;
132 apr_array_header_t *balancers;
133 proxy_worker *forward; /* forward proxy worker */
134 proxy_worker *reverse; /* reverse "module-driven" proxy worker */
135 const char *domain; /* domain name to use in absence of a domain name in the request */
136 int req; /* true if proxy requests are enabled */
143 } viaopt; /* how to deal with proxy Via: headers */
145 apr_size_t recv_buffer_size;
146 char recv_buffer_size_set;
147 apr_size_t io_buffer_size;
148 char io_buffer_size_set;
152 * the following setting masks the error page
153 * returned from the 'proxied server' and just
154 * forwards the status code upwards.
155 * This allows the main server (us) to generate
156 * the error page, (so it will look like a error
157 * returned from the rest of the system
160 int error_override_set;
162 int preserve_host_set;
163 apr_interval_time_t timeout;
169 } badopt; /* how to deal with bad headers */
171 /* putting new stuff on the end maximises binary back-compatibility.
172 * the strmatch_patterns are really a const just to have a
173 * case-independent strstr.
175 apr_array_header_t* cookie_paths;
176 apr_array_header_t* cookie_domains;
177 const apr_strmatch_pattern* cookie_path_str;
178 const apr_strmatch_pattern* cookie_domain_str;
183 } proxy_status; /* Status display options */
184 char proxy_status_set;
185 apr_pool_t *pool; /* Pool used for allocating this struct */
190 const char *p; /* The path */
191 int p_is_fnmatch; /* Is this path an fnmatch candidate? */
192 regex_t *r; /* Is this a regex? */
196 conn_rec *connection;
197 const char *hostname;
200 apr_pool_t *pool; /* Subpool used for creating socket */
201 apr_socket_t *sock; /* Connection socket */
202 apr_sockaddr_t *addr; /* Preparsed remote address info */
203 apr_uint32_t flags; /* Conection flags */
204 int close; /* Close 'this' connection */
205 int close_on_recycle; /* Close the connection when returning to pool */
206 proxy_worker *worker; /* Connection pool this connection belogns to */
207 void *data; /* per scheme connection data */
211 float cache_completion; /* completion percentage */
212 int content_length; /* length of the content */
215 /* Connection pool */
216 struct proxy_conn_pool {
217 apr_pool_t *pool; /* The pool used in constructor and destructor calls */
218 apr_sockaddr_t *addr; /* Preparsed remote address info */
220 apr_reslist_t *res; /* Connection resource list */
222 proxy_conn_rec *conn; /* Single connection for prefork mpm's */
225 /* woker status flags */
226 #define PROXY_WORKER_INITIALIZED 0x0001
227 #define PROXY_WORKER_IGNORE_ERRORS 0x0002
228 #define PROXY_WORKER_IN_SHUTDOWN 0x0010
229 #define PROXY_WORKER_DISABLED 0x0020
230 #define PROXY_WORKER_IN_ERROR 0x0040
232 #define PROXY_WORKER_IS_USABLE(f) (!((f)->s->status & 0x00F0))
234 /* default worker retry timeout in seconds */
235 #define PROXY_WORKER_DEFAULT_RETRY 60
236 #define PROXY_WORKER_MAX_ROUTE_SIZ 63
238 /* Runtime worker status informations. Shared in scoreboard */
241 apr_time_t error_time; /* time of the last error */
242 int retries; /* number of retries on this worker */
243 int lbstatus; /* Current lbstatus */
244 int lbfactor; /* dynamic lbfactor */
245 apr_off_t transferred;/* Number of bytes transferred to remote */
246 apr_off_t read; /* Number of bytes read from remote */
247 apr_size_t elected; /* Number of times the worker was elected */
248 char route[PROXY_WORKER_MAX_ROUTE_SIZ+1];
249 char redirect[PROXY_WORKER_MAX_ROUTE_SIZ+1];
252 /* Worker configuration */
253 struct proxy_worker {
254 int id; /* scoreboard id */
255 apr_interval_time_t retry; /* retry interval */
256 int lbfactor; /* initial load balancing factor */
258 const char *scheme; /* scheme to use ajp|http|https */
259 const char *hostname; /* remote backend address */
260 const char *route; /* balancing route */
261 const char *redirect; /* temporary balancing redirection route */
263 int min; /* Desired minimum number of available connections */
264 int smax; /* Soft maximum on the total number of connections */
265 int hmax; /* Hard maximum on the total number of connections */
266 apr_interval_time_t ttl; /* maximum amount of time in seconds a connection
267 * may be available while exceeding the soft limit */
268 apr_interval_time_t timeout; /* connection timeout */
270 apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */
272 apr_size_t recv_buffer_size;
273 char recv_buffer_size_set;
274 apr_size_t io_buffer_size;
275 char io_buffer_size_set;
278 proxy_conn_pool *cp; /* Connection pool to use */
279 proxy_worker_stat *s; /* Shared data */
280 void *opaque; /* per scheme worker data */
281 int is_address_reusable;
283 apr_thread_mutex_t *mutex; /* Thread lock for updating address cache */
287 struct proxy_balancer {
288 apr_array_header_t *workers; /* array of proxy_workers */
289 const char *name; /* name of the load balancer */
290 const char *sticky; /* sticky session identifier */
291 int sticky_force; /* Disable failover for sticky sessions */
292 apr_interval_time_t timeout; /* Timeout for waiting on free connection */
293 int max_attempts; /* Number of attempts before failing */
294 char max_attempts_set;
296 lbmethod_requests = 1,
300 /* XXX: Perhaps we will need the proc mutex too.
301 * Altrough we are only using arithmetic operations
302 * it may lead to a incorrect calculations.
303 * For now use only the thread mutex.
306 apr_thread_mutex_t *mutex; /* Thread lock for updating lb params */
311 #define PROXY_THREAD_LOCK(x) apr_thread_mutex_lock((x)->mutex)
312 #define PROXY_THREAD_UNLOCK(x) apr_thread_mutex_unlock((x)->mutex)
314 #define PROXY_THREAD_LOCK(x) APR_SUCCESS
315 #define PROXY_THREAD_UNLOCK(x) APR_SUCCESS
320 /* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
321 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
324 #define PROXY_DECLARE(type) type
325 #define PROXY_DECLARE_NONSTD(type) type
326 #define PROXY_DECLARE_DATA
327 #elif defined(PROXY_DECLARE_STATIC)
328 #define PROXY_DECLARE(type) type __stdcall
329 #define PROXY_DECLARE_NONSTD(type) type
330 #define PROXY_DECLARE_DATA
331 #elif defined(PROXY_DECLARE_EXPORT)
332 #define PROXY_DECLARE(type) __declspec(dllexport) type __stdcall
333 #define PROXY_DECLARE_NONSTD(type) __declspec(dllexport) type
334 #define PROXY_DECLARE_DATA __declspec(dllexport)
336 #define PROXY_DECLARE(type) __declspec(dllimport) type __stdcall
337 #define PROXY_DECLARE_NONSTD(type) __declspec(dllimport) type
338 #define PROXY_DECLARE_DATA __declspec(dllimport)
342 * Hook an optional proxy hook. Unlike static hooks, this uses a macro
343 * instead of a function.
345 #define PROXY_OPTIONAL_HOOK(name,fn,pre,succ,order) \
346 APR_OPTIONAL_HOOK(proxy,name,fn,pre,succ,order)
348 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r,
349 proxy_worker *worker, proxy_server_conf *conf, char *url,
350 const char *proxyhost, apr_port_t proxyport))
351 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r,
354 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr))
355 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r))
359 * It will return the most suitable worker at the moment
360 * and coresponding balancer.
361 * The url is rewritten from balancer://cluster/uri to scheme://host:port/uri
362 * and then the scheme_handler is called.
365 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, pre_request, (proxy_worker **worker,
366 proxy_balancer **balancer,
368 proxy_server_conf *conf, char **url))
371 * It is called after request for updating runtime balancer status.
373 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, post_request, (proxy_worker *worker,
374 proxy_balancer *balancer, request_rec *r,
375 proxy_server_conf *conf))
380 PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r);
381 PROXY_DECLARE(int) ap_proxy_hex2c(const char *x);
382 PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x);
383 PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
385 PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
386 char **passwordp, char **hostp, apr_port_t *port);
387 PROXY_DECLARE(const char *)ap_proxy_date_canon(apr_pool_t *p, const char *x);
388 PROXY_DECLARE(int) ap_proxy_liststr(const char *list, const char *val);
389 PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val);
390 PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x);
391 PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y);
392 PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message);
393 PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p);
394 PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p);
395 PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p);
396 PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p);
397 PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
398 PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r);
399 PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos);
400 PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key);
401 /* DEPRECATED (will be replaced with ap_proxy_connect_backend */
402 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 *);
403 PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
404 PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
406 /* Header mapping functions, and a typedef of their signature */
407 PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, proxy_server_conf *conf, const char *url);
408 PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, proxy_server_conf *conf, const char *str);
411 typedef const char *(*ap_proxy_header_reverse_map_fn)(request_rec *,
412 proxy_server_conf *, const char *);
413 #elif defined(PROXY_DECLARE_STATIC)
414 typedef const char *(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
415 proxy_server_conf *, const char *);
416 #elif defined(PROXY_DECLARE_EXPORT)
417 typedef __declspec(dllexport) const char *
418 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
419 proxy_server_conf *, const char *);
421 typedef __declspec(dllimport) const char *
422 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
423 proxy_server_conf *, const char *);
427 /* Connection pool API */
429 * Get the worker from proxy configuration
430 * @param p memory pool used for finding worker
431 * @param conf current proxy server configuration
432 * @param url url to find the worker from
433 * @return proxy_worker or NULL if not found
435 PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
436 proxy_server_conf *conf,
439 * Add the worker to proxy configuration
440 * @param worker the new worker
441 * @param p memory pool to allocate worker from
442 * @param conf current proxy server configuration
443 * @param url url containing worker name
444 * @return error message or NULL if successfull
446 PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,
448 proxy_server_conf *conf,
453 * @param p memory pool to allocate worker from
456 PROXY_DECLARE(proxy_worker *) ap_proxy_create_worker(apr_pool_t *p);
459 * Initize the worker's shared data
460 * @param conf current proxy server configuration
461 * @param worker worker to initialize
462 * @param s current server record
463 * @param worker worker to initialize
465 PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
466 proxy_worker *worker,
472 * @param worker worker to initialize
473 * @param s current server record
474 * @return APR_SUCCESS or error code
476 PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker,
479 * Get the balancer from proxy configuration
480 * @param p memory pool used for finding balancer
481 * @param conf current proxy server configuration
482 * @param url url to find the worker from. Has to have balancer:// prefix
483 * @return proxy_balancer or NULL if not found
485 PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
486 proxy_server_conf *conf,
489 * Add the balancer to proxy configuration
490 * @param balancer the new balancer
491 * @param p memory pool to allocate balancer from
492 * @param conf current proxy server configuration
493 * @param url url containing balancer name
494 * @return error message or NULL if successfull
496 PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer,
498 proxy_server_conf *conf,
502 * Add the worker to the balancer
503 * @param pool memory pool for adding worker
504 * @param balancer balancer to add to
505 * @param balancer worker to add
506 * @note Single worker can be added to multiple balancers.
508 PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(apr_pool_t *pool,
509 proxy_balancer *balancer,
510 proxy_worker *worker);
512 * Get the most suitable worker and(or) balancer for the request
513 * @param worker worker used for processing request
514 * @param balancer balancer used for processing request
515 * @param r current request
516 * @param conf current proxy server configuration
517 * @param url request url that balancer can rewrite.
518 * @return OK or HTTP_XXX error
519 * @note It calls balancer pre_request hook if the url starts with balancer://
520 * The balancer then rewrites the url to particular worker, like http://host:port
522 PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
523 proxy_balancer **balancer,
525 proxy_server_conf *conf,
528 * Post request worker and balancer cleanup
529 * @param worker worker used for processing request
530 * @param balancer balancer used for processing request
531 * @param r current request
532 * @param conf current proxy server configuration
533 * @return OK or HTTP_XXX error
534 * @note When ever the pre_request is called, the post_request has to be
537 PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
538 proxy_balancer *balancer,
540 proxy_server_conf *conf);
542 * Deternime backend hostname and port
543 * @param p memory pool used for processing
544 * @param r current request
545 * @param conf current proxy server configuration
546 * @param worker worker used for processing request
547 * @param conn proxy connection struct
548 * @param uri processed uri
549 * @param url request url
550 * @param proxyname are we connecting directly or via s proxy
551 * @param proxyport proxy host port
552 * @param server_portstr Via headers server port
553 * @param server_portstr_size size of the server_portstr buffer
554 * @return OK or HTTP_XXX error
556 PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
557 proxy_server_conf *conf,
558 proxy_worker *worker,
559 proxy_conn_rec *conn,
562 const char *proxyname,
563 apr_port_t proxyport,
564 char *server_portstr,
565 int server_portstr_size);
567 * Mark a worker for retry
568 * @param proxy_function calling proxy scheme (http, ajp, ...)
569 * @param conf current proxy server configuration
570 * @param worker worker used for retrying
571 * @param s current server record
572 * @return OK if marked for retry, DECLINED otherwise
573 * @note Worker will be marker for retry if the time of the last retry
574 * has been ellapsed. In case there is no retry option set, defaults to
575 * number_of_retries seconds.
577 PROXY_DECLARE(int) ap_proxy_retry_worker(const char *proxy_function,
578 proxy_worker *worker,
581 * Acquire a connection from workers connection pool
582 * @param proxy_function calling proxy scheme (http, ajp, ...)
583 * @param conn acquired connection
584 * @param worker worker used for obtaining connection
585 * @param s current server record
586 * @return OK or HTTP_XXX error
587 * @note If the number of connections is exhaused the function will
588 * block untill the timeout is reached.
590 PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
591 proxy_conn_rec **conn,
592 proxy_worker *worker,
595 * Release a connection back to worker connection pool
596 * @param proxy_function calling proxy scheme (http, ajp, ...)
597 * @param conn acquired connection
598 * @param s current server record
599 * @return OK or HTTP_XXX error
600 * @note The connection will be closed if conn->close_on_release is set
602 PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
603 proxy_conn_rec *conn,
606 * Make a connection to the backend
607 * @param proxy_function calling proxy scheme (http, ajp, ...)
608 * @param conn acquired connection
609 * @param worker connection worker
610 * @param s current server record
611 * @return OK or HTTP_XXX error
612 * @note In case the socket already exists for conn, just check the link
615 PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
616 proxy_conn_rec *conn,
617 proxy_worker *worker,
620 * Make a connection record for backend connection
621 * @param proxy_function calling proxy scheme (http, ajp, ...)
622 * @param conn acquired connection
623 * @param c client connection record
624 * @param s current server record
625 * @return OK or HTTP_XXX error
627 PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
628 proxy_conn_rec *conn,
629 conn_rec *c, server_rec *s);
632 #if MODULE_MAGIC_NUMBER_MAJOR > 20020903
633 #define PROXY_HAS_SCOREBOARD 1
635 #define PROXY_HAS_SCOREBOARD 0
638 /* The number of dynamic workers that can be added when reconfiguring.
639 * If this limit is reached you must stop and restart the server.
641 #define PROXY_DYNAMIC_BALANCER_LIMIT 16
643 * Calculate number of maximum number of workers in scoreboard.
644 * @return number of workers to allocate in the scoreboard
646 int ap_proxy_lb_workers(void);
649 extern module PROXY_DECLARE_DATA proxy_module;
651 extern int PROXY_DECLARE_DATA proxy_lb_workers;
653 #endif /*MOD_PROXY_H*/