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;
176 typedef struct proxy_balancer proxy_balancer;
177 typedef struct proxy_worker proxy_worker;
178 typedef struct proxy_conn_pool proxy_conn_pool;
181 const char *p; /* The path */
182 int p_is_fnmatch; /* Is this path an fnmatch candidate? */
183 regex_t *r; /* Is this a regex? */
187 conn_rec *connection;
188 const char *hostname;
191 apr_pool_t *pool; /* Subpool used for creating socket */
192 apr_socket_t *sock; /* Connection socket */
193 apr_uint32_t flags; /* Conection flags */
194 int close; /* Close 'this' connection */
195 int close_on_recycle; /* Close the connection when returning to pool */
196 proxy_worker *worker; /* Connection pool this connection belogns to */
197 void *data; /* per scheme connection data */
201 float cache_completion; /* completion percentage */
202 int content_length; /* length of the content */
205 /* Connection pool */
206 struct proxy_conn_pool {
207 apr_pool_t *pool; /* The pool used in constructor and destructor calls */
208 apr_sockaddr_t *addr; /* Preparsed remote address info */
210 apr_reslist_t *res; /* Connection resource list */
212 proxy_conn_rec *conn; /* Single connection for prefork mpm's */
215 /* Worker configuration */
216 struct proxy_worker {
218 apr_time_t error_time; /* time of the last error */
219 apr_interval_time_t retry; /* retry interval */
220 int retries; /* number of retries on this worker */
221 int lbfactor; /* initial load balancing factor */
223 const char *scheme; /* scheme to use ajp|http|https */
224 const char *hostname; /* remote backend address */
226 int min; /* Desired minimum number of available connections */
227 int smax; /* Soft maximum on the total number of connections */
228 int hmax; /* Hard maximum on the total number of connections */
229 apr_interval_time_t ttl; /* maximum amount of time in seconds a connection
230 * may be available while exceeding the soft limit */
231 apr_interval_time_t timeout; /* connection timeout */
233 apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */
235 apr_size_t recv_buffer_size;
236 char recv_buffer_size_set;
237 apr_size_t io_buffer_size;
238 char io_buffer_size_set;
241 proxy_conn_pool *cp; /* Connection pool to use */
242 void *opaque; /* per scheme worker data */
245 /* Runtime worker status informations. Shared in scoreboard */
247 proxy_balancer *b; /* balancer containing this worker */
249 double lbfactor; /* dynamic lbfactor */
250 double lbsatus; /* Current lbstatus */
251 apr_size_t transfered; /* Number of bytes transfered to remote */
252 apr_size_t readed; /* Number of bytes readed from remote */
253 } proxy_runtime_worker;
255 struct proxy_balancer {
256 apr_array_header_t *workers; /* array of proxy_runtime_workers */
257 const char *name; /* name of the load balancer */
258 const char *sticky; /* sticky session identifier */
259 int sticky_force; /* Disable failover for sticky sessions */
260 apr_interval_time_t timeout; /* Timeout for waiting on free connection */
262 apr_thread_mutex_t *mutex; /* Thread lock for updating lb params */
268 /* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
269 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
272 #define PROXY_DECLARE(type) type
273 #define PROXY_DECLARE_NONSTD(type) type
274 #define PROXY_DECLARE_DATA
275 #elif defined(PROXY_DECLARE_STATIC)
276 #define PROXY_DECLARE(type) type __stdcall
277 #define PROXY_DECLARE_NONSTD(type) type
278 #define PROXY_DECLARE_DATA
279 #elif defined(PROXY_DECLARE_EXPORT)
280 #define PROXY_DECLARE(type) __declspec(dllexport) type __stdcall
281 #define PROXY_DECLARE_NONSTD(type) __declspec(dllexport) type
282 #define PROXY_DECLARE_DATA __declspec(dllexport)
284 #define PROXY_DECLARE(type) __declspec(dllimport) type __stdcall
285 #define PROXY_DECLARE_NONSTD(type) __declspec(dllimport) type
286 #define PROXY_DECLARE_DATA __declspec(dllimport)
290 * Hook an optional proxy hook. Unlike static hooks, this uses a macro
291 * instead of a function.
293 #define PROXY_OPTIONAL_HOOK(name,fn,pre,succ,order) \
294 APR_OPTIONAL_HOOK(proxy,name,fn,pre,succ,order)
296 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r,
297 proxy_worker *worker, proxy_server_conf *conf, char *url,
298 const char *proxyhost, apr_port_t proxyport))
299 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r,
302 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr))
303 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r))
307 * It will return the most suitable worker at the moment
308 * and coresponding balancer.
309 * The url is rewritten from balancer://cluster/uri to scheme://host:port/uri
310 * and then the scheme_handler is called.
313 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, pre_request, (proxy_worker **worker,
314 struct proxy_balancer **balancer,
316 proxy_server_conf *conf, char **url))
319 * It is called after request for updating runtime balancer status.
321 APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, post_request, (proxy_worker *worker,
322 struct proxy_balancer *balancer, request_rec *r,
323 proxy_server_conf *conf))
328 PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r);
329 PROXY_DECLARE(int) ap_proxy_hex2c(const char *x);
330 PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x);
331 PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
333 PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
334 char **passwordp, char **hostp, apr_port_t *port);
335 PROXY_DECLARE(const char *)ap_proxy_date_canon(apr_pool_t *p, const char *x);
336 PROXY_DECLARE(int) ap_proxy_liststr(const char *list, const char *val);
337 PROXY_DECLARE(char *)ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val);
338 PROXY_DECLARE(int) ap_proxy_hex2sec(const char *x);
339 PROXY_DECLARE(void) ap_proxy_sec2hex(int t, char *y);
340 PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message);
341 PROXY_DECLARE(int) ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p);
342 PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p);
343 PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p);
344 PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p);
345 PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
346 PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r);
347 PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos);
348 PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key);
349 /* DEPRECATED (will be replaced with ap_proxy_connect_backend */
350 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 *);
351 PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
352 PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
354 /* Connection pool API */
355 PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p, proxy_server_conf *conf, const char *url);
356 PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker, apr_pool_t *p, proxy_server_conf *conf, const char *url);
357 PROXY_DECLARE(struct proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p, proxy_server_conf *conf, const char *url);
358 PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer, apr_pool_t *p, proxy_server_conf *conf, const char *url);
359 PROXY_DECLARE(void) ap_proxy_add_worker_to_balancer(proxy_balancer *balancer, proxy_worker *worker);
360 PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker, proxy_balancer **balancer, request_rec *r, proxy_server_conf *conf, char **url);
361 PROXY_DECLARE(int) ap_proxy_determine_connection(apr_pool_t *p, request_rec *r, proxy_server_conf *conf, proxy_worker *worker, proxy_conn_rec *conn,
362 apr_pool_t *ppool, apr_uri_t *uri, char **url, const char *proxyname, apr_port_t proxyport,
363 char *server_portstr, int server_portstr_size);
364 PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function, proxy_conn_rec **conn, proxy_worker *worker, server_rec *s);
365 PROXY_DECLARE(int) ap_proxy_release_connection(const char *proxy_function, proxy_conn_rec *conn, server_rec *s);
366 PROXY_DECLARE(apr_status_t) ap_proxy_close_connection(proxy_conn_rec *conn);
367 PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function, proxy_conn_rec *conn, proxy_worker *worker, server_rec *s);
368 PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, proxy_conn_rec *conn, conn_rec *c, server_rec *s);
371 extern module PROXY_DECLARE_DATA proxy_module;
373 #endif /*MOD_PROXY_H*/