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 *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.
179 } proxy_status; /* Status display options */
180 char proxy_status_set;
181 apr_pool_t *pool; /* Pool used for allocating this struct */
186 const char *p; /* The path */
187 int p_is_fnmatch; /* Is this path an fnmatch candidate? */
188 ap_regex_t *r; /* Is this a regex? */
190 /* ProxyPassReverse and friends are documented as working inside
191 * <Location>. But in fact they never have done in the case of
192 * more than one <Location>, because the server_conf can't see it.
193 * We need to move them to the per-dir config.
194 * Discussed in February:
195 * http://marc.theaimsgroup.com/?l=apache-httpd-dev&m=110726027118798&w=2
197 apr_array_header_t *raliases;
198 apr_array_header_t* cookie_paths;
199 apr_array_header_t* cookie_domains;
200 const apr_strmatch_pattern* cookie_path_str;
201 const apr_strmatch_pattern* cookie_domain_str;
205 conn_rec *connection;
206 const char *hostname;
209 apr_pool_t *pool; /* Subpool used for creating socket */
210 apr_socket_t *sock; /* Connection socket */
211 apr_sockaddr_t *addr; /* Preparsed remote address info */
212 apr_uint32_t flags; /* Conection flags */
213 int close; /* Close 'this' connection */
214 int close_on_recycle; /* Close the connection when returning to pool */
215 proxy_worker *worker; /* Connection pool this connection belogns to */
216 void *data; /* per scheme connection data */
220 float cache_completion; /* completion percentage */
221 int content_length; /* length of the content */
224 /* Connection pool */
225 struct proxy_conn_pool {
226 apr_pool_t *pool; /* The pool used in constructor and destructor calls */
227 apr_sockaddr_t *addr; /* Preparsed remote address info */
229 apr_reslist_t *res; /* Connection resource list */
231 proxy_conn_rec *conn; /* Single connection for prefork mpm's */
234 /* woker status flags */
235 #define PROXY_WORKER_INITIALIZED 0x0001
236 #define PROXY_WORKER_IGNORE_ERRORS 0x0002
237 #define PROXY_WORKER_IN_SHUTDOWN 0x0010
238 #define PROXY_WORKER_DISABLED 0x0020
239 #define PROXY_WORKER_STOPPED 0x0040
240 #define PROXY_WORKER_IN_ERROR 0x0080
242 #define PROXY_WORKER_IS_USABLE(f) (!((f)->s->status & 0x00F0))
244 /* default worker retry timeout in seconds */
245 #define PROXY_WORKER_DEFAULT_RETRY 60
246 #define PROXY_WORKER_MAX_ROUTE_SIZ 63
248 /* Runtime worker status informations. Shared in scoreboard */
251 apr_time_t error_time; /* time of the last error */
252 int retries; /* number of retries on this worker */
253 int lbstatus; /* Current lbstatus */
254 int lbfactor; /* dynamic lbfactor */
255 apr_off_t transferred;/* Number of bytes transferred to remote */
256 apr_off_t read; /* Number of bytes read from remote */
257 apr_size_t elected; /* Number of times the worker was elected */
258 char route[PROXY_WORKER_MAX_ROUTE_SIZ+1];
259 char redirect[PROXY_WORKER_MAX_ROUTE_SIZ+1];
262 /* Worker configuration */
263 struct proxy_worker {
264 int id; /* scoreboard id */
265 apr_interval_time_t retry; /* retry interval */
266 int lbfactor; /* initial load balancing factor */
268 const char *scheme; /* scheme to use ajp|http|https */
269 const char *hostname; /* remote backend address */
270 const char *route; /* balancing route */
271 const char *redirect; /* temporary balancing redirection route */
272 int status; /* temporary worker status */
274 int min; /* Desired minimum number of available connections */
275 int smax; /* Soft maximum on the total number of connections */
276 int hmax; /* Hard maximum on the total number of connections */
277 apr_interval_time_t ttl; /* maximum amount of time in seconds a connection
278 * may be available while exceeding the soft limit */
279 apr_interval_time_t timeout; /* connection timeout */
281 apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */
283 apr_size_t recv_buffer_size;
284 char recv_buffer_size_set;
285 apr_size_t io_buffer_size;
286 char io_buffer_size_set;
289 proxy_conn_pool *cp; /* Connection pool to use */
290 proxy_worker_stat *s; /* Shared data */
291 void *opaque; /* per scheme worker data */
292 int is_address_reusable;
294 apr_thread_mutex_t *mutex; /* Thread lock for updating address cache */
298 struct proxy_balancer {
299 apr_array_header_t *workers; /* array of proxy_workers */
300 const char *name; /* name of the load balancer */
301 const char *sticky; /* sticky session identifier */
302 int sticky_force; /* Disable failover for sticky sessions */
303 apr_interval_time_t timeout; /* Timeout for waiting on free connection */
304 int max_attempts; /* Number of attempts before failing */
305 char max_attempts_set;
307 lbmethod_requests = 1,
311 /* XXX: Perhaps we will need the proc mutex too.
312 * Altrough we are only using arithmetic operations
313 * it may lead to a incorrect calculations.
314 * For now use only the thread mutex.
317 apr_thread_mutex_t *mutex; /* Thread lock for updating lb params */
322 #define PROXY_THREAD_LOCK(x) apr_thread_mutex_lock((x)->mutex)
323 #define PROXY_THREAD_UNLOCK(x) apr_thread_mutex_unlock((x)->mutex)
325 #define PROXY_THREAD_LOCK(x) APR_SUCCESS
326 #define PROXY_THREAD_UNLOCK(x) APR_SUCCESS
331 /* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
332 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
335 #define PROXY_DECLARE(type) type
336 #define PROXY_DECLARE_NONSTD(type) type
337 #define PROXY_DECLARE_DATA
338 #elif defined(PROXY_DECLARE_STATIC)
339 #define PROXY_DECLARE(type) type __stdcall
340 #define PROXY_DECLARE_NONSTD(type) type
341 #define PROXY_DECLARE_DATA
342 #elif defined(PROXY_DECLARE_EXPORT)
343 #define PROXY_DECLARE(type) __declspec(dllexport) type __stdcall
344 #define PROXY_DECLARE_NONSTD(type) __declspec(dllexport) type
345 #define PROXY_DECLARE_DATA __declspec(dllexport)
347 #define PROXY_DECLARE(type) __declspec(dllimport) type __stdcall
348 #define PROXY_DECLARE_NONSTD(type) __declspec(dllimport) type
349 #define PROXY_DECLARE_DATA __declspec(dllimport)
353 * Hook an optional proxy hook. Unlike static hooks, this uses a macro
354 * instead of a function.
356 #define PROXY_OPTIONAL_HOOK(name,fn,pre,succ,order) \
357 APR_OPTIONAL_HOOK(proxy,name,fn,pre,succ,order)
359 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r,
360 proxy_worker *worker, proxy_server_conf *conf, char *url,
361 const char *proxyhost, apr_port_t proxyport))
362 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r,
365 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr))
366 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r))
370 * It will return the most suitable worker at the moment
371 * and coresponding balancer.
372 * The url is rewritten from balancer://cluster/uri to scheme://host:port/uri
373 * and then the scheme_handler is called.
376 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, pre_request, (proxy_worker **worker,
377 proxy_balancer **balancer,
379 proxy_server_conf *conf, char **url))
382 * It is called after request for updating runtime balancer status.
384 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, post_request, (proxy_worker *worker,
385 proxy_balancer *balancer, request_rec *r,
386 proxy_server_conf *conf))
389 * request status hook
390 * It is called after all proxy processing has been done. This gives other
391 * modules a chance to create default content on failure, for example
393 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, request_status,
394 (int *status, request_rec *r))
398 PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r);
399 PROXY_DECLARE(int) ap_proxy_hex2c(const char *x);
400 PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x);
401 PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
402 int forcedec, int proxyreq);
403 PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
404 char **passwordp, char **hostp, apr_port_t *port);
405 PROXY_DECLARE(const char *)ap_proxy_date_canon(apr_pool_t *p, const char *x);
406 PROXY_DECLARE(int) ap_proxy_liststr(const char *list, const char *val);
407 PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val);
408 PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x);
409 PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y);
410 PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message);
411 PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p);
412 PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p);
413 PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p);
414 PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p);
415 PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
416 PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r);
417 PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos);
418 PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key);
419 /* DEPRECATED (will be replaced with ap_proxy_connect_backend */
420 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 *);
421 PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
422 PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
423 PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c);
424 PROXY_DECLARE(const char *) ap_proxy_ssl_val(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *var);
426 /* Header mapping functions, and a typedef of their signature */
427 PROXY_DECLARE(const char *) ap_proxy_location_reverse_map(request_rec *r, proxy_server_conf *conf, const char *url);
428 PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r, proxy_server_conf *conf, const char *str);
431 typedef const char *(*ap_proxy_header_reverse_map_fn)(request_rec *,
432 proxy_server_conf *, const char *);
433 #elif defined(PROXY_DECLARE_STATIC)
434 typedef const char *(__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
435 proxy_server_conf *, const char *);
436 #elif defined(PROXY_DECLARE_EXPORT)
437 typedef __declspec(dllexport) const char *
438 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
439 proxy_server_conf *, const char *);
441 typedef __declspec(dllimport) const char *
442 (__stdcall *ap_proxy_header_reverse_map_fn)(request_rec *,
443 proxy_server_conf *, const char *);
447 /* Connection pool API */
449 * Get the worker from proxy configuration
450 * @param p memory pool used for finding worker
451 * @param conf current proxy server configuration
452 * @param url url to find the worker from
453 * @return proxy_worker or NULL if not found
455 PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
456 proxy_server_conf *conf,
459 * Add the worker to proxy configuration
460 * @param worker the new worker
461 * @param p memory pool to allocate worker from
462 * @param conf current proxy server configuration
463 * @param url url containing worker name
464 * @return error message or NULL if successfull
466 PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,
468 proxy_server_conf *conf,
473 * @param p memory pool to allocate worker from
476 PROXY_DECLARE(proxy_worker *) ap_proxy_create_worker(apr_pool_t *p);
479 * Initize the worker's shared data
480 * @param conf current proxy server configuration
481 * @param worker worker to initialize
482 * @param s current server record
483 * @param worker worker to initialize
485 PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
486 proxy_worker *worker,
492 * @param worker worker to initialize
493 * @param s current server record
494 * @return APR_SUCCESS or error code
496 PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker,
499 * Get the balancer from proxy configuration
500 * @param p memory pool used for finding balancer
501 * @param conf current proxy server configuration
502 * @param url url to find the worker from. Has to have balancer:// prefix
503 * @return proxy_balancer or NULL if not found
505 PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p,
506 proxy_server_conf *conf,
509 * Add the balancer to proxy configuration
510 * @param balancer the new balancer
511 * @param p memory pool to allocate balancer from
512 * @param conf current proxy server configuration
513 * @param url url containing balancer name
514 * @return error message or NULL if successfull
516 PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer,
518 proxy_server_conf *conf,
522 * Add the worker to the balancer
523 * @param pool memory pool for adding worker
524 * @param balancer balancer to add to
525 * @param balancer worker to add
526 * @note Single worker can be added to multiple balancers.
528 PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(apr_pool_t *pool,
529 proxy_balancer *balancer,
530 proxy_worker *worker);
532 * Get the most suitable worker and(or) balancer for the request
533 * @param worker worker used for processing request
534 * @param balancer balancer used for processing request
535 * @param r current request
536 * @param conf current proxy server configuration
537 * @param url request url that balancer can rewrite.
538 * @return OK or HTTP_XXX error
539 * @note It calls balancer pre_request hook if the url starts with balancer://
540 * The balancer then rewrites the url to particular worker, like http://host:port
542 PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
543 proxy_balancer **balancer,
545 proxy_server_conf *conf,
548 * Post request worker and balancer cleanup
549 * @param worker worker used for processing request
550 * @param balancer balancer used for processing request
551 * @param r current request
552 * @param conf current proxy server configuration
553 * @return OK or HTTP_XXX error
554 * @note When ever the pre_request is called, the post_request has to be
557 PROXY_DECLARE(int) ap_proxy_post_request(proxy_worker *worker,
558 proxy_balancer *balancer,
560 proxy_server_conf *conf);
563 * Request status function
564 * @param status status of proxy request
565 * @return OK or DECLINED
567 PROXY_DECLARE(int) ap_proxy_request_status(int *status, request_rec *r);
570 * Deternime backend hostname and port
571 * @param p memory pool used for processing
572 * @param r current request
573 * @param conf current proxy server configuration
574 * @param worker worker used for processing request
575 * @param conn proxy connection struct
576 * @param uri processed uri
577 * @param url request url
578 * @param proxyname are we connecting directly or via s proxy
579 * @param proxyport proxy host port
580 * @param server_portstr Via headers server port
581 * @param server_portstr_size size of the server_portstr buffer
582 * @return OK or HTTP_XXX error
584 PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
585 proxy_server_conf *conf,
586 proxy_worker *worker,
587 proxy_conn_rec *conn,
590 const char *proxyname,
591 apr_port_t proxyport,
592 char *server_portstr,
593 int server_portstr_size);
595 * Mark a worker for retry
596 * @param proxy_function calling proxy scheme (http, ajp, ...)
597 * @param conf current proxy server configuration
598 * @param worker worker used for retrying
599 * @param s current server record
600 * @return OK if marked for retry, DECLINED otherwise
601 * @note Worker will be marker for retry if the time of the last retry
602 * has been ellapsed. In case there is no retry option set, defaults to
603 * number_of_retries seconds.
605 PROXY_DECLARE(int) ap_proxy_retry_worker(const char *proxy_function,
606 proxy_worker *worker,
609 * Acquire a connection from workers connection pool
610 * @param proxy_function calling proxy scheme (http, ajp, ...)
611 * @param conn acquired connection
612 * @param worker worker used for obtaining connection
613 * @param s current server record
614 * @return OK or HTTP_XXX error
615 * @note If the number of connections is exhaused the function will
616 * block untill the timeout is reached.
618 PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
619 proxy_conn_rec **conn,
620 proxy_worker *worker,
623 * Release a connection back to worker connection pool
624 * @param proxy_function calling proxy scheme (http, ajp, ...)
625 * @param conn acquired connection
626 * @param s current server record
627 * @return OK or HTTP_XXX error
628 * @note The connection will be closed if conn->close_on_release is set
630 PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function,
631 proxy_conn_rec *conn,
634 * Make a connection to the backend
635 * @param proxy_function calling proxy scheme (http, ajp, ...)
636 * @param conn acquired connection
637 * @param worker connection worker
638 * @param s current server record
639 * @return OK or HTTP_XXX error
640 * @note In case the socket already exists for conn, just check the link
643 PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
644 proxy_conn_rec *conn,
645 proxy_worker *worker,
648 * Make a connection record for backend connection
649 * @param proxy_function calling proxy scheme (http, ajp, ...)
650 * @param conn acquired connection
651 * @param c client connection record
652 * @param s current server record
653 * @return OK or HTTP_XXX error
655 PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
656 proxy_conn_rec *conn,
657 conn_rec *c, server_rec *s);
660 #if MODULE_MAGIC_NUMBER_MAJOR > 20020903
661 #define PROXY_HAS_SCOREBOARD 1
663 #define PROXY_HAS_SCOREBOARD 0
666 /* The number of dynamic workers that can be added when reconfiguring.
667 * If this limit is reached you must stop and restart the server.
669 #define PROXY_DYNAMIC_BALANCER_LIMIT 16
671 * Calculate number of maximum number of workers in scoreboard.
672 * @return number of workers to allocate in the scoreboard
674 int ap_proxy_lb_workers(void);
677 extern module PROXY_DECLARE_DATA proxy_module;
679 extern int PROXY_DECLARE_DATA proxy_lb_workers;
681 #endif /*MOD_PROXY_H*/