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;
120 apr_array_header_t *proxies;
121 apr_array_header_t *sec_proxy;
122 apr_array_header_t *aliases;
123 apr_array_header_t *raliases;
124 apr_array_header_t *noproxies;
125 apr_array_header_t *dirconn;
126 apr_array_header_t *allowed_connect_ports;
127 apr_array_header_t *workers;
128 apr_array_header_t *balancers;
129 const char *domain; /* domain name to use in absence of a domain name in the request */
130 int req; /* true if proxy requests are enabled */
137 } viaopt; /* how to deal with proxy Via: headers */
139 apr_size_t recv_buffer_size;
140 char recv_buffer_size_set;
141 apr_size_t io_buffer_size;
142 char io_buffer_size_set;
146 * the following setting masks the error page
147 * returned from the 'proxied server' and just
148 * forwards the status code upwards.
149 * This allows the main server (us) to generate
150 * the error page, (so it will look like a error
151 * returned from the rest of the system
154 int error_override_set;
156 int preserve_host_set;
157 apr_interval_time_t timeout;
163 } badopt; /* how to deal with bad headers */
165 /* putting new stuff on the end maximises binary back-compatibility.
166 * the strmatch_patterns are really a const just to have a
167 * case-independent strstr.
169 apr_array_header_t* cookie_paths;
170 apr_array_header_t* cookie_domains;
171 const apr_strmatch_pattern* cookie_path_str;
172 const apr_strmatch_pattern* cookie_domain_str;
177 } proxy_status; /* Status display options */
178 char proxy_status_set;
182 typedef struct proxy_balancer proxy_balancer;
183 typedef struct proxy_worker proxy_worker;
184 typedef struct proxy_conn_pool proxy_conn_pool;
187 const char *p; /* The path */
188 int p_is_fnmatch; /* Is this path an fnmatch candidate? */
189 regex_t *r; /* Is this a regex? */
193 conn_rec *connection;
194 const char *hostname;
197 apr_pool_t *pool; /* Subpool used for creating socket */
198 apr_socket_t *sock; /* Connection socket */
199 apr_uint32_t flags; /* Conection flags */
200 int close; /* Close 'this' connection */
201 int close_on_recycle; /* Close the connection when returning to pool */
202 proxy_worker *worker; /* Connection pool this connection belogns to */
203 void *data; /* per scheme connection data */
207 float cache_completion; /* completion percentage */
208 int content_length; /* length of the content */
211 /* Connection pool */
212 struct proxy_conn_pool {
213 apr_pool_t *pool; /* The pool used in constructor and destructor calls */
214 apr_sockaddr_t *addr; /* Preparsed remote address info */
216 apr_reslist_t *res; /* Connection resource list */
218 int nfree; /* Balancer free count number */
219 proxy_conn_rec *conn; /* Single connection for prefork mpm's */
222 /* woker status flags */
223 #define PROXY_WORKER_INITIALIZED 0x0001
224 #define PROXY_WORKER_IN_SHUTDOWN 0x0010
225 #define PROXY_WORKER_DISABLED 0x0020
226 #define PROXY_WORKER_IN_ERROR 0x0040
228 #define PROXY_WORKER_IS_USABLE(f) (!((f)->status & 0x00F0))
231 /* Worker configuration */
232 struct proxy_worker {
234 apr_time_t error_time; /* time of the last error */
235 apr_interval_time_t retry; /* retry interval */
236 int retries; /* number of retries on this worker */
237 int lbfactor; /* initial load balancing factor */
239 const char *scheme; /* scheme to use ajp|http|https */
240 const char *hostname; /* remote backend address */
241 const char *route; /* balancing route */
242 const char *redirect; /* temporary balancing redirection route */
244 int min; /* Desired minimum number of available connections */
245 int smax; /* Soft maximum on the total number of connections */
246 int hmax; /* Hard maximum on the total number of connections */
247 apr_interval_time_t ttl; /* maximum amount of time in seconds a connection
248 * may be available while exceeding the soft limit */
249 apr_interval_time_t timeout; /* connection timeout */
251 apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */
253 apr_size_t recv_buffer_size;
254 char recv_buffer_size_set;
255 apr_size_t io_buffer_size;
256 char io_buffer_size_set;
259 proxy_conn_pool *cp; /* Connection pool to use */
260 void *opaque; /* per scheme worker data */
263 /* Runtime worker status informations. Shared in scoreboard */
265 int id; /* scoreboard id */
266 double lbstatus; /* Current lbstatus */
267 double lbfactor; /* dynamic lbfactor */
268 apr_size_t transfered; /* Number of bytes transfered to remote */
269 apr_size_t readed; /* Number of bytes readed from remote */
270 apr_size_t elected; /* Number of times the worker was elected */
271 } proxy_runtime_stat;
273 /* Runtime worker. */
275 proxy_balancer *b; /* balancer containing this worker */
277 proxy_runtime_stat *s;
278 } proxy_runtime_worker;
280 struct proxy_balancer {
281 apr_array_header_t *workers; /* array of proxy_runtime_workers */
282 const char *name; /* name of the load balancer */
283 const char *sticky; /* sticky session identifier */
284 int sticky_force; /* Disable failover for sticky sessions */
285 apr_interval_time_t timeout; /* Timeout for waiting on free connection */
286 /* XXX: Perhaps we will need the proc mutex too.
287 * Altrough we are only using arithmetic operations
288 * it may lead to a incorrect calculations.
289 * For now use only the thread mutex.
292 apr_thread_mutex_t *mutex; /* Thread lock for updating lb params */
298 /* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
299 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
302 #define PROXY_DECLARE(type) type
303 #define PROXY_DECLARE_NONSTD(type) type
304 #define PROXY_DECLARE_DATA
305 #elif defined(PROXY_DECLARE_STATIC)
306 #define PROXY_DECLARE(type) type __stdcall
307 #define PROXY_DECLARE_NONSTD(type) type
308 #define PROXY_DECLARE_DATA
309 #elif defined(PROXY_DECLARE_EXPORT)
310 #define PROXY_DECLARE(type) __declspec(dllexport) type __stdcall
311 #define PROXY_DECLARE_NONSTD(type) __declspec(dllexport) type
312 #define PROXY_DECLARE_DATA __declspec(dllexport)
314 #define PROXY_DECLARE(type) __declspec(dllimport) type __stdcall
315 #define PROXY_DECLARE_NONSTD(type) __declspec(dllimport) type
316 #define PROXY_DECLARE_DATA __declspec(dllimport)
320 * Hook an optional proxy hook. Unlike static hooks, this uses a macro
321 * instead of a function.
323 #define PROXY_OPTIONAL_HOOK(name,fn,pre,succ,order) \
324 APR_OPTIONAL_HOOK(proxy,name,fn,pre,succ,order)
326 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r,
327 proxy_worker *worker, proxy_server_conf *conf, char *url,
328 const char *proxyhost, apr_port_t proxyport))
329 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r,
332 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr))
333 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r))
337 * It will return the most suitable worker at the moment
338 * and coresponding balancer.
339 * The url is rewritten from balancer://cluster/uri to scheme://host:port/uri
340 * and then the scheme_handler is called.
343 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, pre_request, (proxy_worker **worker,
344 proxy_balancer **balancer,
346 proxy_server_conf *conf, char **url))
349 * It is called after request for updating runtime balancer status.
351 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, post_request, (proxy_worker *worker,
352 proxy_balancer *balancer, request_rec *r,
353 proxy_server_conf *conf))
358 PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r);
359 PROXY_DECLARE(int) ap_proxy_hex2c(const char *x);
360 PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x);
361 PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
363 PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
364 char **passwordp, char **hostp, apr_port_t *port);
365 PROXY_DECLARE(const char *)ap_proxy_date_canon(apr_pool_t *p, const char *x);
366 PROXY_DECLARE(int) ap_proxy_liststr(const char *list, const char *val);
367 PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val);
368 PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x);
369 PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y);
370 PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message);
371 PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p);
372 PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p);
373 PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p);
374 PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p);
375 PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
376 PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r);
377 PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos);
378 PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key);
379 /* DEPRECATED (will be replaced with ap_proxy_connect_backend */
380 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 *);
381 PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
382 PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
384 /* Connection pool API */
386 * Get the worker from proxy configuration
387 * @param p memory pool used for finding worker
388 * @param conf current proxy server configuration
389 * @param url url to find the worker from
390 * @return proxy_worker or NULL if not found
392 PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
393 proxy_server_conf *conf,
396 * Add the worker to proxy configuration
397 * @param worker the new worker
398 * @param p memory pool to allocate worker from
399 * @param conf current proxy server configuration
400 * @param url url containing worker name
401 * @return error message or NULL if successfull
403 PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,
405 proxy_server_conf *conf,
408 * Get the balancer from proxy configuration
409 * @param p memory pool used for finding balancer
410 * @param conf current proxy server configuration
411 * @param url url to find the worker from. Has to have balancer:// prefix
412 * @return proxy_balancer or NULL if not found
414 PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
415 proxy_server_conf *conf,
418 * Add the balancer to proxy configuration
419 * @param balancer the new balancer
420 * @param p memory pool to allocate balancer from
421 * @param conf current proxy server configuration
422 * @param url url containing balancer name
423 * @return error message or NULL if successfull
425 PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer,
427 proxy_server_conf *conf,
431 * Add the worker to the balancer
432 * @param pool memory pool for adding worker
433 * @param balancer balancer to add to
434 * @param balancer worker to add
435 * @note Single worker can be added to multiple balancers.
437 PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(apr_pool_t *pool,
438 proxy_balancer *balancer,
439 proxy_worker *worker);
441 * Get the most suitable worker and(or) balancer for the request
442 * @param worker worker used for processing request
443 * @param balancer balancer used for processing request
444 * @param r current request
445 * @param conf current proxy server configuration
446 * @param url request url that balancer can rewrite.
447 * @return OK or HTTP_XXX error
448 * @note It calls balancer pre_request hook if the url starts with balancer://
449 * The balancer then rewrites the url to particular worker, like http://host:port
451 PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
452 proxy_balancer **balancer,
454 proxy_server_conf *conf,
457 * Post request worker and balancer cleanup
458 * @param worker worker used for processing request
459 * @param balancer balancer used for processing request
460 * @param r current request
461 * @param conf current proxy server configuration
462 * @return OK or HTTP_XXX error
463 * @note When ever the pre_request is called, the post_request has to be
466 PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
467 proxy_balancer *balancer,
469 proxy_server_conf *conf);
471 * Deternime backend hostname and port
472 * @param p memory pool used for processing
473 * @param r current request
474 * @param conf current proxy server configuration
475 * @param worker worker used for processing request
476 * @param conn proxy connection struct
477 * @param ppool long living memory pool
478 * @param uri processed uri
479 * @param url request url
480 * @param proxyname are we connecting directly or via s proxy
481 * @param proxyport proxy host port
482 * @param server_portstr Via headers server port
483 * @param server_portstr_size size of the server_portstr buffer
484 * @return OK or HTTP_XXX error
486 PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
487 proxy_server_conf *conf,
488 proxy_worker *worker,
489 proxy_conn_rec *conn,
493 const char *proxyname,
494 apr_port_t proxyport,
495 char *server_portstr,
496 int server_portstr_size);
498 * Mark a worker for retry
499 * @param proxy_function calling proxy scheme (http, ajp, ...)
500 * @param conf current proxy server configuration
501 * @param worker worker used for retrying
502 * @param s current server record
503 * @return OK if marked for retry, DECLINED otherwise
504 * @note Worker will be marker for retry if the time of the last retry
505 * has been ellapsed. In case there is no retry option set, defaults to
506 * number_of_retries seconds.
508 PROXY_DECLARE(int) ap_proxy_retry_worker(const char *proxy_function,
509 proxy_worker *worker,
512 * Acquire a connection from workers connection pool
513 * @param proxy_function calling proxy scheme (http, ajp, ...)
514 * @param conn acquired connection
515 * @param worker worker used for obtaining connection
516 * @param s current server record
517 * @return OK or HTTP_XXX error
518 * @note If the number of connections is exhaused the function will
519 * block untill the timeout is reached.
521 PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
522 proxy_conn_rec **conn,
523 proxy_worker *worker,
526 * Release a connection back to worker connection pool
527 * @param proxy_function calling proxy scheme (http, ajp, ...)
528 * @param conn acquired connection
529 * @param s current server record
530 * @return OK or HTTP_XXX error
531 * @note The connection will be closed if conn->close_on_release is set
533 PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
534 proxy_conn_rec *conn,
537 * Close the connection
538 * @param conn connection to close
539 * @return APR_SUCCESS or error code
541 PROXY_DECLARE(apr_status_t) ap_proxy_close_connection(proxy_conn_rec *conn);
544 * Make a connection to the backend
545 * @param proxy_function calling proxy scheme (http, ajp, ...)
546 * @param conn acquired connection
547 * @param worker connection worker
548 * @param s current server record
549 * @return OK or HTTP_XXX error
550 * @note In case the socket already exists for conn, just check the link
553 PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
554 proxy_conn_rec *conn,
555 proxy_worker *worker,
558 * Make a connection record for backend connection
559 * @param proxy_function calling proxy scheme (http, ajp, ...)
560 * @param conn acquired connection
561 * @param c client connection record
562 * @param s current server record
563 * @return OK or HTTP_XXX error
565 PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
566 proxy_conn_rec *conn,
567 conn_rec *c, server_rec *s);
570 #if MODULE_MAGIC_NUMBER_MAJOR > 20020903
571 #define PROXY_HAS_SCOREBOARD 1
573 #define PROXY_HAS_SCOREBOARD 0
575 /* The number of dynamic balancers that can be added */
576 #define PROXY_DYNAMIC_BALANCER_LIMIT 16
577 PROXY_DECLARE(int) ap_proxy_lb_workers(void);
580 extern module PROXY_DECLARE_DATA proxy_module;
582 #endif /*MOD_PROXY_H*/