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);
407 /* Header mapping functions, and a typedef of their signature */
408 PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, proxy_server_conf *conf, const char *url);
409 PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, proxy_server_conf *conf, const char *str);
412 typedef const char *(*ap_proxy_header_reverse_map_fn)(request_rec *,
413 proxy_server_conf *, const char *);
414 #elif defined(PROXY_DECLARE_STATIC)
415 typedef const char *(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
416 proxy_server_conf *, const char *);
417 #elif defined(PROXY_DECLARE_EXPORT)
418 typedef __declspec(dllexport) const char *
419 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
420 proxy_server_conf *, const char *);
422 typedef __declspec(dllimport) const char *
423 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
424 proxy_server_conf *, const char *);
428 /* Connection pool API */
430 * Get the worker from proxy configuration
431 * @param p memory pool used for finding worker
432 * @param conf current proxy server configuration
433 * @param url url to find the worker from
434 * @return proxy_worker or NULL if not found
436 PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
437 proxy_server_conf *conf,
440 * Add the worker to proxy configuration
441 * @param worker the new worker
442 * @param p memory pool to allocate worker from
443 * @param conf current proxy server configuration
444 * @param url url containing worker name
445 * @return error message or NULL if successfull
447 PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,
449 proxy_server_conf *conf,
454 * @param p memory pool to allocate worker from
457 PROXY_DECLARE(proxy_worker *) ap_proxy_create_worker(apr_pool_t *p);
460 * Initize the worker's shared data
461 * @param conf current proxy server configuration
462 * @param worker worker to initialize
463 * @param s current server record
464 * @param worker worker to initialize
466 PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
467 proxy_worker *worker,
473 * @param worker worker to initialize
474 * @param s current server record
475 * @return APR_SUCCESS or error code
477 PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker,
480 * Get the balancer from proxy configuration
481 * @param p memory pool used for finding balancer
482 * @param conf current proxy server configuration
483 * @param url url to find the worker from. Has to have balancer:// prefix
484 * @return proxy_balancer or NULL if not found
486 PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
487 proxy_server_conf *conf,
490 * Add the balancer to proxy configuration
491 * @param balancer the new balancer
492 * @param p memory pool to allocate balancer from
493 * @param conf current proxy server configuration
494 * @param url url containing balancer name
495 * @return error message or NULL if successfull
497 PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer,
499 proxy_server_conf *conf,
503 * Add the worker to the balancer
504 * @param pool memory pool for adding worker
505 * @param balancer balancer to add to
506 * @param balancer worker to add
507 * @note Single worker can be added to multiple balancers.
509 PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(apr_pool_t *pool,
510 proxy_balancer *balancer,
511 proxy_worker *worker);
513 * Get the most suitable worker and(or) balancer for the request
514 * @param worker worker used for processing request
515 * @param balancer balancer used for processing request
516 * @param r current request
517 * @param conf current proxy server configuration
518 * @param url request url that balancer can rewrite.
519 * @return OK or HTTP_XXX error
520 * @note It calls balancer pre_request hook if the url starts with balancer://
521 * The balancer then rewrites the url to particular worker, like http://host:port
523 PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
524 proxy_balancer **balancer,
526 proxy_server_conf *conf,
529 * Post request worker and balancer cleanup
530 * @param worker worker used for processing request
531 * @param balancer balancer used for processing request
532 * @param r current request
533 * @param conf current proxy server configuration
534 * @return OK or HTTP_XXX error
535 * @note When ever the pre_request is called, the post_request has to be
538 PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
539 proxy_balancer *balancer,
541 proxy_server_conf *conf);
543 * Deternime backend hostname and port
544 * @param p memory pool used for processing
545 * @param r current request
546 * @param conf current proxy server configuration
547 * @param worker worker used for processing request
548 * @param conn proxy connection struct
549 * @param uri processed uri
550 * @param url request url
551 * @param proxyname are we connecting directly or via s proxy
552 * @param proxyport proxy host port
553 * @param server_portstr Via headers server port
554 * @param server_portstr_size size of the server_portstr buffer
555 * @return OK or HTTP_XXX error
557 PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
558 proxy_server_conf *conf,
559 proxy_worker *worker,
560 proxy_conn_rec *conn,
563 const char *proxyname,
564 apr_port_t proxyport,
565 char *server_portstr,
566 int server_portstr_size);
568 * Mark a worker for retry
569 * @param proxy_function calling proxy scheme (http, ajp, ...)
570 * @param conf current proxy server configuration
571 * @param worker worker used for retrying
572 * @param s current server record
573 * @return OK if marked for retry, DECLINED otherwise
574 * @note Worker will be marker for retry if the time of the last retry
575 * has been ellapsed. In case there is no retry option set, defaults to
576 * number_of_retries seconds.
578 PROXY_DECLARE(int) ap_proxy_retry_worker(const char *proxy_function,
579 proxy_worker *worker,
582 * Acquire a connection from workers connection pool
583 * @param proxy_function calling proxy scheme (http, ajp, ...)
584 * @param conn acquired connection
585 * @param worker worker used for obtaining connection
586 * @param s current server record
587 * @return OK or HTTP_XXX error
588 * @note If the number of connections is exhaused the function will
589 * block untill the timeout is reached.
591 PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
592 proxy_conn_rec **conn,
593 proxy_worker *worker,
596 * Release a connection back to worker connection pool
597 * @param proxy_function calling proxy scheme (http, ajp, ...)
598 * @param conn acquired connection
599 * @param s current server record
600 * @return OK or HTTP_XXX error
601 * @note The connection will be closed if conn->close_on_release is set
603 PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
604 proxy_conn_rec *conn,
607 * Make a connection to the backend
608 * @param proxy_function calling proxy scheme (http, ajp, ...)
609 * @param conn acquired connection
610 * @param worker connection worker
611 * @param s current server record
612 * @return OK or HTTP_XXX error
613 * @note In case the socket already exists for conn, just check the link
616 PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
617 proxy_conn_rec *conn,
618 proxy_worker *worker,
621 * Make a connection record for backend connection
622 * @param proxy_function calling proxy scheme (http, ajp, ...)
623 * @param conn acquired connection
624 * @param c client connection record
625 * @param s current server record
626 * @return OK or HTTP_XXX error
628 PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
629 proxy_conn_rec *conn,
630 conn_rec *c, server_rec *s);
633 #if MODULE_MAGIC_NUMBER_MAJOR > 20020903
634 #define PROXY_HAS_SCOREBOARD 1
636 #define PROXY_HAS_SCOREBOARD 0
639 /* The number of dynamic workers that can be added when reconfiguring.
640 * If this limit is reached you must stop and restart the server.
642 #define PROXY_DYNAMIC_BALANCER_LIMIT 16
644 * Calculate number of maximum number of workers in scoreboard.
645 * @return number of workers to allocate in the scoreboard
647 int ap_proxy_lb_workers(void);
650 extern module PROXY_DECLARE_DATA proxy_module;
652 extern int PROXY_DECLARE_DATA proxy_lb_workers;
654 #endif /*MOD_PROXY_H*/