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 const char *domain; /* domain name to use in absence of a domain name in the request */
135 int req; /* true if proxy requests are enabled */
142 } viaopt; /* how to deal with proxy Via: headers */
144 apr_size_t recv_buffer_size;
145 char recv_buffer_size_set;
146 apr_size_t io_buffer_size;
147 char io_buffer_size_set;
151 * the following setting masks the error page
152 * returned from the 'proxied server' and just
153 * forwards the status code upwards.
154 * This allows the main server (us) to generate
155 * the error page, (so it will look like a error
156 * returned from the rest of the system
159 int error_override_set;
161 int preserve_host_set;
162 apr_interval_time_t timeout;
168 } badopt; /* how to deal with bad headers */
170 /* putting new stuff on the end maximises binary back-compatibility.
171 * the strmatch_patterns are really a const just to have a
172 * case-independent strstr.
174 apr_array_header_t* cookie_paths;
175 apr_array_header_t* cookie_domains;
176 const apr_strmatch_pattern* cookie_path_str;
177 const apr_strmatch_pattern* cookie_domain_str;
182 } proxy_status; /* Status display options */
183 char proxy_status_set;
184 apr_pool_t *pool; /* Pool used for allocating this struct */
189 const char *p; /* The path */
190 int p_is_fnmatch; /* Is this path an fnmatch candidate? */
191 regex_t *r; /* Is this a regex? */
195 conn_rec *connection;
196 const char *hostname;
199 apr_pool_t *pool; /* Subpool used for creating socket */
200 apr_socket_t *sock; /* Connection socket */
201 apr_sockaddr_t *addr; /* Preparsed remote address info */
202 apr_uint32_t flags; /* Conection flags */
203 int close; /* Close 'this' connection */
204 int close_on_recycle; /* Close the connection when returning to pool */
205 proxy_worker *worker; /* Connection pool this connection belogns to */
206 void *data; /* per scheme connection data */
210 float cache_completion; /* completion percentage */
211 int content_length; /* length of the content */
214 /* Connection pool */
215 struct proxy_conn_pool {
216 apr_pool_t *pool; /* The pool used in constructor and destructor calls */
217 apr_sockaddr_t *addr; /* Preparsed remote address info */
219 apr_reslist_t *res; /* Connection resource list */
221 proxy_conn_rec *conn; /* Single connection for prefork mpm's */
224 /* woker status flags */
225 #define PROXY_WORKER_INITIALIZED 0x0001
226 #define PROXY_WORKER_IGNORE_ERRORS 0x0002
227 #define PROXY_WORKER_IN_SHUTDOWN 0x0010
228 #define PROXY_WORKER_DISABLED 0x0020
229 #define PROXY_WORKER_IN_ERROR 0x0040
231 #define PROXY_WORKER_IS_USABLE(f) (!((f)->s->status & 0x00F0))
233 /* default worker retry timeout in seconds */
234 #define PROXY_WORKER_DEFAULT_RETRY 60
235 #define PROXY_WORKER_MAX_ROUTE_SIZ 63
237 /* Runtime worker status informations. Shared in scoreboard */
240 apr_time_t error_time; /* time of the last error */
241 int retries; /* number of retries on this worker */
242 int lbstatus; /* Current lbstatus */
243 int lbfactor; /* dynamic lbfactor */
244 apr_off_t transfered; /* Number of bytes transfered to remote */
245 apr_off_t readed; /* Number of bytes readed from remote */
246 apr_size_t elected; /* Number of times the worker was elected */
247 char route[PROXY_WORKER_MAX_ROUTE_SIZ+1];
248 char redirect[PROXY_WORKER_MAX_ROUTE_SIZ+1];
251 /* Worker configuration */
252 struct proxy_worker {
253 int id; /* scoreboard id */
254 apr_interval_time_t retry; /* retry interval */
255 int lbfactor; /* initial load balancing factor */
257 const char *scheme; /* scheme to use ajp|http|https */
258 const char *hostname; /* remote backend address */
259 const char *route; /* balancing route */
260 const char *redirect; /* temporary balancing redirection route */
262 int min; /* Desired minimum number of available connections */
263 int smax; /* Soft maximum on the total number of connections */
264 int hmax; /* Hard maximum on the total number of connections */
265 apr_interval_time_t ttl; /* maximum amount of time in seconds a connection
266 * may be available while exceeding the soft limit */
267 apr_interval_time_t timeout; /* connection timeout */
269 apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */
271 apr_size_t recv_buffer_size;
272 char recv_buffer_size_set;
273 apr_size_t io_buffer_size;
274 char io_buffer_size_set;
277 proxy_conn_pool *cp; /* Connection pool to use */
278 proxy_worker_stat *s; /* Shared data */
279 void *opaque; /* per scheme worker data */
282 struct proxy_balancer {
283 apr_array_header_t *workers; /* array of proxy_workers */
284 const char *name; /* name of the load balancer */
285 const char *sticky; /* sticky session identifier */
286 int sticky_force; /* Disable failover for sticky sessions */
287 apr_interval_time_t timeout; /* Timeout for waiting on free connection */
288 int max_attempts; /* Number of attempts before failing */
289 char max_attempts_set;
291 /* XXX: Perhaps we will need the proc mutex too.
292 * Altrough we are only using arithmetic operations
293 * it may lead to a incorrect calculations.
294 * For now use only the thread mutex.
297 apr_thread_mutex_t *mutex; /* Thread lock for updating lb params */
303 /* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
304 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
307 #define PROXY_DECLARE(type) type
308 #define PROXY_DECLARE_NONSTD(type) type
309 #define PROXY_DECLARE_DATA
310 #elif defined(PROXY_DECLARE_STATIC)
311 #define PROXY_DECLARE(type) type __stdcall
312 #define PROXY_DECLARE_NONSTD(type) type
313 #define PROXY_DECLARE_DATA
314 #elif defined(PROXY_DECLARE_EXPORT)
315 #define PROXY_DECLARE(type) __declspec(dllexport) type __stdcall
316 #define PROXY_DECLARE_NONSTD(type) __declspec(dllexport) type
317 #define PROXY_DECLARE_DATA __declspec(dllexport)
319 #define PROXY_DECLARE(type) __declspec(dllimport) type __stdcall
320 #define PROXY_DECLARE_NONSTD(type) __declspec(dllimport) type
321 #define PROXY_DECLARE_DATA __declspec(dllimport)
325 * Hook an optional proxy hook. Unlike static hooks, this uses a macro
326 * instead of a function.
328 #define PROXY_OPTIONAL_HOOK(name,fn,pre,succ,order) \
329 APR_OPTIONAL_HOOK(proxy,name,fn,pre,succ,order)
331 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r,
332 proxy_worker *worker, proxy_server_conf *conf, char *url,
333 const char *proxyhost, apr_port_t proxyport))
334 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r,
337 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr))
338 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r))
342 * It will return the most suitable worker at the moment
343 * and coresponding balancer.
344 * The url is rewritten from balancer://cluster/uri to scheme://host:port/uri
345 * and then the scheme_handler is called.
348 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, pre_request, (proxy_worker **worker,
349 proxy_balancer **balancer,
351 proxy_server_conf *conf, char **url))
354 * It is called after request for updating runtime balancer status.
356 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, post_request, (proxy_worker *worker,
357 proxy_balancer *balancer, request_rec *r,
358 proxy_server_conf *conf))
363 PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r);
364 PROXY_DECLARE(int) ap_proxy_hex2c(const char *x);
365 PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x);
366 PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
368 PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
369 char **passwordp, char **hostp, apr_port_t *port);
370 PROXY_DECLARE(const char *)ap_proxy_date_canon(apr_pool_t *p, const char *x);
371 PROXY_DECLARE(int) ap_proxy_liststr(const char *list, const char *val);
372 PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val);
373 PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x);
374 PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y);
375 PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message);
376 PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p);
377 PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p);
378 PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p);
379 PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p);
380 PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
381 PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r);
382 PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos);
383 PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key);
384 /* DEPRECATED (will be replaced with ap_proxy_connect_backend */
385 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 *);
386 PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
387 PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
389 /* Connection pool API */
391 * Get the worker from proxy configuration
392 * @param p memory pool used for finding worker
393 * @param conf current proxy server configuration
394 * @param url url to find the worker from
395 * @return proxy_worker or NULL if not found
397 PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
398 proxy_server_conf *conf,
401 * Add the worker to proxy configuration
402 * @param worker the new worker
403 * @param p memory pool to allocate worker from
404 * @param conf current proxy server configuration
405 * @param url url containing worker name
406 * @return error message or NULL if successfull
408 PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,
410 proxy_server_conf *conf,
415 * @param p memory pool to allocate worker from
418 PROXY_DECLARE(proxy_worker *) ap_proxy_create_worker(apr_pool_t *p);
421 * Initize the worker's shared data
422 * @param conf current proxy server configuration
423 * @param worker worker to initialize
424 * @param s current server record
425 * @param worker worker to initialize
427 PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
428 proxy_worker *worker,
434 * @param worker worker to initialize
435 * @param s current server record
436 * @return APR_SUCCESS or error code
438 PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker,
441 * Get the balancer from proxy configuration
442 * @param p memory pool used for finding balancer
443 * @param conf current proxy server configuration
444 * @param url url to find the worker from. Has to have balancer:// prefix
445 * @return proxy_balancer or NULL if not found
447 PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
448 proxy_server_conf *conf,
451 * Add the balancer to proxy configuration
452 * @param balancer the new balancer
453 * @param p memory pool to allocate balancer from
454 * @param conf current proxy server configuration
455 * @param url url containing balancer name
456 * @return error message or NULL if successfull
458 PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer,
460 proxy_server_conf *conf,
464 * Add the worker to the balancer
465 * @param pool memory pool for adding worker
466 * @param balancer balancer to add to
467 * @param balancer worker to add
468 * @note Single worker can be added to multiple balancers.
470 PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(apr_pool_t *pool,
471 proxy_balancer *balancer,
472 proxy_worker *worker);
474 * Get the most suitable worker and(or) balancer for the request
475 * @param worker worker used for processing request
476 * @param balancer balancer used for processing request
477 * @param r current request
478 * @param conf current proxy server configuration
479 * @param url request url that balancer can rewrite.
480 * @return OK or HTTP_XXX error
481 * @note It calls balancer pre_request hook if the url starts with balancer://
482 * The balancer then rewrites the url to particular worker, like http://host:port
484 PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
485 proxy_balancer **balancer,
487 proxy_server_conf *conf,
490 * Post request worker and balancer cleanup
491 * @param worker worker used for processing request
492 * @param balancer balancer used for processing request
493 * @param r current request
494 * @param conf current proxy server configuration
495 * @return OK or HTTP_XXX error
496 * @note When ever the pre_request is called, the post_request has to be
499 PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
500 proxy_balancer *balancer,
502 proxy_server_conf *conf);
504 * Deternime backend hostname and port
505 * @param p memory pool used for processing
506 * @param r current request
507 * @param conf current proxy server configuration
508 * @param worker worker used for processing request
509 * @param conn proxy connection struct
510 * @param uri processed uri
511 * @param url request url
512 * @param proxyname are we connecting directly or via s proxy
513 * @param proxyport proxy host port
514 * @param server_portstr Via headers server port
515 * @param server_portstr_size size of the server_portstr buffer
516 * @return OK or HTTP_XXX error
518 PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
519 proxy_server_conf *conf,
520 proxy_worker *worker,
521 proxy_conn_rec *conn,
524 const char *proxyname,
525 apr_port_t proxyport,
526 char *server_portstr,
527 int server_portstr_size);
529 * Mark a worker for retry
530 * @param proxy_function calling proxy scheme (http, ajp, ...)
531 * @param conf current proxy server configuration
532 * @param worker worker used for retrying
533 * @param s current server record
534 * @return OK if marked for retry, DECLINED otherwise
535 * @note Worker will be marker for retry if the time of the last retry
536 * has been ellapsed. In case there is no retry option set, defaults to
537 * number_of_retries seconds.
539 PROXY_DECLARE(int) ap_proxy_retry_worker(const char *proxy_function,
540 proxy_worker *worker,
543 * Acquire a connection from workers connection pool
544 * @param proxy_function calling proxy scheme (http, ajp, ...)
545 * @param conn acquired connection
546 * @param worker worker used for obtaining connection
547 * @param s current server record
548 * @return OK or HTTP_XXX error
549 * @note If the number of connections is exhaused the function will
550 * block untill the timeout is reached.
552 PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
553 proxy_conn_rec **conn,
554 proxy_worker *worker,
557 * Release a connection back to worker connection pool
558 * @param proxy_function calling proxy scheme (http, ajp, ...)
559 * @param conn acquired connection
560 * @param s current server record
561 * @return OK or HTTP_XXX error
562 * @note The connection will be closed if conn->close_on_release is set
564 PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
565 proxy_conn_rec *conn,
568 * Make a connection to the backend
569 * @param proxy_function calling proxy scheme (http, ajp, ...)
570 * @param conn acquired connection
571 * @param worker connection worker
572 * @param s current server record
573 * @return OK or HTTP_XXX error
574 * @note In case the socket already exists for conn, just check the link
577 PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
578 proxy_conn_rec *conn,
579 proxy_worker *worker,
582 * Make a connection record for backend connection
583 * @param proxy_function calling proxy scheme (http, ajp, ...)
584 * @param conn acquired connection
585 * @param c client connection record
586 * @param s current server record
587 * @return OK or HTTP_XXX error
589 PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
590 proxy_conn_rec *conn,
591 conn_rec *c, server_rec *s);
594 #if MODULE_MAGIC_NUMBER_MAJOR > 20020903
595 #define PROXY_HAS_SCOREBOARD 1
597 #define PROXY_HAS_SCOREBOARD 0
600 /* The number of dynamic workers that can be added when reconfiguring.
601 * If this limit is reached you must stop and restart the server.
603 #define PROXY_DYNAMIC_BALANCER_LIMIT 16
605 * Calculate number of maximum number of workers in scoreboard.
606 * @return number of workers to allocate in the scoreboard
608 int ap_proxy_lb_workers(void);
611 extern module PROXY_DECLARE_DATA proxy_module;
613 extern int PROXY_DECLARE_DATA proxy_lb_workers;
615 #endif /*MOD_PROXY_H*/