Apache HTTPD
mod_proxy.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17#include "mod_proxy.h"
18#include "mod_core.h"
19#include "apr_optional.h"
20#include "apr_strings.h"
21#include "scoreboard.h"
22#include "mod_status.h"
23#include "proxy_util.h"
24
25#if (MODULE_MAGIC_NUMBER_MAJOR > 20020903)
26#include "mod_ssl.h"
27#else
32 int proxy, int enable));
33#endif
34
35#ifndef MAX
36#define MAX(x,y) ((x) >= (y) ? (x) : (y))
37#endif
38
39/*
40 * We do health-checks only if that (sub)module is loaded in. This
41 * allows for us to continue as is w/o requiring mod_watchdog for
42 * those implementations which aren't using health checks
43 */
45
46/* Externals */
48 {NONE, "NONE", 1},
49 {TCP, "TCP", 1},
50 {OPTIONS, "OPTIONS", 1},
51 {HEAD, "HEAD", 1},
52 {GET, "GET", 1},
53 {CPING, "CPING", 0},
54 {PROVIDER, "PROVIDER", 0},
55 {OPTIONS11, "OPTIONS11", 1},
56 {HEAD11, "HEAD11", 1},
57 {GET11, "GET11", 1},
58 {EOT, NULL, 1}
59};
60
76
77static const char * const proxy_id = "proxy";
79
80/*
81 * A Web proxy module. Stages:
82 *
83 * translate_name: set filename to proxy:<URL>
84 * map_to_storage: run proxy_walk (rather than directory_walk/file_walk)
85 * can't trust directory_walk/file_walk since these are
86 * not in our filesystem. Prevents mod_http from serving
87 * the TRACE request we will set aside to handle later.
88 * fix_ups: convert the URL stored in the filename to the
89 * canonical form.
90 * handler: handle proxy requests
91 */
92
93/* -------------------------------------------------------------- */
94/* Translate the URL into a 'filename' */
95
96static const char *set_worker_param(apr_pool_t *p,
98 proxy_worker *worker,
99 const char *key,
100 const char *val)
101{
102
103 int ival;
105
106 if (!strcasecmp(key, "loadfactor")) {
107 /* Normalized load factor. Used with BalancerMember,
108 * it is a number between 1 and 100.
109 */
110 double fval = atof(val);
111 ival = fval * 100.0;
112 if (ival < 100 || ival > 10000)
113 return "LoadFactor must be a number between 1..100";
114 worker->s->lbfactor = ival;
115 }
116 else if (!strcasecmp(key, "retry")) {
117 /* If set it will give the retry timeout for the worker
118 * The default value is 60 seconds, meaning that if
119 * in error state, it will be retried after that timeout.
120 */
121 ival = atoi(val);
122 if (ival < 0)
123 return "Retry must be a positive value";
124 worker->s->retry = apr_time_from_sec(ival);
125 worker->s->retry_set = 1;
126 }
127 else if (!strcasecmp(key, "ttl")) {
128 /* Time in seconds that will destroy all the connections
129 * that exceed the smax
130 */
131 ival = atoi(val);
132 if (ival < 1)
133 return "TTL must be at least one second";
134 worker->s->ttl = apr_time_from_sec(ival);
135 }
136 else if (!strcasecmp(key, "min")) {
137 /* Initial number of connections to remote
138 */
139 ival = atoi(val);
140 if (ival < 0)
141 return "Min must be a positive number";
142 worker->s->min = ival;
143 }
144 else if (!strcasecmp(key, "max")) {
145 /* Maximum number of connections to remote
146 */
147 ival = atoi(val);
148 if (ival < 0)
149 return "Max must be a positive number";
150 worker->s->hmax = ival;
151 }
152 /* XXX: More intelligent naming needed */
153 else if (!strcasecmp(key, "smax")) {
154 /* Maximum number of connections to remote that
155 * will not be destroyed
156 */
157 ival = atoi(val);
158 if (ival < 0)
159 return "Smax must be a positive number";
160 worker->s->smax = ival;
161 }
162 else if (!strcasecmp(key, "acquire")) {
163 /* Acquire timeout in given unit (default is milliseconds).
164 * If set this will be the maximum time to
165 * wait for a free connection.
166 */
168 return "Acquire timeout has wrong format";
169 if (timeout < 1000)
170 return "Acquire must be at least one millisecond";
171 worker->s->acquire = timeout;
172 worker->s->acquire_set = 1;
173 }
174 else if (!strcasecmp(key, "timeout")) {
175 /* Connection timeout in seconds.
176 * Defaults to server timeout.
177 */
178 ival = atoi(val);
179 if (ival < 1)
180 return "Timeout must be at least one second";
181 worker->s->timeout = apr_time_from_sec(ival);
182 worker->s->timeout_set = 1;
183 }
184 else if (!strcasecmp(key, "iobuffersize")) {
185 long s = atol(val);
186 if (s < 512 && s) {
187 return "IOBufferSize must be >= 512 bytes, or 0 for system default.";
188 }
189 worker->s->io_buffer_size = (s ? s : AP_IOBUFSIZE);
190 worker->s->io_buffer_size_set = 1;
191 }
192 else if (!strcasecmp(key, "receivebuffersize")) {
193 ival = atoi(val);
194 if (ival < 512 && ival != 0) {
195 return "ReceiveBufferSize must be >= 512 bytes, or 0 for system default.";
196 }
197 worker->s->recv_buffer_size = ival;
198 worker->s->recv_buffer_size_set = 1;
199 }
200 else if (!strcasecmp(key, "keepalive")) {
201 if (!strcasecmp(val, "on"))
202 worker->s->keepalive = 1;
203 else if (!strcasecmp(val, "off"))
204 worker->s->keepalive = 0;
205 else
206 return "KeepAlive must be On|Off";
207 worker->s->keepalive_set = 1;
208 }
209 else if (!strcasecmp(key, "disablereuse")) {
210 if (!strcasecmp(val, "on"))
211 worker->s->disablereuse = 1;
212 else if (!strcasecmp(val, "off"))
213 worker->s->disablereuse = 0;
214 else
215 return "DisableReuse must be On|Off";
216 worker->s->disablereuse_set = 1;
217 }
218 else if (!strcasecmp(key, "enablereuse")) {
219 if (!strcasecmp(val, "on"))
220 worker->s->disablereuse = 0;
221 else if (!strcasecmp(val, "off"))
222 worker->s->disablereuse = 1;
223 else
224 return "EnableReuse must be On|Off";
225 worker->s->disablereuse_set = 1;
226 }
227 else if (!strcasecmp(key, "addressttl")) {
228 /* Address TTL in seconds
229 */
231 if (strcmp(val, "-1") == 0) {
232 worker->s->address_ttl = -1;
233 }
236 && (ttl % apr_time_from_sec(1)) == 0) {
237 worker->s->address_ttl = apr_time_sec(ttl);
238 }
239 else {
240 return "AddressTTL must be -1 or a number of seconds not "
241 "exceeding " APR_STRINGIFY(APR_INT32_MAX);
242 }
243 worker->s->address_ttl_set = 1;
244 }
245 else if (!strcasecmp(key, "route")) {
246 /* Worker route.
247 */
248 if (strlen(val) >= sizeof(worker->s->route))
249 return apr_psprintf(p, "Route length must be < %d characters",
250 (int)sizeof(worker->s->route));
251 PROXY_STRNCPY(worker->s->route, val);
252 }
253 else if (!strcasecmp(key, "redirect")) {
254 /* Worker redirection route.
255 */
256 if (strlen(val) >= sizeof(worker->s->redirect))
257 return apr_psprintf(p, "Redirect length must be < %d characters",
258 (int)sizeof(worker->s->redirect));
259 PROXY_STRNCPY(worker->s->redirect, val);
260 }
261 else if (!strcasecmp(key, "status")) {
262 const char *v;
263 int mode = 1;
264 apr_status_t rv;
265 /* Worker status.
266 */
267 for (v = val; *v; v++) {
268 if (*v == '+') {
269 mode = 1;
270 v++;
271 }
272 else if (*v == '-') {
273 mode = 0;
274 v++;
275 }
276 rv = ap_proxy_set_wstatus(*v, mode, worker);
277 if (rv != APR_SUCCESS)
278 return "Unknown status parameter option";
279 }
280 }
281 else if (!strcasecmp(key, "flushpackets")) {
282 if (!strcasecmp(val, "on"))
283 worker->s->flush_packets = flush_on;
284 else if (!strcasecmp(val, "off"))
285 worker->s->flush_packets = flush_off;
286 else if (!strcasecmp(val, "auto"))
287 worker->s->flush_packets = flush_auto;
288 else
289 return "flushpackets must be on|off|auto";
290 }
291 else if (!strcasecmp(key, "flushwait")) {
292 ival = atoi(val);
293 if (ival > 1000 || ival < 0) {
294 return "flushwait must be <= 1000, or 0 for system default of 10 millseconds.";
295 }
296 if (ival == 0)
297 worker->s->flush_wait = PROXY_FLUSH_WAIT;
298 else
299 worker->s->flush_wait = ival * 1000; /* change to microseconds */
300 }
301 else if (!strcasecmp(key, "ping")) {
302 /* Ping/Pong timeout in given unit (default is second).
303 */
305 return "Ping/Pong timeout has wrong format";
306 if (timeout < 1000)
307 return "Ping/Pong timeout must be at least one millisecond";
308 worker->s->ping_timeout = timeout;
309 worker->s->ping_timeout_set = 1;
310 }
311 else if (!strcasecmp(key, "lbset")) {
312 ival = atoi(val);
313 if (ival < 0 || ival > 99)
314 return "lbset must be between 0 and 99";
315 worker->s->lbset = ival;
316 }
317 else if (!strcasecmp(key, "connectiontimeout")) {
318 /* Request timeout in given unit (default is second).
319 * Defaults to connection timeout
320 */
322 return "Connectiontimeout has wrong format";
323 if (timeout < 1000)
324 return "Connectiontimeout must be at least one millisecond.";
325 worker->s->conn_timeout = timeout;
326 worker->s->conn_timeout_set = 1;
327 }
328 else if (!strcasecmp(key, "flusher")) {
329 if (PROXY_STRNCPY(worker->s->flusher, val) != APR_SUCCESS) {
330 return apr_psprintf(p, "flusher name length must be < %d characters",
331 (int)sizeof(worker->s->flusher));
332 }
333 }
334 else if (!strcasecmp(key, "upgrade")) {
335 if (PROXY_STRNCPY(worker->s->upgrade,
336 strcasecmp(val, "ANY") ? val : "*") != APR_SUCCESS) {
337 return apr_psprintf(p, "upgrade protocol length must be < %d characters",
338 (int)sizeof(worker->s->upgrade));
339 }
340 }
341 else if (!strcasecmp(key, "responsefieldsize")) {
342 long s = atol(val);
343 if (s < 0) {
344 return "ResponseFieldSize must be greater than 0 bytes, or 0 for system default.";
345 }
346 worker->s->response_field_size = (s ? s : HUGE_STRING_LEN);
347 worker->s->response_field_size_set = 1;
348 }
349 else if (!strcasecmp(key, "secret")) {
350 if (PROXY_STRNCPY(worker->s->secret, val) != APR_SUCCESS) {
351 return apr_psprintf(p, "Secret length must be < %d characters",
352 (int)sizeof(worker->s->secret));
353 }
354 }
355 else {
357 return set_worker_hc_param_f(p, s, worker, key, val, NULL);
358 } else {
359 return "unknown Worker parameter";
360 }
361 }
362 return NULL;
363}
364
365static const char *set_balancer_param(proxy_server_conf *conf,
366 apr_pool_t *p,
367 proxy_balancer *balancer,
368 const char *key,
369 const char *val)
370{
371
372 int ival;
373 if (!strcasecmp(key, "stickysession")) {
374 char *path;
375 /* Balancer sticky session name.
376 * Set to something like JSESSIONID or
377 * PHPSESSIONID, etc..,
378 */
379 if (strlen(val) >= sizeof(balancer->s->sticky_path))
380 apr_psprintf(p, "stickysession length must be < %d characters",
381 (int)sizeof(balancer->s->sticky_path));
382 PROXY_STRNCPY(balancer->s->sticky_path, val);
383 PROXY_STRNCPY(balancer->s->sticky, val);
384
385 if ((path = strchr((char *)balancer->s->sticky, '|'))) {
386 *path++ = '\0';
387 PROXY_STRNCPY(balancer->s->sticky_path, path);
388 }
389 }
390 else if (!strcasecmp(key, "stickysessionsep")) {
391 /* separator/delimiter for sessionid and route,
392 * normally '.'
393 */
394 if (strlen(val) != 1) {
395 if (!strcasecmp(val, "off"))
396 balancer->s->sticky_separator = 0;
397 else
398 return "stickysessionsep must be a single character or Off";
399 }
400 else
401 balancer->s->sticky_separator = *val;
402 balancer->s->sticky_separator_set = 1;
403 }
404 else if (!strcasecmp(key, "nofailover")) {
405 /* If set to 'on' the session will break
406 * if the worker is in error state or
407 * disabled.
408 */
409 if (!strcasecmp(val, "on"))
410 balancer->s->sticky_force = 1;
411 else if (!strcasecmp(val, "off"))
412 balancer->s->sticky_force = 0;
413 else
414 return "failover must be On|Off";
415 balancer->s->sticky_force_set = 1;
416 }
417 else if (!strcasecmp(key, "timeout")) {
418 /* Balancer timeout in seconds.
419 * If set this will be the maximum time to
420 * wait for a free worker.
421 * Default is not to wait.
422 */
423 ival = atoi(val);
424 if (ival < 1)
425 return "timeout must be at least one second";
426 balancer->s->timeout = apr_time_from_sec(ival);
427 }
428 else if (!strcasecmp(key, "maxattempts")) {
429 /* Maximum number of failover attempts before
430 * giving up.
431 */
432 ival = atoi(val);
433 if (ival < 0)
434 return "maximum number of attempts must be a positive number";
435 balancer->s->max_attempts = ival;
436 balancer->s->max_attempts_set = 1;
437 }
438 else if (!strcasecmp(key, "lbmethod")) {
439 proxy_balancer_method *provider;
440 if (strlen(val) > (sizeof(balancer->s->lbpname)-1))
441 return "unknown lbmethod";
442 provider = ap_lookup_provider(PROXY_LBMETHOD, val, "0");
443 if (provider) {
444 balancer->lbmethod = provider;
445 if (PROXY_STRNCPY(balancer->s->lbpname, val) == APR_SUCCESS) {
446 balancer->lbmethod_set = 1;
447 return NULL;
448 }
449 else {
450 return "lbmethod name too large";
451 }
452 }
453 return "unknown lbmethod";
454 }
455 else if (!strcasecmp(key, "scolonpathdelim")) {
456 /* If set to 'on' then ';' will also be
457 * used as a session path separator/delim (ala
458 * mod_jk)
459 */
460 if (!strcasecmp(val, "on"))
461 balancer->s->scolonsep = 1;
462 else if (!strcasecmp(val, "off"))
463 balancer->s->scolonsep = 0;
464 else
465 return "scolonpathdelim must be On|Off";
466 balancer->s->scolonsep_set = 1;
467 }
468 else if (!strcasecmp(key, "failonstatus")) {
469 char *val_split;
470 char *status;
471 char *tok_state;
472
474
475 balancer->errstatuses = apr_array_make(p, 1, sizeof(int));
476
478 while (status != NULL) {
479 ival = atoi(status);
481 *(int *)apr_array_push(balancer->errstatuses) = ival;
482 }
483 else {
484 return "failonstatus must be one or more HTTP response codes";
485 }
486 status = apr_strtok(NULL, ", ", &tok_state);
487 }
488
489 }
490 else if (!strcasecmp(key, "failontimeout")) {
491 if (!strcasecmp(val, "on"))
492 balancer->failontimeout = 1;
493 else if (!strcasecmp(val, "off"))
494 balancer->failontimeout = 0;
495 else
496 return "failontimeout must be On|Off";
497 balancer->failontimeout_set = 1;
498 }
499 else if (!strcasecmp(key, "nonce")) {
500 if (!strcasecmp(val, "None")) {
501 *balancer->s->nonce = '\0';
502 }
503 else {
504 if (PROXY_STRNCPY(balancer->s->nonce, val) != APR_SUCCESS) {
505 return "Provided nonce is too large";
506 }
507 }
508 balancer->s->nonce_set = 1;
509 }
510 else if (!strcasecmp(key, "growth")) {
511 ival = atoi(val);
512 if (ival < 1 || ival > 100) /* arbitrary limit here */
513 return "growth must be between 1 and 100";
514 balancer->growth = ival;
515 balancer->growth_set = 1;
516 }
517 else if (!strcasecmp(key, "forcerecovery")) {
518 if (!strcasecmp(val, "on"))
519 balancer->s->forcerecovery = 1;
520 else if (!strcasecmp(val, "off"))
521 balancer->s->forcerecovery = 0;
522 else
523 return "forcerecovery must be On|Off";
524 balancer->s->forcerecovery_set = 1;
525 }
526 else {
527 return "unknown Balancer parameter";
528 }
529 return NULL;
530}
531
532static int alias_match(const char *uri, const char *alias_fakename)
533{
534 const char *end_fakename = alias_fakename + strlen(alias_fakename);
535 const char *aliasp = alias_fakename, *urip = uri;
536 const char *end_uri = uri + strlen(uri);
537
538 while (aliasp < end_fakename && urip < end_uri) {
539 if (*aliasp == '/') {
540 /* any number of '/' in the alias matches any number in
541 * the supplied URI, but there must be at least one...
542 */
543 if (*urip != '/')
544 return 0;
545
546 while (*aliasp == '/')
547 ++aliasp;
548 while (*urip == '/')
549 ++urip;
550 }
551 else {
552 /* Other characters are compared literally */
553 if (*urip++ != *aliasp++)
554 return 0;
555 }
556 }
557
558 /* fixup badly encoded stuff (e.g. % as last character) */
559 if (aliasp > end_fakename) {
561 }
562 if (urip > end_uri) {
563 urip = end_uri;
564 }
565
566 /* We reach the end of the uri before the end of "alias_fakename"
567 * for example uri is "/" and alias_fakename "/examples"
568 */
569 if (urip == end_uri && aliasp != end_fakename) {
570 return 0;
571 }
572
573 /* Check last alias path component matched all the way */
574 if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/')
575 return 0;
576
577 /* Return number of characters from URI which matched (may be
578 * greater than length of alias, since we may have matched
579 * doubled slashes)
580 */
581
582 return urip - uri;
583}
584
585/*
586 * Inspired by mod_jk's jk_servlet_normalize().
587 */
589 const char **urip,
590 const char *alias)
591{
592 char *map;
593 const char *uri = *urip;
596 int alias_depth = 0, depth;
597
598 /* Both uri and alias should start with '/' */
599 if (uri[0] != '/' || alias[0] != '/') {
600 return 0;
601 }
602
603 stack = apr_array_make(p, 5, sizeof(int));
604 map = apr_palloc(p, strlen(uri) + 1);
605 map[0] = '/';
606 map[1] = '\0';
607
609 while (uri[uri_pos] != '\0') {
610 /* Remove path parameters ;foo=bar/ from any path segment */
611 if (uri[uri_pos] == ';') {
612 do {
613 uri_pos++;
614 } while (uri[uri_pos] != '/' && uri[uri_pos] != '\0');
615 continue;
616 }
617
618 if (map[map_pos - 1] == '/') {
619 /* Collapse ///// sequences to / */
620 if (uri[uri_pos] == '/') {
621 do {
622 uri_pos++;
623 } while (uri[uri_pos] == '/');
624 continue;
625 }
626
627 if (uri[uri_pos] == '.') {
628 /* Remove /./ segments */
629 if (uri[uri_pos + 1] == '/'
630 || uri[uri_pos + 1] == ';'
631 || uri[uri_pos + 1] == '\0') {
632 uri_pos++;
633 if (uri[uri_pos] == '/') {
634 uri_pos++;
635 }
636 continue;
637 }
638
639 /* Remove /xx/../ segments */
640 if (uri[uri_pos + 1] == '.'
641 && (uri[uri_pos + 2] == '/'
642 || uri[uri_pos + 2] == ';'
643 || uri[uri_pos + 2] == '\0')) {
644 /* Wind map segment back the previous one */
645 if (map_pos == 1) {
646 /* Above root */
647 return 0;
648 }
649 do {
650 map_pos--;
651 } while (map[map_pos - 1] != '/');
652 map[map_pos] = '\0';
653
654 /* Wind alias segment back, unless in deeper segment */
655 if (alias_depth == stack->nelts) {
656 if (alias[alias_pos] == '\0') {
657 alias_pos--;
658 }
659 while (alias_pos > 0 && alias[alias_pos] == '/') {
660 alias_pos--;
661 }
662 while (alias_pos > 0 && alias[alias_pos - 1] != '/') {
663 alias_pos--;
664 }
666 alias_depth--;
667 }
669
670 /* Move uri forward to the next segment */
671 uri_pos += 2;
672 if (uri[uri_pos] == '/') {
673 uri_pos++;
674 }
675 first_pos = 0;
676 continue;
677 }
678 }
679 if (first_pos) {
680 while (uri[first_pos] == '/') {
681 first_pos++;
682 }
683 }
684
685 /* New segment */
687 if (alias[alias_pos] != '\0') {
688 if (alias[alias_pos - 1] != '/') {
689 /* Remain in pair with uri segments */
690 do {
691 alias_pos++;
692 } while (alias[alias_pos - 1] != '/' && alias[alias_pos]);
693 }
694 while (alias[alias_pos] == '/') {
695 alias_pos++;
696 }
697 if (alias[alias_pos] != '\0') {
698 alias_depth++;
699 }
700 }
701 }
702
703 if (alias[alias_pos] != '\0') {
704 int *match = &APR_ARRAY_IDX(stack, alias_depth - 1, int);
705 if (*match) {
706 if (alias[alias_pos] != uri[uri_pos]) {
707 /* Current segment does not match */
708 *match = 0;
709 }
710 else if (alias[alias_pos + 1] == '\0'
711 && alias[alias_pos] != '/') {
712 if (uri[uri_pos + 1] == ';') {
713 /* We'll preserve the parameters of the last
714 * segment if it does not end with '/', so mark
715 * the match as negative for below handling.
716 */
717 *match = -(uri_pos + 1);
718 }
719 else if (uri[uri_pos + 1] != '/'
720 && uri[uri_pos + 1] != '\0') {
721 /* Last segment does not match all the way */
722 *match = 0;
723 }
724 }
725 }
726 /* Don't go past the segment if the uri isn't there yet */
727 if (alias[alias_pos] != '/' || uri[uri_pos] == '/') {
728 alias_pos++;
729 }
730 }
731
732 if (uri[uri_pos] == '/') {
733 first_pos = uri_pos + 1;
734 }
735 map[map_pos++] = uri[uri_pos++];
736 map[map_pos] = '\0';
737 }
738
739 /* Can't reach the end of uri before the end of the alias,
740 * for example if uri is "/" and alias is "/examples"
741 */
742 if (alias[alias_pos] != '\0') {
743 return 0;
744 }
745
746 /* Check whether each alias segment matched */
747 for (depth = 0; depth < alias_depth; ++depth) {
748 if (!APR_ARRAY_IDX(stack, depth, int)) {
749 return 0;
750 }
751 }
752
753 /* If alias_depth == stack->nelts we have a full match, i.e.
754 * uri == alias so we can return uri_pos as is (the end of uri)
755 */
757 /* Return the segment following the alias */
759 if (alias_depth) {
760 /* But if the last segment of the alias does not end with '/'
761 * and the corresponding segment of the uri has parameters,
762 * we want to forward those parameters (see above for the
763 * negative pos trick/mark).
764 */
765 int pos = APR_ARRAY_IDX(stack, alias_depth - 1, int);
766 if (pos < 0) {
767 uri_pos = -pos;
768 }
769 }
770 }
771 /* If the alias lacks a trailing slash, take it from the uri (if any) */
772 if (alias[alias_pos - 1] != '/' && uri[uri_pos - 1] == '/') {
773 uri_pos--;
774 }
775
776 *urip = map;
777 return uri_pos;
778}
779
780/* Detect if an absoluteURI should be proxied or not. Note that we
781 * have to do this during this phase because later phases are
782 * "short-circuiting"... i.e. translate_names will end when the first
783 * module returns OK. So for example, if the request is something like:
784 *
785 * GET http://othervhost/cgi-bin/printenv HTTP/1.0
786 *
787 * mod_alias will notice the /cgi-bin part and ScriptAlias it and
788 * short-circuit the proxy... just because of the ordering in the
789 * configuration file.
790 */
792{
793 void *sconf = r->server->module_config;
794 proxy_server_conf *conf =
795 (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
796
797 /* Ick... msvc (perhaps others) promotes ternary short results to int */
798
799 if (conf->req && r->parsed_uri.scheme) {
800 /* but it might be something vhosted */
801 if (!r->parsed_uri.hostname
805 ? r->parsed_uri.port
806 : ap_default_port(r)))) {
808 r->uri = r->unparsed_uri;
809 r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL);
810 r->handler = "proxy-server";
811 }
812 }
813 /* We need special treatment for CONNECT proxying: it has no scheme part */
814 else if (conf->req && r->method_number == M_CONNECT
816 && r->parsed_uri.port_str) {
818 r->uri = r->unparsed_uri;
819 r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL);
820 r->handler = "proxy-server";
821 }
822 return DECLINED;
823}
824
826 proxy_dir_conf *dconf)
827{
828 int len;
829 const char *fake;
830 const char *real;
833 char *found = NULL;
834 int mismatch = 0;
835 unsigned int nocanon = ent->flags & PROXYPASS_NOCANON;
836 const char *use_uri = nocanon ? r->unparsed_uri : r->uri;
837 const char *servlet_uri = NULL;
838
839 if (dconf && (dconf->interpolate_env == 1) && (ent->flags & PROXYPASS_INTERPOLATE)) {
840 fake = ap_proxy_interpolate(r, ent->fake);
841 real = ap_proxy_interpolate(r, ent->real);
842 }
843 else {
844 fake = ent->fake;
845 real = ent->real;
846 }
847
849 "attempting to match URI path '%s' against %s '%s' for "
850 "proxying", r->uri, (ent->regex ? "pattern" : "prefix"),
851 fake);
852
853 if (ent->regex) {
854 if (!ap_regexec(ent->regex, r->uri, AP_MAX_REG_MATCH, regm, 0)) {
855 if ((real[0] == '!') && (real[1] == '\0')) {
857 "proxying is explicitly disabled for URI path "
858 "'%s'; declining", r->uri);
859 return DECLINED;
860 }
861 /* test that we haven't reduced the URI */
862 if (nocanon && ap_regexec(ent->regex, r->unparsed_uri,
863 AP_MAX_REG_MATCH, reg1, 0)) {
864 mismatch = 1;
865 use_uri = r->uri;
866 }
868 (use_uri == r->uri) ? regm : reg1);
869 if (!found) {
871 "Substitution in regular expression failed. "
872 "Replacement too long?");
874 }
875
876 /* Note: The strcmp() below catches cases where there
877 * was no regex substitution. This is so cases like:
878 *
879 * ProxyPassMatch \.gif balancer://foo
880 *
881 * will work "as expected". The upshot is that the 2
882 * directives below act the exact same way (ie: $1 is implied):
883 *
884 * ProxyPassMatch ^(/.*\.gif)$ balancer://foo
885 * ProxyPassMatch ^(/.*\.gif)$ balancer://foo$1
886 *
887 * which may be confusing.
888 */
889 if (strcmp(found, real) != 0) {
890 found = apr_pstrcat(r->pool, "proxy:", found, NULL);
891 }
892 else {
893 found = apr_pstrcat(r->pool, "proxy:", real, use_uri, NULL);
894 }
895 }
896 }
897 else {
899 servlet_uri = r->uri;
901 nocanon = 0; /* ignored since servlet's normalization applies */
902 }
903 else {
904 len = alias_match(r->uri, fake);
905 }
906
907 if (len != 0) {
908 if ((real[0] == '!') && (real[1] == '\0')) {
910 "proxying is explicitly disabled for URI path "
911 "'%s'; declining", r->uri);
912 return DECLINED;
913 }
914 if (nocanon && len != alias_match(r->unparsed_uri, fake)) {
915 mismatch = 1;
916 use_uri = r->uri;
917 }
918 found = apr_pstrcat(r->pool, "proxy:", real, use_uri + len, NULL);
919 }
920 }
921 if (mismatch) {
922 /* We made a reducing transformation, so we can't safely use
923 * unparsed_uri. Safe fallback is to ignore nocanon.
924 */
926 "Unescaped URL path matched ProxyPass; ignoring unsafe nocanon");
927 }
928
929 if (found) {
930 unsigned int encoded = ent->flags & PROXYPASS_MAP_ENCODED;
931
932 /* A proxy module is assigned this URL, check whether it's interested
933 * in the request itself (e.g. proxy_wstunnel cares about Upgrade
934 * requests only, and could hand over to proxy_http otherwise).
935 */
936 int rc = proxy_run_check_trans(r, found + 6);
937 if (rc != OK && rc != DECLINED) {
938 return HTTP_CONTINUE;
939 }
940
941 r->filename = found;
942 r->handler = "proxy-server";
944 if (nocanon && !mismatch) {
945 /* mod_proxy_http needs to be told. Different module. */
946 apr_table_setn(r->notes, "proxy-nocanon", "1");
947 }
948 if (ent->flags & PROXYPASS_NOQUERY) {
949 apr_table_setn(r->notes, "proxy-noquery", "1");
950 }
951 if (encoded) {
952 apr_table_setn(r->notes, "proxy-noencode", "1");
953 }
954
955 if (servlet_uri) {
957 "Servlet path '%s' (%s) matches proxy handler '%s'",
959 /* Apply servlet normalization to r->uri so that <Location> or any
960 * directory context match does not have to handle path parameters.
961 * We change r->uri in-place so that r->parsed_uri.path is updated
962 * too. Since normalized servlet_uri is necessarily shorter than
963 * the original r->uri, strcpy() is fine.
964 */
965 AP_DEBUG_ASSERT(strlen(r->uri) >= strlen(servlet_uri));
967 }
968 else {
970 "URI path '%s' matches proxy handler '%s'", r->uri,
971 found);
972 }
973 return (encoded) ? DONE : OK;
974 }
975
976 return HTTP_CONTINUE;
977}
978
980{
981 int i, enc;
982 struct proxy_alias *ent;
983 proxy_dir_conf *dconf;
984 proxy_server_conf *conf;
985
986 if (r->proxyreq) {
987 /* someone has already set up the proxy, it was possibly ourselves
988 * in proxy_detect (DONE will prevent further decoding of r->uri,
989 * only if proxyreq is set before pre_trans already).
990 */
991 return pre_trans ? DONE : OK;
992 }
993
994 /* In early pre_trans hook, r->uri was not manipulated yet so we are
995 * compliant with RFC1945 at this point. Otherwise, it probably isn't
996 * an issue because this is a hybrid proxy/origin server.
997 */
998
999 dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
1001 &proxy_module);
1002
1003 /* Always and only do PROXY_MAP_ENCODED mapping in pre_trans, when
1004 * r->uri is still encoded, or we might consider for instance that
1005 * a decoded sub-delim is now a delimiter (e.g. "%3B" => ';' for
1006 * path parameters), which it's not.
1007 */
1008 if ((pre_trans && !conf->map_encoded_one)
1009 || (!pre_trans && conf->map_encoded_all)) {
1010 /* Fast path, nothing at this stage */
1011 return DECLINED;
1012 }
1013
1014 if ((r->unparsed_uri[0] == '*' && r->unparsed_uri[1] == '\0')
1015 || !r->uri || r->uri[0] != '/') {
1016 return DECLINED;
1017 }
1018
1019 if (apr_table_get(r->subprocess_env, "no-proxy")) {
1020 return DECLINED;
1021 }
1022
1023 /* short way - this location is reverse proxied? */
1024 if (dconf->alias) {
1025 enc = (dconf->alias->flags & PROXYPASS_MAP_ENCODED) != 0;
1026 if (!(pre_trans ^ enc)) {
1027 int rv = ap_proxy_trans_match(r, dconf->alias, dconf);
1028 if (rv != HTTP_CONTINUE) {
1029 return rv;
1030 }
1031 }
1032 }
1033
1034 /* long way - walk the list of aliases, find a match */
1035 for (i = 0; i < conf->aliases->nelts; i++) {
1036 ent = &((struct proxy_alias *)conf->aliases->elts)[i];
1037 enc = (ent->flags & PROXYPASS_MAP_ENCODED) != 0;
1038 if (!(pre_trans ^ enc)) {
1039 int rv = ap_proxy_trans_match(r, ent, dconf);
1040 if (rv != HTTP_CONTINUE) {
1041 return rv;
1042 }
1043 }
1044 }
1045
1046 return DECLINED;
1047}
1048
1050{
1051 return proxy_trans(r, 1);
1052}
1053
1055{
1056 return proxy_trans(r, 0);
1057}
1058
1060{
1062 &proxy_module);
1064 ap_conf_vector_t **sec_proxy = (ap_conf_vector_t **) sconf->sec_proxy->elts;
1067 int num_sec = sconf->sec_proxy->nelts;
1068 /* XXX: shouldn't we use URI here? Canonicalize it first?
1069 * Pass over "proxy:" prefix
1070 */
1071 const char *proxyname = r->filename + 6;
1072 int j;
1074
1075 for (j = 0; j < num_sec; ++j)
1076 {
1077 int nmatch = 0;
1078 int i;
1080
1081 entry_config = sec_proxy[j];
1083
1084 if (entry_proxy->r) {
1085
1086 if (entry_proxy->refs && entry_proxy->refs->nelts) {
1087 if (!rxpool) {
1089 apr_pool_tag(rxpool, "proxy_rxpool");
1090 }
1091 nmatch = entry_proxy->refs->nelts;
1093 }
1094
1096 continue;
1097 }
1098
1099 for (i = 0; i < nmatch; i++) {
1100 if (pmatch[i].rm_so >= 0 && pmatch[i].rm_eo >= 0 &&
1101 ((const char **)entry_proxy->refs->elts)[i]) {
1103 ((const char **)entry_proxy->refs->elts)[i],
1106 pmatch[i].rm_eo - pmatch[i].rm_so));
1107 }
1108 }
1109 }
1110
1111 else if (
1112 /* XXX: What about case insensitive matching ???
1113 * Compare regex, fnmatch or string as appropriate
1114 * If the entry doesn't relate, then continue
1115 */
1116 entry_proxy->p_is_fnmatch ? apr_fnmatch(entry_proxy->p,
1117 proxyname, 0) :
1119 strlen(entry_proxy->p))) {
1120 continue;
1121 }
1123 entry_config);
1124 }
1125
1127
1128 if (rxpool) {
1130 }
1131
1132 return OK;
1133}
1134
1136{
1137 int access_status;
1138
1139 if (!r->proxyreq || !r->filename || strncmp(r->filename, "proxy:", 6) != 0)
1140 return DECLINED;
1141
1142 /* Don't let the core or mod_http map_to_storage hooks handle this,
1143 * We don't need directory/file_walk, and we want to TRACE on our own.
1144 */
1145 if ((access_status = proxy_walk(r))) {
1147 return access_status;
1148 }
1149
1150 return OK;
1151}
1152
1153/* -------------------------------------------------------------- */
1154/* Fixup the filename */
1155
1156/*
1157 * Canonicalise the URL
1158 */
1160{
1161 if (!r->proxyreq || !r->filename || strncmp(r->filename, "proxy:", 6) != 0)
1162 return DECLINED;
1163
1164 /* XXX: Shouldn't we try this before we run the proxy_walk? */
1165
1166 return ap_proxy_canon_url(r);
1167}
1168
1169/* Send a redirection if the request contains a hostname which is not */
1170/* fully qualified, i.e. doesn't have a domain name appended. Some proxy */
1171/* servers like Netscape's allow this and access hosts from the local */
1172/* domain in this case. I think it is better to redirect to a FQDN, since */
1173/* these will later be found in the bookmarks files. */
1174/* The "ProxyDomain" directive determines what domain will be appended */
1175static int proxy_needsdomain(request_rec *r, const char *url, const char *domain)
1176{
1177 char *nuri;
1178 const char *ref;
1179
1180 /* We only want to worry about GETs */
1181 if (!r->proxyreq || r->method_number != M_GET || !r->parsed_uri.hostname)
1182 return DECLINED;
1183
1184 /* If host does contain a dot already, or it is "localhost", decline */
1185 if (strchr(r->parsed_uri.hostname, '.') != NULL /* has domain, or IPv4 literal */
1186 || strchr(r->parsed_uri.hostname, ':') != NULL /* IPv6 literal */
1187 || ap_cstr_casecmp(r->parsed_uri.hostname, "localhost") == 0)
1188 return DECLINED; /* host name has a dot already */
1189
1190 ref = apr_table_get(r->headers_in, "Referer");
1191
1192 /* Reassemble the request, but insert the domain after the host name */
1193 /* Note that the domain name always starts with a dot */
1195 domain, NULL);
1197 &r->parsed_uri,
1199
1200 apr_table_setn(r->headers_out, "Location", nuri);
1202 "Domain missing: %s sent to %s%s%s", r->uri,
1205 ref ? " from " : "", ref ? ref : "");
1206
1208}
1209
1210/* -------------------------------------------------------------- */
1211/* Invoke handler */
1212
1214{
1215 char *uri, *scheme, *p;
1216 const char *p2;
1217 void *sconf = r->server->module_config;
1219 ap_get_module_config(sconf, &proxy_module);
1220 apr_array_header_t *proxies = conf->proxies;
1221 struct proxy_remote *ents = (struct proxy_remote *) proxies->elts;
1222 int rc = DECLINED, access_status, i;
1223 int direct_connect = 0;
1224 const char *str;
1225 apr_int64_t maxfwd;
1226 proxy_balancer *balancer = NULL;
1227 proxy_worker *worker = NULL;
1228 int attempts = 0, max_attempts = 0;
1229 struct dirconn_entry *list = (struct dirconn_entry *)conf->dirconn->elts;
1230 int saved_status;
1231
1232 /* is this for us? */
1233 if (!r->filename) {
1234 return DECLINED;
1235 }
1236
1237 /* We may have forced the proxy handler via config or .htaccess */
1238 if (!r->proxyreq && r->handler && strncmp(r->handler, "proxy:", 6) == 0) {
1239 char *old_filename = r->filename;
1240
1243
1244 /* Still need to canonicalize r->filename */
1246 if (rc != OK) {
1248 r->proxyreq = 0;
1249 }
1250 }
1251 else if (r->proxyreq && strncmp(r->filename, "proxy:", 6) == 0) {
1252 rc = OK;
1253 }
1254 if (rc != OK) {
1255 return rc;
1256 }
1257
1258 uri = r->filename + 6;
1259 p = strchr(uri, ':');
1260 if (p == NULL) {
1262 "proxy_handler no URL in %s", r->filename);
1263 return HTTP_BAD_REQUEST;
1264 }
1265 scheme = apr_pstrmemdup(r->pool, uri, p - uri);
1266
1267 /* handle max-forwards / OPTIONS / TRACE */
1268 if ((str = apr_table_get(r->headers_in, "Max-Forwards"))) {
1269 char *end;
1270 maxfwd = apr_strtoi64(str, &end, 10);
1271 if (maxfwd < 0 || maxfwd == APR_INT64_MAX || *end) {
1273 "Max-Forwards value '%s' could not be parsed", str);
1275 "Max-Forwards request header could not be parsed");
1276 }
1277 else if (maxfwd == 0) {
1278 switch (r->method_number) {
1279 case M_TRACE: {
1280 int access_status;
1284 return OK;
1285 }
1286 case M_OPTIONS: {
1287 int access_status;
1291 return OK;
1292 }
1293 default: {
1295 "Max-Forwards has reached zero - proxy loop?");
1296 }
1297 }
1298 }
1299 maxfwd = (maxfwd > 0) ? maxfwd - 1 : 0;
1300 }
1301 else {
1302 /* set configured max-forwards */
1303 maxfwd = conf->maxfwd;
1304 }
1305 if (maxfwd >= 0) {
1306 apr_table_setn(r->headers_in, "Max-Forwards",
1307 apr_psprintf(r->pool, "%" APR_INT64_T_FMT, maxfwd));
1308 }
1309
1310 if (r->method_number == M_TRACE) {
1313
1314 if (coreconf->trace_enable == AP_TRACE_DISABLE)
1315 {
1316 /* Allow "error-notes" string to be printed by ap_send_error_response()
1317 * Note; this goes nowhere, canned error response need an overhaul.
1318 */
1319 apr_table_setn(r->notes, "error-notes",
1320 "TRACE forbidden by server configuration");
1321 apr_table_setn(r->notes, "verbose-error-to", "*");
1323 "TRACE forbidden by server configuration");
1325 }
1326
1327 /* Can't test ap_should_client_block, we aren't ready to send
1328 * the client a 100 Continue response till the connection has
1329 * been established
1330 */
1331 if (coreconf->trace_enable != AP_TRACE_EXTENDED
1332 && (r->read_length || r->read_chunked || r->remaining))
1333 {
1334 /* Allow "error-notes" string to be printed by ap_send_error_response()
1335 * Note; this goes nowhere, canned error response need an overhaul.
1336 */
1337 apr_table_setn(r->notes, "error-notes",
1338 "TRACE with request body is not allowed");
1339 apr_table_setn(r->notes, "verbose-error-to", "*");
1341 "TRACE with request body is not allowed");
1343 }
1344 }
1345
1346 /* If the host doesn't have a domain name, add one and redirect. */
1347 if (conf->domain != NULL) {
1348 rc = proxy_needsdomain(r, uri, conf->domain);
1351 }
1352
1353 /* Check URI's destination host against NoProxy hosts */
1354 /* Bypass ProxyRemote server lookup if configured as NoProxy */
1355 for (direct_connect = i = 0; i < conf->dirconn->nelts &&
1356 !direct_connect; i++) {
1357 direct_connect = list[i].matcher(&list[i], r);
1358 }
1359#if DEBUGGING
1361 (direct_connect) ? APLOGNO(03231) "NoProxy for %s" : APLOGNO(03232) "UseProxy for %s",
1362 r->uri);
1363#endif
1364
1365 do {
1366 char *url = uri;
1367 /* Try to obtain the most suitable worker */
1368 access_status = ap_proxy_pre_request(&worker, &balancer, r, conf, &url);
1369 if (access_status != OK) {
1370 /*
1371 * Only return if access_status is not HTTP_SERVICE_UNAVAILABLE
1372 * This gives other modules the chance to hook into the
1373 * request_status hook and decide what to do in this situation.
1374 */
1376 return access_status;
1377 /*
1378 * Ensure that balancer is NULL if worker is NULL to prevent
1379 * potential problems in the post_request hook.
1380 */
1381 if (!worker)
1382 balancer = NULL;
1383 goto cleanup;
1384 }
1385
1386 /* Initialise worker if needed, note the shared area must be initialized by the balancer logic */
1387 if (balancer) {
1388 ap_proxy_initialize_worker(worker, r->server, conf->pool);
1389 }
1390
1391 if (balancer && balancer->s->max_attempts_set && !max_attempts)
1392 max_attempts = balancer->s->max_attempts;
1393 /* firstly, try a proxy, unless a NoProxy directive is active */
1394 if (!direct_connect) {
1395 for (i = 0; i < proxies->nelts; i++) {
1396 p2 = ap_strchr_c(ents[i].scheme, ':'); /* is it a partial URL? */
1397 if (strcmp(ents[i].scheme, "*") == 0 ||
1398 (ents[i].use_regex &&
1399 ap_regexec(ents[i].regexp, url, 0, NULL, 0) == 0) ||
1400 (p2 == NULL && ap_cstr_casecmp(scheme, ents[i].scheme) == 0) ||
1401 (p2 != NULL &&
1402 ap_cstr_casecmpn(url, ents[i].scheme,
1403 strlen(ents[i].scheme)) == 0)) {
1404
1405 /* handle the scheme */
1407 "Trying to run scheme_handler against proxy");
1408
1409 if (ents[i].creds) {
1410 apr_table_set(r->notes, "proxy-basic-creds", ents[i].creds);
1412 "Using proxy auth creds %s", ents[i].creds);
1413 }
1414
1416 conf, url,
1417 ents[i].hostname,
1418 ents[i].port);
1419
1420 if (ents[i].creds) apr_table_unset(r->notes, "proxy-basic-creds");
1421
1422 /* Did the scheme handler process the request? */
1423 if (access_status != DECLINED) {
1424 const char *cl_a;
1425 apr_off_t cl;
1426
1427 /*
1428 * An fatal error or success, so no point in
1429 * retrying with a direct connection.
1430 */
1432 goto cleanup;
1433 }
1434
1435 cl_a = apr_table_get(r->headers_in, "Content-Length");
1437 || cl > 0)) {
1438 /*
1439 * The request body is of length > 0. We cannot
1440 * retry with a direct connection since we already
1441 * sent (parts of) the request body to the proxy
1442 * and do not have any longer.
1443 */
1444 goto cleanup;
1445 }
1446 /*
1447 * Transfer-Encoding was set as input header, so we had
1448 * a request body. We cannot retry with a direct
1449 * connection for the same reason as above.
1450 */
1451 if (apr_table_get(r->headers_in, "Transfer-Encoding")) {
1452 goto cleanup;
1453 }
1454 }
1455 }
1456 }
1457 }
1458
1459 /* otherwise, try it direct */
1460 /* N.B. what if we're behind a firewall, where we must use a proxy or
1461 * give up??
1462 */
1463
1464 /* handle the scheme */
1466 "Running scheme %s handler (attempt %d)",
1467 scheme, attempts);
1468 AP_PROXY_RUN(r, worker, conf, url, attempts);
1470 url, NULL, 0);
1471 if (access_status == OK
1472 || apr_table_get(r->notes, "proxy-error-override"))
1473 break;
1475 /* Unrecoverable server error.
1476 * We can not failover to another worker.
1477 * Mark the worker as unusable if member of load balancer
1478 */
1479 if (balancer
1480 && !(worker->s->status & PROXY_WORKER_IGNORE_ERRORS)) {
1481 worker->s->status |= PROXY_WORKER_IN_ERROR;
1482 worker->s->error_time = apr_time_now();
1483 }
1484 break;
1485 }
1487 /* Recoverable server error.
1488 * We can failover to another worker
1489 * Mark the worker as unusable if member of load balancer
1490 */
1491 if (balancer
1492 && !(worker->s->status & PROXY_WORKER_IGNORE_ERRORS)) {
1493 worker->s->status |= PROXY_WORKER_IN_ERROR;
1494 worker->s->error_time = apr_time_now();
1495 }
1496 }
1497 else {
1498 /* Unrecoverable error.
1499 * Return the origin status code to the client.
1500 */
1501 break;
1502 }
1503 /* Try again if the worker is unusable and the service is
1504 * unavailable.
1505 */
1506 } while (!PROXY_WORKER_IS_USABLE(worker) &&
1507 max_attempts > attempts++);
1508
1509 if (DECLINED == access_status) {
1511 "No protocol handler was valid for the URL %s "
1512 "(scheme '%s'). "
1513 "If you are using a DSO version of mod_proxy, make sure "
1514 "the proxy submodules are included in the configuration "
1515 "using LoadModule.", r->uri, scheme);
1517 goto cleanup;
1518 }
1519cleanup:
1520 /*
1521 * Save current r->status and set it to the value of access_status which
1522 * might be different (e.g. r->status could be HTTP_OK if e.g. we override
1523 * the error page on the proxy or if the error was not generated by the
1524 * backend itself but by the proxy e.g. a bad gateway) in order to give
1525 * ap_proxy_post_request a chance to act correctly on the status code.
1526 * But only do the above if access_status is not OK and not DONE, because
1527 * in this case r->status might contain the true status and overwriting
1528 * it with OK or DONE would be wrong.
1529 */
1530 if ((access_status != OK) && (access_status != DONE)) {
1533 ap_proxy_post_request(worker, balancer, r, conf);
1534 /*
1535 * Only restore r->status if it has not been changed by
1536 * ap_proxy_post_request as we assume that this change was intentional.
1537 */
1538 if (r->status == access_status) {
1540 }
1541 }
1542 else {
1543 ap_proxy_post_request(worker, balancer, r, conf);
1544 }
1545
1548
1549 return access_status;
1550}
1551
1552/* -------------------------------------------------------------- */
1553/* Setup configurable data */
1554
1556{
1558
1559 ps->sec_proxy = apr_array_make(p, 10, sizeof(ap_conf_vector_t *));
1560 ps->proxies = apr_array_make(p, 10, sizeof(struct proxy_remote));
1561 ps->aliases = apr_array_make(p, 10, sizeof(struct proxy_alias));
1562 ps->noproxies = apr_array_make(p, 10, sizeof(struct noproxy_entry));
1563 ps->dirconn = apr_array_make(p, 10, sizeof(struct dirconn_entry));
1564 ps->workers = apr_array_make(p, 10, sizeof(proxy_worker));
1565 ps->balancers = apr_array_make(p, 10, sizeof(proxy_balancer));
1566 ps->forward = NULL;
1567 ps->reverse = NULL;
1568 ps->domain = NULL;
1569 ps->map_encoded_one = 0;
1570 ps->map_encoded_all = 1;
1571 ps->id = apr_psprintf(p, "p%x", 1); /* simply for storage size */
1572 ps->viaopt = via_off; /* initially backward compatible with 1.3.1 */
1573 ps->viaopt_set = 0; /* 0 means default */
1574 ps->req = 0;
1575 ps->max_balancers = 0;
1576 ps->bal_persist = 0;
1577 ps->inherit = 1;
1578 ps->inherit_set = 0;
1579 ps->ppinherit = 1;
1580 ps->ppinherit_set = 0;
1581 ps->bgrowth = 5;
1582 ps->bgrowth_set = 0;
1583 ps->req_set = 0;
1584 ps->recv_buffer_size = 0; /* this default was left unset for some reason */
1585 ps->recv_buffer_size_set = 0;
1586 ps->io_buffer_size = AP_IOBUFSIZE;
1587 ps->io_buffer_size_set = 0;
1588 ps->maxfwd = DEFAULT_MAX_FORWARDS;
1589 ps->maxfwd_set = 0;
1590 ps->timeout = 0;
1591 ps->timeout_set = 0;
1592 ps->badopt = bad_error;
1593 ps->badopt_set = 0;
1594 ps->source_address = NULL;
1595 ps->source_address_set = 0;
1596 apr_pool_create_ex(&ps->pool, p, NULL, NULL);
1597 apr_pool_tag(ps->pool, "proxy_server_conf");
1598
1599 return ps;
1600}
1601
1605{
1608 proxy_balancer tmp;
1609 int x, y, found;
1611
1612 /* Check if the balancer is defined in both override and base configs:
1613 * a) If it is, Create copy of base balancer and change the configuration
1614 * which can be changed by ProxyPass.
1615 * b) Otherwise, copy the balancer to tocopy array and merge it later.
1616 */
1617 b1 = (proxy_balancer *) base->elts;
1618 for (y = 0; y < base->nelts; y++) {
1619 b2 = (proxy_balancer *) overrides->elts;
1620 for (x = 0, found = 0; x < overrides->nelts; x++) {
1621 if (b1->hash.def == b2->hash.def && b1->hash.fnv == b2->hash.fnv) {
1622 tmp = *b2;
1623 *b2 = *b1;
1624 b2->s = tmp.s;
1625
1626 /* For shared memory entries, b2->s belongs to override
1627 * balancer, so if some entry is not set there, we have to
1628 * update it according to the base balancer. */
1629 if (*b2->s->sticky == 0 && *b1->s->sticky) {
1630 PROXY_STRNCPY(b2->s->sticky_path, b1->s->sticky_path);
1631 PROXY_STRNCPY(b2->s->sticky, b1->s->sticky);
1632 }
1633 if (!b2->s->sticky_separator_set
1634 && b1->s->sticky_separator_set) {
1635 b2->s->sticky_separator_set = b1->s->sticky_separator_set;
1636 b2->s->sticky_separator = b1->s->sticky_separator;
1637 }
1638 if (!b2->s->timeout && b1->s->timeout) {
1639 b2->s->timeout = b1->s->timeout;
1640 }
1641 if (!b2->s->max_attempts_set && b1->s->max_attempts_set) {
1642 b2->s->max_attempts_set = b1->s->max_attempts_set;
1643 b2->s->max_attempts = b1->s->max_attempts;
1644 }
1645 if (!b2->s->nonce_set && b1->s->nonce_set) {
1646 b2->s->nonce_set = b1->s->nonce_set;
1647 PROXY_STRNCPY(b2->s->nonce, b1->s->nonce);
1648 }
1649 if (!b2->s->sticky_force_set && b1->s->sticky_force_set) {
1650 b2->s->sticky_force_set = b1->s->sticky_force_set;
1651 b2->s->sticky_force = b1->s->sticky_force;
1652 }
1653 if (!b2->s->scolonsep_set && b1->s->scolonsep_set) {
1654 b2->s->scolonsep_set = b1->s->scolonsep_set;
1655 b2->s->scolonsep = b1->s->scolonsep;
1656 }
1657 if (!b2->s->forcerecovery_set && b1->s->forcerecovery_set) {
1658 b2->s->forcerecovery_set = b1->s->forcerecovery_set;
1659 b2->s->forcerecovery = b1->s->forcerecovery;
1660 }
1661
1662 /* For non-shared memory entries, b2 is copy of b1, so we have
1663 * to use tmp copy of b1 to detect changes done in override. */
1664 if (tmp.lbmethod_set) {
1665 b2->lbmethod_set = tmp.lbmethod_set;
1666 b2->lbmethod = tmp.lbmethod;
1667 }
1668 if (tmp.growth_set) {
1669 b2->growth_set = tmp.growth_set;
1670 b2->growth = tmp.growth;
1671 }
1672 if (tmp.failontimeout_set) {
1673 b2->failontimeout_set = tmp.failontimeout_set;
1674 b2->failontimeout = tmp.failontimeout;
1675 }
1676 if (!apr_is_empty_array(tmp.errstatuses)) {
1677 apr_array_cat(tmp.errstatuses, b2->errstatuses);
1678 b2->errstatuses = tmp.errstatuses;
1679 }
1680
1681 found = 1;
1682 break;
1683 }
1684 b2++;
1685 }
1686 if (!found) {
1688 }
1689 b1++;
1690 }
1691
1693}
1694
1695static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv)
1696{
1700
1701 ps->inherit = (overrides->inherit_set == 0) ? base->inherit : overrides->inherit;
1702 ps->inherit_set = overrides->inherit_set || base->inherit_set;
1703
1704 ps->ppinherit = (overrides->ppinherit_set == 0) ? base->ppinherit : overrides->ppinherit;
1705 ps->ppinherit_set = overrides->ppinherit_set || base->ppinherit_set;
1706
1707 if (ps->ppinherit) {
1708 ps->proxies = apr_array_append(p, base->proxies, overrides->proxies);
1709 }
1710 else {
1711 ps->proxies = overrides->proxies;
1712 }
1713 ps->sec_proxy = apr_array_append(p, base->sec_proxy, overrides->sec_proxy);
1714 ps->aliases = apr_array_append(p, base->aliases, overrides->aliases);
1715 ps->noproxies = apr_array_append(p, base->noproxies, overrides->noproxies);
1716 ps->dirconn = apr_array_append(p, base->dirconn, overrides->dirconn);
1717 if (ps->inherit || ps->ppinherit) {
1718 ps->workers = apr_array_append(p, base->workers, overrides->workers);
1719 ps->balancers = merge_balancers(p, base->balancers, overrides->balancers);
1720 }
1721 else {
1722 ps->workers = overrides->workers;
1723 ps->balancers = overrides->balancers;
1724 }
1725 ps->forward = overrides->forward ? overrides->forward : base->forward;
1726 ps->reverse = overrides->reverse ? overrides->reverse : base->reverse;
1727
1728 ps->map_encoded_one = overrides->map_encoded_one || base->map_encoded_one;
1729 ps->map_encoded_all = overrides->map_encoded_all && base->map_encoded_all;
1730
1731 ps->domain = (overrides->domain == NULL) ? base->domain : overrides->domain;
1732 ps->id = (overrides->id == NULL) ? base->id : overrides->id;
1733 ps->viaopt = (overrides->viaopt_set == 0) ? base->viaopt : overrides->viaopt;
1734 ps->viaopt_set = overrides->viaopt_set || base->viaopt_set;
1735 ps->req = (overrides->req_set == 0) ? base->req : overrides->req;
1736 ps->req_set = overrides->req_set || base->req_set;
1737 ps->bgrowth = (overrides->bgrowth_set == 0) ? base->bgrowth : overrides->bgrowth;
1738 ps->bgrowth_set = overrides->bgrowth_set || base->bgrowth_set;
1739 ps->max_balancers = overrides->max_balancers || base->max_balancers;
1740 ps->bal_persist = overrides->bal_persist;
1741 ps->recv_buffer_size = (overrides->recv_buffer_size_set == 0) ? base->recv_buffer_size : overrides->recv_buffer_size;
1742 ps->recv_buffer_size_set = overrides->recv_buffer_size_set || base->recv_buffer_size_set;
1743 ps->io_buffer_size = (overrides->io_buffer_size_set == 0) ? base->io_buffer_size : overrides->io_buffer_size;
1744 ps->io_buffer_size_set = overrides->io_buffer_size_set || base->io_buffer_size_set;
1745 ps->maxfwd = (overrides->maxfwd_set == 0) ? base->maxfwd : overrides->maxfwd;
1746 ps->maxfwd_set = overrides->maxfwd_set || base->maxfwd_set;
1747 ps->timeout = (overrides->timeout_set == 0) ? base->timeout : overrides->timeout;
1748 ps->timeout_set = overrides->timeout_set || base->timeout_set;
1749 ps->badopt = (overrides->badopt_set == 0) ? base->badopt : overrides->badopt;
1750 ps->badopt_set = overrides->badopt_set || base->badopt_set;
1751 ps->proxy_status = (overrides->proxy_status_set == 0) ? base->proxy_status : overrides->proxy_status;
1752 ps->proxy_status_set = overrides->proxy_status_set || base->proxy_status_set;
1753 ps->source_address = (overrides->source_address_set == 0) ? base->source_address : overrides->source_address;
1754 ps->source_address_set = overrides->source_address_set || base->source_address_set;
1755 ps->pool = base->pool;
1756 return ps;
1757}
1758static const char *set_source_address(cmd_parms *parms, void *dummy,
1759 const char *arg)
1760{
1762 ap_get_module_config(parms->server->module_config, &proxy_module);
1763 struct apr_sockaddr_t *addr;
1764
1766 psf->pool)) {
1767 psf->source_address = addr;
1768 psf->source_address_set = 1;
1769 }
1770 else {
1771 return "ProxySourceAddress invalid value";
1772 }
1773
1774 return NULL;
1775}
1776
1778{
1779 proxy_dir_conf *new =
1781
1782 /* Filled in by proxysection, when applicable */
1783
1784 /* Put these in the dir config so they work inside <Location> */
1785 new->raliases = apr_array_make(p, 10, sizeof(struct proxy_alias));
1786 new->cookie_paths = apr_array_make(p, 10, sizeof(struct proxy_alias));
1787 new->cookie_domains = apr_array_make(p, 10, sizeof(struct proxy_alias));
1788 new->error_override_codes = apr_array_make(p, 10, sizeof(int));
1789 new->preserve_host_set = 0;
1790 new->preserve_host = 0;
1791 new->interpolate_env = -1; /* unset */
1792 new->error_override = 0;
1793 new->error_override_set = 0;
1794 new->add_forwarded_headers = 1;
1795 new->add_forwarded_headers_set = 0;
1796 new->forward_100_continue = 1;
1797 new->forward_100_continue_set = 0;
1798
1799 return (void *) new;
1800}
1801
1802static int int_order(const void *i1, const void *i2)
1803{
1804 return *(const int *)i1 - *(const int *)i2;
1805}
1806
1807static void *merge_proxy_dir_config(apr_pool_t *p, void *basev, void *addv)
1808{
1812
1813 new->p = add->p;
1814 new->p_is_fnmatch = add->p_is_fnmatch;
1815 new->r = add->r;
1816 new->refs = add->refs;
1817
1818 /* Put these in the dir config so they work inside <Location> */
1819 new->raliases = apr_array_append(p, base->raliases, add->raliases);
1820 new->cookie_paths
1821 = apr_array_append(p, base->cookie_paths, add->cookie_paths);
1822 new->cookie_domains
1823 = apr_array_append(p, base->cookie_domains, add->cookie_domains);
1824 new->error_override_codes
1825 = apr_array_append(p, base->error_override_codes, add->error_override_codes);
1826 /* Keep the array sorted for binary search (since "base" and "add" are
1827 * already sorted, it's only needed only if both are merged).
1828 */
1829 if (base->error_override_codes->nelts
1830 && add->error_override_codes->nelts) {
1831 qsort(new->error_override_codes->elts,
1832 new->error_override_codes->nelts,
1833 sizeof(int), int_order);
1834 }
1835 new->interpolate_env = (add->interpolate_env == -1) ? base->interpolate_env
1836 : add->interpolate_env;
1837 new->preserve_host = (add->preserve_host_set == 0) ? base->preserve_host
1838 : add->preserve_host;
1839 new->preserve_host_set = add->preserve_host_set || base->preserve_host_set;
1840 new->error_override = (add->error_override_set == 0) ? base->error_override
1841 : add->error_override;
1842 new->error_override_set = add->error_override_set || base->error_override_set;
1843 new->alias = (add->alias_set == 0) ? base->alias : add->alias;
1844 new->alias_set = add->alias_set || base->alias_set;
1845 new->add_forwarded_headers =
1846 (add->add_forwarded_headers_set == 0) ? base->add_forwarded_headers
1847 : add->add_forwarded_headers;
1848 new->add_forwarded_headers_set = add->add_forwarded_headers_set
1849 || base->add_forwarded_headers_set;
1850 new->forward_100_continue =
1851 (add->forward_100_continue_set == 0) ? base->forward_100_continue
1852 : add->forward_100_continue;
1853 new->forward_100_continue_set = add->forward_100_continue_set
1854 || base->forward_100_continue_set;
1855
1856 return new;
1857}
1858
1859static const char *add_proxy(cmd_parms *cmd, void *dummy, const char *f1,
1860 const char *r1, const char *creds, int regex)
1861{
1862 server_rec *s = cmd->server;
1863 proxy_server_conf *conf =
1864 (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);
1865 struct proxy_remote *new;
1866 char *p, *q;
1867 char *r, *f, *scheme;
1868 ap_regex_t *reg = NULL;
1869 int port;
1870
1871 r = apr_pstrdup(cmd->pool, r1);
1872 scheme = apr_pstrdup(cmd->pool, r1);
1873 f = apr_pstrdup(cmd->pool, f1);
1874 p = strchr(r, ':');
1875 if (p == NULL || p[1] != '/' || p[2] != '/' || p[3] == '\0') {
1876 if (regex)
1877 return "ProxyRemoteMatch: Bad syntax for a remote proxy server";
1878 else
1879 return "ProxyRemote: Bad syntax for a remote proxy server";
1880 }
1881 else {
1882 scheme[p-r] = 0;
1883 }
1884 q = strchr(p + 3, ':');
1885 if (q != NULL) {
1886 if (sscanf(q + 1, "%u", &port) != 1 || port > 65535) {
1887 if (regex)
1888 return "ProxyRemoteMatch: Bad syntax for a remote proxy server (bad port number)";
1889 else
1890 return "ProxyRemote: Bad syntax for a remote proxy server (bad port number)";
1891 }
1892 *q = '\0';
1893 }
1894 else
1895 port = -1;
1896 *p = '\0';
1897 if (regex) {
1898 reg = ap_pregcomp(cmd->pool, f, AP_REG_EXTENDED);
1899 if (!reg)
1900 return "Regular expression for ProxyRemoteMatch could not be compiled.";
1901 }
1902 else
1903 if (strchr(f, ':') == NULL)
1904 ap_str_tolower(f); /* lowercase scheme */
1905 ap_str_tolower(p + 3); /* lowercase hostname */
1906
1907 if (port == -1) {
1909 }
1910
1911 new = apr_array_push(conf->proxies);
1912 new->scheme = f;
1913 new->protocol = r;
1914 new->hostname = p + 3;
1915 new->port = port;
1916 new->regexp = reg;
1917 new->use_regex = regex;
1918 if (creds) {
1919 new->creds = apr_pstrcat(cmd->pool, "Basic ",
1920 ap_pbase64encode(cmd->pool, (char *)creds),
1921 NULL);
1922 }
1923 return NULL;
1924}
1925
1926static const char *add_proxy_noregex(cmd_parms *cmd, void *dummy, const char *f1,
1927 const char *r1, const char *creds)
1928{
1929 return add_proxy(cmd, dummy, f1, r1, creds, 0);
1930}
1931
1932static const char *add_proxy_regex(cmd_parms *cmd, void *dummy, const char *f1,
1933 const char *r1, const char *creds)
1934{
1935 return add_proxy(cmd, dummy, f1, r1, creds, 1);
1936}
1937
1939{
1940 const char *ptr;
1941 /*
1942 * We could be passed a URL during the config stage that contains
1943 * the UDS path... ignore it
1944 */
1945 if (!ap_cstr_casecmpn(url, "unix:", 5) &&
1946 ((ptr = ap_strchr_c(url + 5, '|')) != NULL)) {
1947 /* move past the 'unix:...|' UDS path info */
1948 const char *ret, *c;
1949
1950 ret = ptr + 1;
1951 /* special case: "unix:....|scheme:" is OK, expand
1952 * to "unix:....|scheme://localhost"
1953 * */
1954 c = ap_strchr_c(ret, ':');
1955 if (c == NULL) {
1956 return NULL;
1957 }
1958 if (c[1] == '\0') {
1959 return apr_pstrcat(p, ret, "//localhost", NULL);
1960 }
1961 else {
1962 return ret;
1963 }
1964 }
1965 return url;
1966}
1967
1968static const char *
1969 add_pass(cmd_parms *cmd, void *dummy, const char *arg, int is_regex)
1970{
1972 server_rec *s = cmd->server;
1973 proxy_server_conf *conf =
1974 (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);
1975 struct proxy_alias *new;
1976 char *f = cmd->path;
1977 char *r = NULL;
1978 const char *real;
1979 char *word;
1980 apr_table_t *params = apr_table_make(cmd->pool, 5);
1981 const apr_array_header_t *arr;
1982 const apr_table_entry_t *elts;
1983 int i;
1986 unsigned int flags = 0;
1987 const char *err;
1988
1990 if (err) {
1991 return err;
1992 }
1993
1994 while (*arg) {
1995 word = ap_getword_conf(cmd->pool, &arg);
1996 if (!f) {
1997 if (!strcmp(word, "~")) {
1998 if (is_regex) {
1999 return "ProxyPassMatch invalid syntax ('~' usage).";
2000 }
2002 continue;
2003 }
2004 f = word;
2005 }
2006 else if (!r) {
2007 r = word;
2008 }
2009 else if (!strcasecmp(word,"nocanon")) {
2011 }
2012 else if (!strcasecmp(word,"interpolate")) {
2014 }
2015 else if (!strcasecmp(word,"noquery")) {
2017 }
2018 else {
2019 char *val = strchr(word, '=');
2020 if (!val) {
2021 if (cmd->path) {
2022 if (*r == '/') {
2023 return "ProxyPass|ProxyPassMatch can not have a path when defined in "
2024 "a location.";
2025 }
2026 else {
2027 return "Invalid ProxyPass|ProxyPassMatch parameter. Parameter must "
2028 "be in the form 'key=value'.";
2029 }
2030 }
2031 else {
2032 return "Invalid ProxyPass|ProxyPassMatch parameter. Parameter must be "
2033 "in the form 'key=value'.";
2034 }
2035 }
2036 else {
2037 *val++ = '\0';
2038 }
2039 if (!strcasecmp(word, "mapping")) {
2040 if (!strcasecmp(val, "encoded")) {
2042 }
2043 else if (!strcasecmp(val, "servlet")) {
2045 }
2046 else {
2047 return "unknown mapping";
2048 }
2049 }
2050 else {
2052 }
2053 }
2054 }
2056 conf->map_encoded_one = 1;
2057 }
2058 else {
2059 conf->map_encoded_all = 0;
2060 }
2061
2062 if (r == NULL) {
2063 return "ProxyPass|ProxyPassMatch needs a path when not defined in a location";
2064 }
2065 if (!(real = ap_proxy_de_socketfy(cmd->temp_pool, r))) {
2066 return "ProxyPass|ProxyPassMatch uses an invalid \"unix:\" URL";
2067 }
2068
2069
2070 /* if per directory, save away the single alias */
2071 if (cmd->path) {
2072 dconf->alias = apr_pcalloc(cmd->pool, sizeof(struct proxy_alias));
2073 dconf->alias_set = 1;
2074 new = dconf->alias;
2075 if (apr_fnmatch_test(f)) {
2077 }
2078 }
2079 /* if per server, add to the alias array */
2080 else {
2081 new = apr_array_push(conf->aliases);
2082 }
2083
2084 new->fake = apr_pstrdup(cmd->pool, f);
2085 new->real = apr_pstrdup(cmd->pool, real);
2086 new->flags = flags;
2088 new->regex = ap_pregcomp(cmd->pool, f, AP_REG_EXTENDED);
2089 if (new->regex == NULL)
2090 return "Regular expression could not be compiled.";
2091 }
2092 else {
2093 new->regex = NULL;
2094 }
2095
2096 if (r[0] == '!' && r[1] == '\0')
2097 return NULL;
2098
2100 elts = (const apr_table_entry_t *)arr->elts;
2101 /* Distinguish the balancer from worker */
2104 char *fake_copy;
2105
2106 /*
2107 * In the regex case supplying a fake URL doesn't make sense as it
2108 * cannot be parsed anyway with apr_uri_parse later on in
2109 * ap_proxy_define_balancer / ap_proxy_update_balancer
2110 */
2112 fake_copy = NULL;
2113 }
2114 else {
2115 fake_copy = f;
2116 }
2117 if (!balancer) {
2118 const char *err = ap_proxy_define_balancer(cmd->pool, &balancer, conf, r, fake_copy, 0);
2119 if (err)
2120 return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL);
2121 }
2122 else {
2124 }
2125 for (i = 0; i < arr->nelts; i++) {
2126 const char *err = set_balancer_param(conf, cmd->pool, balancer, elts[i].key,
2127 elts[i].val);
2128 if (err)
2129 return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL);
2130 }
2131 new->balancer = balancer;
2132 }
2133 else {
2134 int reuse = 0;
2135 proxy_worker *worker = ap_proxy_get_worker_ex(cmd->temp_pool, NULL,
2136 conf, new->real,
2137 worker_type);
2138 if (!worker) {
2139 const char *err;
2140 err = ap_proxy_define_worker_ex(cmd->pool, &worker, NULL,
2141 conf, r, worker_type);
2142 if (err)
2143 return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL);
2144
2145 PROXY_COPY_CONF_PARAMS(worker, conf);
2146 }
2147 else {
2148 reuse = 1;
2149 ap_log_error(APLOG_MARK, APLOG_INFO, 0, cmd->server, APLOGNO(01145)
2150 "Sharing worker '%s' instead of creating new worker '%s'",
2151 ap_proxy_worker_name(cmd->pool, worker), new->real);
2152 }
2153
2154 for (i = 0; i < arr->nelts; i++) {
2155 if (reuse) {
2156 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(01146)
2157 "Ignoring parameter '%s=%s' for worker '%s' because of worker sharing",
2158 elts[i].key, elts[i].val, ap_proxy_worker_name(cmd->pool, worker));
2159 } else {
2160 const char *err = set_worker_param(cmd->pool, s, worker, elts[i].key,
2161 elts[i].val);
2162 if (err)
2163 return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL);
2164 }
2165 }
2166 }
2167 return NULL;
2168}
2169
2170static const char *
2172{
2173 return add_pass(cmd, dummy, arg, 0);
2174}
2175
2176static const char *
2177 add_pass_regex(cmd_parms *cmd, void *dummy, const char *arg)
2178{
2179 return add_pass(cmd, dummy, arg, 1);
2180}
2181
2182
2183static const char * add_pass_reverse(cmd_parms *cmd, void *dconf, const char *f,
2184 const char *r, const char *i)
2185{
2186 proxy_dir_conf *conf = dconf;
2187 struct proxy_alias *new;
2188 const char *fake;
2189 const char *real;
2190 const char *interp;
2191 const char *err;
2192
2194 if (err) {
2195 return err;
2196 }
2197
2198 if (cmd->path == NULL) {
2199 if (r == NULL || !strcasecmp(r, "interpolate")) {
2200 return "ProxyPassReverse needs a path when not defined in a location";
2201 }
2202 fake = f;
2203 real = r;
2204 interp = i;
2205 }
2206 else {
2207 if (r && strcasecmp(r, "interpolate")) {
2208 return "ProxyPassReverse can not have a path when defined in a location";
2209 }
2210 fake = cmd->path;
2211 real = f;
2212 interp = r;
2213 }
2214
2215 new = apr_array_push(conf->raliases);
2216 new->fake = fake;
2217 new->real = real;
2218 new->flags = interp ? PROXYPASS_INTERPOLATE : 0;
2219
2220 return NULL;
2221}
2222static const char* cookie_path(cmd_parms *cmd, void *dconf, const char *f,
2223 const char *r, const char *interp)
2224{
2225 proxy_dir_conf *conf = dconf;
2226 struct proxy_alias *new;
2227
2228 new = apr_array_push(conf->cookie_paths);
2229 new->fake = f;
2230 new->real = r;
2231 new->flags = interp ? PROXYPASS_INTERPOLATE : 0;
2232
2233 return NULL;
2234}
2235static const char* cookie_domain(cmd_parms *cmd, void *dconf, const char *f,
2236 const char *r, const char *interp)
2237{
2238 proxy_dir_conf *conf = dconf;
2239 struct proxy_alias *new;
2240
2241 new = apr_array_push(conf->cookie_domains);
2242 new->fake = f;
2243 new->real = r;
2244 new->flags = interp ? PROXYPASS_INTERPOLATE : 0;
2245 return NULL;
2246}
2247
2248static const char *
2250{
2251 server_rec *s = parms->server;
2252 proxy_server_conf *conf =
2253 ap_get_module_config(s->module_config, &proxy_module);
2254 struct noproxy_entry *new;
2255 struct noproxy_entry *list = (struct noproxy_entry *) conf->noproxies->elts;
2256 struct apr_sockaddr_t *addr;
2257 int found = 0;
2258 int i;
2259
2260 /* Don't duplicate entries */
2261 for (i = 0; i < conf->noproxies->nelts; i++) {
2262 if (strcasecmp(arg, list[i].name) == 0) { /* ignore case for host names */
2263 found = 1;
2264 break;
2265 }
2266 }
2267
2268 if (!found) {
2269 new = apr_array_push(conf->noproxies);
2270 new->name = arg;
2271 if (APR_SUCCESS == apr_sockaddr_info_get(&addr, new->name, APR_UNSPEC, 0, 0, parms->pool)) {
2272 new->addr = addr;
2273 }
2274 else {
2275 new->addr = NULL;
2276 }
2277 }
2278 return NULL;
2279}
2280
2281
2282/* Similar to set_proxy_exclude(), but defining directly connected hosts,
2283 * which should never be accessed via the configured ProxyRemote servers
2284 */
2285static const char *
2287{
2288 server_rec *s = parms->server;
2289 proxy_server_conf *conf =
2290 ap_get_module_config(s->module_config, &proxy_module);
2291 struct dirconn_entry *New;
2292 struct dirconn_entry *list = (struct dirconn_entry *) conf->dirconn->elts;
2293 int found = 0;
2294 int i;
2295
2296 /* Don't duplicate entries */
2297 for (i = 0; i < conf->dirconn->nelts; i++) {
2298 if (strcasecmp(arg, list[i].name) == 0) {
2299 found = 1;
2300 break;
2301 }
2302 }
2303
2304 if (!found) {
2305 New = apr_array_push(conf->dirconn);
2306 New->name = apr_pstrdup(parms->pool, arg);
2307 New->hostaddr = NULL;
2308
2309 if (ap_proxy_is_ipaddr(New, parms->pool)) {
2310#if DEBUGGING
2312 "Parsed addr %s", inet_ntoa(New->addr));
2314 "Parsed mask %s", inet_ntoa(New->mask));
2315#endif
2316 }
2317 else if (ap_proxy_is_domainname(New, parms->pool)) {
2318 ap_str_tolower(New->name);
2319#if DEBUGGING
2321 "Parsed domain %s", New->name);
2322#endif
2323 }
2324 else if (ap_proxy_is_hostname(New, parms->pool)) {
2325 ap_str_tolower(New->name);
2326#if DEBUGGING
2328 "Parsed host %s", New->name);
2329#endif
2330 }
2331 else {
2332 ap_proxy_is_word(New, parms->pool);
2333#if DEBUGGING
2334 fprintf(stderr, "Parsed word %s\n", New->name);
2335#endif
2336 }
2337 }
2338 return NULL;
2339}
2340
2341static const char *
2343{
2345 ap_get_module_config(parms->server->module_config, &proxy_module);
2346
2347 if (arg[0] != '.')
2348 return "ProxyDomain: domain name must start with a dot.";
2349
2350 psf->domain = arg;
2351 return NULL;
2352}
2353
2354static const char *
2356{
2358 ap_get_module_config(parms->server->module_config, &proxy_module);
2359
2360 psf->req = flag;
2361 psf->req_set = 1;
2362 return NULL;
2363}
2364
2365static const char *
2366 set_proxy_error_override(cmd_parms *parms, void *dconf, const char *arg)
2367{
2368 proxy_dir_conf *conf = dconf;
2369
2370 if (strcasecmp(arg, "Off") == 0) {
2371 conf->error_override = 0;
2372 conf->error_override_set = 1;
2373 }
2374 else if (strcasecmp(arg, "On") == 0) {
2375 conf->error_override = 1;
2376 conf->error_override_set = 1;
2377 }
2378 else if (conf->error_override_set == 1) {
2379 int *newcode;
2380 int argcode, i;
2381 if (!apr_isdigit(arg[0]))
2382 return "ProxyErrorOverride: status codes to intercept must be numeric";
2383 if (!conf->error_override)
2384 return "ProxyErrorOverride: status codes must follow a value of 'on'";
2385
2386 argcode = strtol(arg, NULL, 10);
2388 return "ProxyErrorOverride: status codes to intercept must be valid HTTP Status Codes >=400 && <600";
2389
2391 *newcode = argcode;
2392
2393 /* Keep the array sorted for binary search. */
2394 for (i = conf->error_override_codes->nelts - 1; i > 0; --i) {
2395 int *oldcode = &((int *)conf->error_override_codes->elts)[i - 1];
2396 if (*oldcode <= argcode) {
2397 break;
2398 }
2399 *newcode = *oldcode;
2400 *oldcode = argcode;
2401 newcode = oldcode;
2402 }
2403 }
2404 else
2405 return "ProxyErrorOverride first parameter must be one of: off | on";
2406
2407 return NULL;
2408}
2409
2410static const char *
2412{
2413 proxy_dir_conf *conf = dconf;
2415 conf->add_forwarded_headers_set = 1;
2416 return NULL;
2417}
2418static const char *
2420{
2421 proxy_dir_conf *conf = dconf;
2422
2423 conf->preserve_host = flag;
2424 conf->preserve_host_set = 1;
2425 return NULL;
2426}
2427static const char *
2429{
2430 proxy_dir_conf *conf = dconf;
2431 conf->forward_100_continue = flag;
2432 conf->forward_100_continue_set = 1;
2433 return NULL;
2434}
2435
2436static const char *
2438{
2440 ap_get_module_config(parms->server->module_config, &proxy_module);
2441 int s = atoi(arg);
2442 if (s < 512 && s != 0) {
2443 return "ProxyReceiveBufferSize must be >= 512 bytes, or 0 for system default.";
2444 }
2445
2446 psf->recv_buffer_size = s;
2447 psf->recv_buffer_size_set = 1;
2448 return NULL;
2449}
2450
2451static const char *
2453{
2455 ap_get_module_config(parms->server->module_config, &proxy_module);
2456 long s = atol(arg);
2457 if (s < 512 && s) {
2458 return "ProxyIOBufferSize must be >= 512 bytes, or 0 for system default.";
2459 }
2460 psf->io_buffer_size = (s ? s : AP_IOBUFSIZE);
2461 psf->io_buffer_size_set = 1;
2462 return NULL;
2463}
2464
2465static const char *
2467{
2469 ap_get_module_config(parms->server->module_config, &proxy_module);
2470 long s = atol(arg);
2471
2472 psf->maxfwd = s;
2473 psf->maxfwd_set = 1;
2474 return NULL;
2475}
2476static const char*
2478{
2480 ap_get_module_config(parms->server->module_config, &proxy_module);
2481 int timeout;
2482
2483 timeout = atoi(arg);
2484 if (timeout<1) {
2485 return "Proxy Timeout must be at least 1 second.";
2486 }
2487 psf->timeout_set = 1;
2488 psf->timeout = apr_time_from_sec(timeout);
2489
2490 return NULL;
2491}
2492
2493static const char*
2494 set_via_opt(cmd_parms *parms, void *dummy, const char *arg)
2495{
2497 ap_get_module_config(parms->server->module_config, &proxy_module);
2498
2499 if (strcasecmp(arg, "Off") == 0)
2500 psf->viaopt = via_off;
2501 else if (strcasecmp(arg, "On") == 0)
2502 psf->viaopt = via_on;
2503 else if (strcasecmp(arg, "Block") == 0)
2504 psf->viaopt = via_block;
2505 else if (strcasecmp(arg, "Full") == 0)
2506 psf->viaopt = via_full;
2507 else {
2508 return "ProxyVia must be one of: "
2509 "off | on | full | block";
2510 }
2511
2512 psf->viaopt_set = 1;
2513 return NULL;
2514}
2515
2516static const char*
2517 set_bad_opt(cmd_parms *parms, void *dummy, const char *arg)
2518{
2520 ap_get_module_config(parms->server->module_config, &proxy_module);
2521
2522 if (strcasecmp(arg, "IsError") == 0)
2523 psf->badopt = bad_error;
2524 else if (strcasecmp(arg, "Ignore") == 0)
2525 psf->badopt = bad_ignore;
2526 else if (strcasecmp(arg, "StartBody") == 0)
2527 psf->badopt = bad_body;
2528 else {
2529 return "ProxyBadHeader must be one of: "
2530 "IsError | Ignore | StartBody";
2531 }
2532
2533 psf->badopt_set = 1;
2534 return NULL;
2535}
2536
2537static const char*
2539{
2541 ap_get_module_config(parms->server->module_config, &proxy_module);
2542
2543 if (strcasecmp(arg, "Off") == 0)
2544 psf->proxy_status = status_off;
2545 else if (strcasecmp(arg, "On") == 0)
2546 psf->proxy_status = status_on;
2547 else if (strcasecmp(arg, "Full") == 0)
2548 psf->proxy_status = status_full;
2549 else {
2550 return "ProxyStatus must be one of: "
2551 "off | on | full";
2552 }
2553
2554 psf->proxy_status_set = 1;
2555 return NULL;
2556}
2557
2558static const char *set_bgrowth(cmd_parms *parms, void *dummy, const char *arg)
2559{
2561 ap_get_module_config(parms->server->module_config, &proxy_module);
2562
2563 int growth = atoi(arg);
2564 if (growth < 0 || growth > 1000) {
2565 return "BalancerGrowth must be between 0 and 1000";
2566 }
2567 psf->bgrowth = growth;
2568 psf->bgrowth_set = 1;
2569
2570 return NULL;
2571}
2572
2573static const char *set_persist(cmd_parms *parms, void *dummy, int flag)
2574{
2576 ap_get_module_config(parms->server->module_config, &proxy_module);
2577
2578 psf->bal_persist = flag;
2579 return NULL;
2580}
2581
2582static const char *set_inherit(cmd_parms *parms, void *dummy, int flag)
2583{
2585 ap_get_module_config(parms->server->module_config, &proxy_module);
2586
2587 psf->inherit = flag;
2588 psf->inherit_set = 1;
2589 return NULL;
2590}
2591
2592static const char *set_ppinherit(cmd_parms *parms, void *dummy, int flag)
2593{
2595 ap_get_module_config(parms->server->module_config, &proxy_module);
2596
2597 psf->ppinherit = flag;
2598 psf->ppinherit_set = 1;
2599 return NULL;
2600}
2601
2602static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
2603{
2604 server_rec *s = cmd->server;
2605 proxy_server_conf *conf =
2606 ap_get_module_config(s->module_config, &proxy_module);
2607 proxy_balancer *balancer;
2608 proxy_worker *worker;
2609 char *path = cmd->path;
2610 char *name = NULL;
2611 const char *real;
2612 char *word;
2613 apr_table_t *params = apr_table_make(cmd->pool, 5);
2614 const apr_array_header_t *arr;
2615 const apr_table_entry_t *elts;
2616 int reuse = 0;
2617 int i;
2618 /* XXX: Should this be NOT_IN_DIRECTORY|NOT_IN_FILES? */
2620 if (err)
2621 return err;
2622
2623 if (cmd->path)
2624 path = apr_pstrdup(cmd->pool, cmd->path);
2625
2626 while (*arg) {
2627 char *val;
2628 word = ap_getword_conf(cmd->pool, &arg);
2629 val = strchr(word, '=');
2630
2631 if (!val) {
2632 if (!path)
2633 path = word;
2634 else if (!name)
2635 name = word;
2636 else {
2637 if (cmd->path)
2638 return "BalancerMember can not have a balancer name when defined in a location";
2639 else
2640 return "Invalid BalancerMember parameter. Parameter must "
2641 "be in the form 'key=value'";
2642 }
2643 } else {
2644 *val++ = '\0';
2646 }
2647 }
2648 if (!path)
2649 return "BalancerMember must define balancer name when outside <Proxy > section";
2650 if (!name)
2651 return "BalancerMember must define remote proxy server";
2652 if (!(real = ap_proxy_de_socketfy(cmd->temp_pool, name))) {
2653 return "BalancerMember uses an invalid \"unix:\" URL";
2654 }
2655
2656 ap_str_tolower(path); /* lowercase scheme://hostname */
2657
2658 /* Try to find the balancer */
2659 balancer = ap_proxy_get_balancer(cmd->temp_pool, conf, path, 0);
2660 if (!balancer) {
2661 err = ap_proxy_define_balancer(cmd->pool, &balancer, conf, path, "/", 0);
2662 if (err)
2663 return apr_pstrcat(cmd->temp_pool, "BalancerMember ", err, NULL);
2664 }
2665
2666 /* Try to find existing worker */
2667 worker = ap_proxy_get_worker(cmd->temp_pool, balancer, conf, real);
2668 if (!worker) {
2669 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01147)
2670 "Defining worker '%s' for balancer '%s'",
2671 name, balancer->s->name);
2672 if ((err = ap_proxy_define_worker(cmd->pool, &worker, balancer, conf, name, 0)) != NULL)
2673 return apr_pstrcat(cmd->temp_pool, "BalancerMember ", err, NULL);
2674 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01148)
2675 "Defined worker '%s' for balancer '%s'",
2676 ap_proxy_worker_name(cmd->pool, worker), balancer->s->name);
2677 PROXY_COPY_CONF_PARAMS(worker, conf);
2678 } else {
2679 reuse = 1;
2680 ap_log_error(APLOG_MARK, APLOG_INFO, 0, cmd->server, APLOGNO(01149)
2681 "Sharing worker '%s' instead of creating new worker '%s'",
2682 ap_proxy_worker_name(cmd->pool, worker), name);
2683 }
2684 if (!worker->section_config) {
2685 worker->section_config = balancer->section_config;
2686 }
2687
2689 elts = (const apr_table_entry_t *)arr->elts;
2690 for (i = 0; i < arr->nelts; i++) {
2691 if (reuse) {
2692 ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, APLOGNO(01150)
2693 "Ignoring parameter '%s=%s' for worker '%s' because of worker sharing",
2694 elts[i].key, elts[i].val, ap_proxy_worker_name(cmd->pool, worker));
2695 } else {
2696 err = set_worker_param(cmd->pool, cmd->server, worker, elts[i].key,
2697 elts[i].val);
2698 if (err)
2699 return apr_pstrcat(cmd->temp_pool, "BalancerMember ", err, NULL);
2700 }
2701 }
2702
2703 return NULL;
2704}
2705
2706static const char *
2707 set_proxy_param(cmd_parms *cmd, void *dummy, const char *arg)
2708{
2709 server_rec *s = cmd->server;
2710 proxy_server_conf *conf =
2711 (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);
2712 char *name = NULL;
2713 char *word, *val;
2714 proxy_balancer *balancer = NULL;
2715 proxy_worker *worker = NULL;
2716 unsigned int worker_type = 0;
2717 int in_proxy_section = 0;
2718 /* XXX: Should this be NOT_IN_DIRECTORY|NOT_IN_FILES? */
2720 if (err)
2721 return err;
2722
2723 if (cmd->directive->parent &&
2724 strncasecmp(cmd->directive->parent->directive,
2725 "<Proxy", 6) == 0) {
2726 const char *pargs = cmd->directive->parent->args;
2727 /* Directive inside <Proxy section
2728 * Parent directive arg is the worker/balancer name.
2729 */
2730 name = ap_getword_conf(cmd->temp_pool, &pargs);
2731 if ((word = ap_strchr(name, '>')))
2732 *word = '\0';
2733 if (strncasecmp(cmd->directive->parent->directive + 6,
2734 "Match", 5) == 0) {
2736 }
2737 else {
2739 }
2740 in_proxy_section = 1;
2741 }
2742 else {
2743 /* Standard set directive with worker/balancer
2744 * name as first param.
2745 */
2746 name = ap_getword_conf(cmd->temp_pool, &arg);
2747 }
2748
2750 balancer = ap_proxy_get_balancer(cmd->pool, conf, name, 0);
2751 if (!balancer) {
2752 if (in_proxy_section) {
2753 err = ap_proxy_define_balancer(cmd->pool, &balancer, conf, name, "/", 0);
2754 if (err)
2755 return apr_pstrcat(cmd->temp_pool, "ProxySet ",
2756 err, NULL);
2757 }
2758 else
2759 return apr_pstrcat(cmd->temp_pool, "ProxySet can not find '",
2760 name, "' Balancer.", NULL);
2761 }
2762 }
2763 else {
2764 const char *real;
2765
2766 if (!(real = ap_proxy_de_socketfy(cmd->temp_pool, name))) {
2767 return "ProxySet uses an invalid \"unix:\" URL";
2768 }
2769
2770 worker = ap_proxy_get_worker_ex(cmd->temp_pool, NULL, conf,
2771 real, worker_type);
2772 if (!worker) {
2773 if (in_proxy_section) {
2774 err = ap_proxy_define_worker_ex(cmd->pool, &worker, NULL,
2775 conf, name, worker_type);
2776 if (err)
2777 return apr_pstrcat(cmd->temp_pool, "ProxySet ",
2778 err, NULL);
2779 }
2780 else
2781 return apr_pstrcat(cmd->temp_pool, "ProxySet can not find '",
2782 name, "' Worker.", NULL);
2783 }
2784 }
2785
2786 while (*arg) {
2787 word = ap_getword_conf(cmd->pool, &arg);
2788 val = strchr(word, '=');
2789 if (!val) {
2790 return "Invalid ProxySet parameter. Parameter must be "
2791 "in the form 'key=value'";
2792 }
2793 else
2794 *val++ = '\0';
2795 if (worker)
2796 err = set_worker_param(cmd->pool, cmd->server, worker, word, val);
2797 else
2798 err = set_balancer_param(conf, cmd->pool, balancer, word, val);
2799
2800 if (err)
2801 return apr_pstrcat(cmd->temp_pool, "ProxySet: ", err, " ", word, "=", val, "; ", name, NULL);
2802 }
2803
2804 return NULL;
2805}
2806
2808{
2810 &proxy_module);
2811 void **new_space = (void **)apr_array_push(sconf->sec_proxy);
2812
2814}
2815
2816static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg)
2817{
2818 const char *errmsg;
2819 const char *endp = ap_strrchr_c(arg, '>');
2820 int old_overrides = cmd->override;
2821 char *old_path = cmd->path;
2822 proxy_dir_conf *conf;
2824 ap_regex_t *r = NULL;
2825 const command_rec *thiscmd = cmd->cmd;
2826 char *word, *val;
2827 proxy_balancer *balancer = NULL;
2828 proxy_worker *worker = NULL;
2832 (proxy_server_conf *) ap_get_module_config(cmd->server->module_config, &proxy_module);
2833
2834 if (err != NULL) {
2835 return err;
2836 }
2837
2838 if (endp == NULL) {
2839 return apr_pstrcat(cmd->pool, cmd->cmd->name,
2840 "> directive missing closing '>'", NULL);
2841 }
2842
2843 arg = apr_pstrndup(cmd->pool, arg, endp-arg);
2844
2845 if (!arg) {
2846 if (thiscmd->cmd_data)
2847 return "<ProxyMatch > block must specify a path";
2848 else
2849 return "<Proxy > block must specify a path";
2850 }
2851
2852 cmd->path = ap_getword_conf(cmd->pool, &arg);
2853 cmd->override = OR_ALL|ACCESS_CONF|PROXY_CONF;
2854
2855 if (!strncasecmp(cmd->path, "proxy:", 6))
2856 cmd->path += 6;
2857
2858 /* XXX Ignore case? What if we proxy a case-insensitive server?!?
2859 * While we are at it, shouldn't we also canonicalize the entire
2860 * scheme? See proxy_fixup()
2861 */
2862 if (thiscmd->cmd_data) { /* <ProxyMatch> */
2863 r = ap_pregcomp(cmd->pool, cmd->path, AP_REG_EXTENDED);
2864 if (!r) {
2865 return "Regex could not be compiled";
2866 }
2868 }
2869
2870 /* initialize our config and fetch it */
2871 conf = ap_set_config_vectors(cmd->server, new_dir_conf, cmd->path,
2872 &proxy_module, cmd->pool);
2873
2874 errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_dir_conf);
2875 if (errmsg != NULL)
2876 return errmsg;
2877
2878 conf->r = r;
2879 conf->p = cmd->path;
2880 conf->p_is_fnmatch = apr_fnmatch_test(conf->p);
2881
2882 if (r) {
2883 conf->refs = apr_array_make(cmd->pool, 8, sizeof(char *));
2884 ap_regname(r, conf->refs, AP_REG_MATCH, 1);
2885 }
2886
2888
2889 if (*arg != '\0') {
2890 if (thiscmd->cmd_data)
2891 return "Multiple <ProxyMatch> arguments not (yet) supported.";
2892 if (conf->p_is_fnmatch)
2893 return apr_pstrcat(cmd->pool, thiscmd->name,
2894 "> arguments are not supported for wildchar url.",
2895 NULL);
2896 if (!ap_strchr_c(conf->p, ':'))
2897 return apr_pstrcat(cmd->pool, thiscmd->name,
2898 "> arguments are not supported for non url.",
2899 NULL);
2900 if (ap_proxy_valid_balancer_name((char *)conf->p, 9)) {
2901 balancer = ap_proxy_get_balancer(cmd->pool, sconf, conf->p, 0);
2902 if (!balancer) {
2903 err = ap_proxy_define_balancer(cmd->pool, &balancer,
2904 sconf, conf->p, "/", 0);
2905 if (err)
2906 return apr_pstrcat(cmd->temp_pool, thiscmd->name,
2907 " ", err, NULL);
2908 }
2909 if (!balancer->section_config) {
2910 balancer->section_config = new_dir_conf;
2911 }
2912 }
2913 else {
2914 const char *real;
2915
2916 if (!(real = ap_proxy_de_socketfy(cmd->temp_pool, conf->p))) {
2917 return "<Proxy/ProxyMatch > uses an invalid \"unix:\" URL";
2918 }
2919
2920 worker = ap_proxy_get_worker_ex(cmd->temp_pool, NULL, sconf,
2921 real, worker_type);
2922 if (!worker) {
2923 err = ap_proxy_define_worker_ex(cmd->pool, &worker, NULL, sconf,
2924 conf->p, worker_type);
2925 if (err)
2926 return apr_pstrcat(cmd->temp_pool, thiscmd->name,
2927 " ", err, NULL);
2928 }
2929 if (!worker->section_config) {
2930 worker->section_config = new_dir_conf;
2931 }
2932 }
2933 if (worker == NULL && balancer == NULL) {
2934 return apr_pstrcat(cmd->pool, thiscmd->name,
2935 "> arguments are supported only for workers.",
2936 NULL);
2937 }
2938 while (*arg) {
2939 word = ap_getword_conf(cmd->pool, &arg);
2940 val = strchr(word, '=');
2941 if (!val) {
2942 return "Invalid Proxy parameter. Parameter must be "
2943 "in the form 'key=value'";
2944 }
2945 else
2946 *val++ = '\0';
2947 if (worker)
2948 err = set_worker_param(cmd->pool, cmd->server, worker, word, val);
2949 else
2950 err = set_balancer_param(sconf, cmd->pool, balancer,
2951 word, val);
2952 if (err)
2953 return apr_pstrcat(cmd->temp_pool, thiscmd->name, " ", err, " ",
2954 word, "=", val, "; ", conf->p, NULL);
2955 }
2956 }
2957
2958 cmd->path = old_path;
2959 cmd->override = old_overrides;
2960
2961 return NULL;
2962}
2963
2964static const command_rec proxy_cmds[] =
2965{
2967 "Container for directives affecting resources located in the proxied "
2968 "location"),
2969 AP_INIT_RAW_ARGS("<ProxyMatch", proxysection, (void*)1, RSRC_CONF,
2970 "Container for directives affecting resources located in the proxied "
2971 "location, in regular expression syntax"),
2972 AP_INIT_FLAG("ProxyRequests", set_proxy_req, NULL, RSRC_CONF,
2973 "on if the true proxy requests should be accepted"),
2975 "a scheme, partial URL or '*' and a proxy server"),
2976 AP_INIT_TAKE23("ProxyRemoteMatch", add_proxy_regex, NULL, RSRC_CONF,
2977 "a regex pattern and a proxy server"),
2978 AP_INIT_FLAG("ProxyPassInterpolateEnv", ap_set_flag_slot_char,
2979 (void*)APR_OFFSETOF(proxy_dir_conf, interpolate_env),
2980 RSRC_CONF|ACCESS_CONF, "Interpolate Env Vars in reverse Proxy") ,
2982 "a virtual path and a URL"),
2984 "a virtual path and a URL"),
2986 "a virtual path and a URL for reverse proxy behaviour"),
2987 AP_INIT_TAKE23("ProxyPassReverseCookiePath", cookie_path, NULL,
2988 RSRC_CONF|ACCESS_CONF, "Path rewrite rule for proxying cookies"),
2989 AP_INIT_TAKE23("ProxyPassReverseCookieDomain", cookie_domain, NULL,
2990 RSRC_CONF|ACCESS_CONF, "Domain rewrite rule for proxying cookies"),
2992 "A list of names, hosts or domains to which the proxy will not connect"),
2993 AP_INIT_TAKE1("ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF,
2994 "Receive buffer size for outgoing HTTP and FTP connections in bytes"),
2995 AP_INIT_TAKE1("ProxyIOBufferSize", set_io_buffer_size, NULL, RSRC_CONF,
2996 "IO buffer size for outgoing HTTP and FTP connections in bytes"),
2997 AP_INIT_TAKE1("ProxyMaxForwards", set_max_forwards, NULL, RSRC_CONF,
2998 "The maximum number of proxies a request may be forwarded through."),
3000 "A list of domains, hosts, or subnets to which the proxy will connect directly"),
3002 "The default intranet domain name (in absence of a domain in the URL)"),
3004 "Configure Via: proxy header header to one of: on | off | block | full"),
3006 "use our error handling pages instead of the servers' we are proxying"),
3008 "on if we should preserve host header while proxying"),
3010 "Set the timeout (in seconds) for a proxied connection. "
3011 "This overrides the server timeout"),
3012 AP_INIT_TAKE1("ProxyBadHeader", set_bad_opt, NULL, RSRC_CONF,
3013 "How to handle bad header line in response: IsError | Ignore | StartBody"),
3015 "A balancer name and scheme with list of params"),
3016 AP_INIT_TAKE1("BalancerGrowth", set_bgrowth, NULL, RSRC_CONF,
3017 "Number of additional Balancers that can be added post-config"),
3018 AP_INIT_FLAG("BalancerPersist", set_persist, NULL, RSRC_CONF,
3019 "on if the balancer should persist changes on reboot/restart made via the Balancer Manager"),
3020 AP_INIT_FLAG("BalancerInherit", set_inherit, NULL, RSRC_CONF,
3021 "on if this server should inherit Balancers and Workers defined in the main server "
3022 "(Setting to off recommended if using the Balancer Manager)"),
3023 AP_INIT_FLAG("ProxyPassInherit", set_ppinherit, NULL, RSRC_CONF,
3024 "on if this server should inherit all ProxyPass directives defined in the main server "
3025 "(Setting to off recommended if using the Balancer Manager)"),
3026 AP_INIT_TAKE1("ProxyStatus", set_status_opt, NULL, RSRC_CONF,
3027 "Configure Status: proxy status to one of: on | off | full"),
3029 "A balancer or worker name with list of params"),
3030 AP_INIT_TAKE1("ProxySourceAddress", set_source_address, NULL, RSRC_CONF,
3031 "Configure local source IP used for request forward"),
3033 "on if X-Forwarded-* headers should be added or completed"),
3035 "on if 100-Continue should be forwarded to the origin server, off if the "
3036 "proxy should handle it by itself"),
3037 {NULL}
3038};
3039
3043
3045{
3046 /*
3047 * if c == NULL just check if the optional function was imported
3048 * else run the optional function so ssl filters are inserted
3049 */
3050 if (c == NULL) {
3052 }
3053 return ap_ssl_bind_outgoing(c, NULL, 1) == OK;
3054}
3055
3060
3062 ap_conf_vector_t *per_dir_config,
3063 int enable)
3064{
3065 /*
3066 * if c == NULL just check if the optional function was imported
3067 * else run the optional function so ssl filters are inserted
3068 */
3069 if (c == NULL) {
3071 }
3072 return ap_ssl_bind_outgoing(c, per_dir_config, enable) == OK;
3073}
3074
3079
3082 const char *var)
3083{
3084 return ap_ssl_var_lookup(p, s, c, r, var);
3085}
3086
3088 apr_pool_t *ptemp, server_rec *main_s)
3089{
3090 server_rec *s = main_s;
3092 proxy_id, NULL, s, pconf, 0);
3093 if (rv != APR_SUCCESS) {
3095 "failed to create %s mutex", proxy_id);
3096 return rv;
3097 }
3098
3104
3105 for (; s; s = s->next) {
3106 int rc, i;
3108 ap_get_module_config(s->module_config, &proxy_module);
3110 (ap_conf_vector_t **)sconf->sec_proxy->elts;
3111
3112 for (i = 0; i < sconf->sec_proxy->nelts; ++i) {
3114 s, sections[i]);
3115 if (rc != OK && rc != DECLINED) {
3116 return rc;
3117 }
3118 }
3119 }
3120
3121 return OK;
3122}
3123
3124/*
3125 * proxy Extension to mod_status
3126 */
3128{
3129 int i, n;
3130 void *sconf = r->server->module_config;
3132 ap_get_module_config(sconf, &proxy_module);
3133 proxy_balancer *balancer = NULL;
3134 proxy_worker **worker = NULL;
3135
3136 if (conf->balancers->nelts == 0 ||
3137 conf->proxy_status == status_off)
3138 return OK;
3139
3140 balancer = (proxy_balancer *)conf->balancers->elts;
3141 for (i = 0; i < conf->balancers->nelts; i++) {
3142 if (!(flags & AP_STATUS_SHORT)) {
3143 ap_rputs("<hr />\n<h1>Proxy LoadBalancer Status for ", r);
3144 ap_rvputs(r, balancer->s->name, "</h1>\n\n", NULL);
3145 ap_rputs("\n\n<table border=\"0\"><tr>"
3146 "<th>SSes</th><th>Timeout</th><th>Method</th>"
3147 "</tr>\n<tr>", r);
3148 if (*balancer->s->sticky) {
3149 if (strcmp(balancer->s->sticky, balancer->s->sticky_path)) {
3150 ap_rvputs(r, "<td>", balancer->s->sticky, " | ",
3151 balancer->s->sticky_path, NULL);
3152 }
3153 else {
3154 ap_rvputs(r, "<td>", balancer->s->sticky, NULL);
3155 }
3156 }
3157 else {
3158 ap_rputs("<td> - ", r);
3159 }
3160 ap_rprintf(r, "</td><td>%" APR_TIME_T_FMT "</td>",
3161 apr_time_sec(balancer->s->timeout));
3162 ap_rprintf(r, "<td>%s</td>\n",
3163 balancer->lbmethod->name);
3164 ap_rputs("</table>\n", r);
3165 ap_rputs("\n\n<table border=\"0\"><tr>"
3166 "<th>Sch</th><th>Host</th><th>Stat</th>"
3167 "<th>Route</th><th>Redir</th>"
3168 "<th>F</th><th>Set</th><th>Acc</th><th>Busy</th><th>Wr</th><th>Rd</th>"
3169 "</tr>\n", r);
3170 }
3171 else {
3172 ap_rprintf(r, "ProxyBalancer[%d]Name: %s\n", i, balancer->s->name);
3173 }
3174
3175 worker = (proxy_worker **)balancer->workers->elts;
3176 for (n = 0; n < balancer->workers->nelts; n++) {
3177 char fbuf[50];
3178 if (!(flags & AP_STATUS_SHORT)) {
3179 ap_rvputs(r, "<tr>\n<td>", (*worker)->s->scheme, "</td>", NULL);
3180 ap_rvputs(r, "<td>", (*worker)->s->hostname_ex, "</td><td>", NULL);
3182 ap_rvputs(r, "</td><td>", (*worker)->s->route, NULL);
3183 ap_rvputs(r, "</td><td>", (*worker)->s->redirect, NULL);
3184 ap_rprintf(r, "</td><td>%.2f</td>", (float)((*worker)->s->lbfactor)/100.0);
3185 ap_rprintf(r, "<td>%d</td>", (*worker)->s->lbset);
3186 ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td>",
3187 (*worker)->s->elected);
3188 ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td><td>",
3189 (*worker)->s->busy);
3190 ap_rputs(apr_strfsize((*worker)->s->transferred, fbuf), r);
3191 ap_rputs("</td><td>", r);
3192 ap_rputs(apr_strfsize((*worker)->s->read, fbuf), r);
3193 ap_rputs("</td>\n", r);
3194
3195 /* TODO: Add the rest of dynamic worker data */
3196 ap_rputs("</tr>\n", r);
3197 }
3198 else {
3199 ap_rprintf(r, "ProxyBalancer[%d]Worker[%d]Name: %s\n",
3200 i, n, (*worker)->s->name_ex);
3201 ap_rprintf(r, "ProxyBalancer[%d]Worker[%d]Status: %s\n",
3202 i, n, ap_proxy_parse_wstatus(r->pool, *worker));
3203 ap_rprintf(r, "ProxyBalancer[%d]Worker[%d]Elected: %"
3204 APR_SIZE_T_FMT "\n",
3205 i, n, (*worker)->s->elected);
3206 ap_rprintf(r, "ProxyBalancer[%d]Worker[%d]Busy: %"
3207 APR_SIZE_T_FMT "\n",
3208 i, n, (*worker)->s->busy);
3209 ap_rprintf(r, "ProxyBalancer[%d]Worker[%d]Sent: %"
3210 APR_OFF_T_FMT "K\n",
3211 i, n, (*worker)->s->transferred >> 10);
3212 ap_rprintf(r, "ProxyBalancer[%d]Worker[%d]Rcvd: %"
3213 APR_OFF_T_FMT "K\n",
3214 i, n, (*worker)->s->read >> 10);
3215
3216 /* TODO: Add the rest of dynamic worker data */
3217 }
3218
3219 ++worker;
3220 }
3221 if (!(flags & AP_STATUS_SHORT)) {
3222 ap_rputs("</table>\n", r);
3223 }
3224 ++balancer;
3225 }
3226 if (!(flags & AP_STATUS_SHORT)) {
3227 ap_rputs("<hr /><table>\n"
3228 "<tr><th>SSes</th><td>Sticky session name</td></tr>\n"
3229 "<tr><th>Timeout</th><td>Balancer Timeout</td></tr>\n"
3230 "<tr><th>Sch</th><td>Connection scheme</td></tr>\n"
3231 "<tr><th>Host</th><td>Backend Hostname</td></tr>\n"
3232 "<tr><th>Stat</th><td>Worker status</td></tr>\n"
3233 "<tr><th>Route</th><td>Session Route</td></tr>\n"
3234 "<tr><th>Redir</th><td>Session Route Redirection</td></tr>\n"
3235 "<tr><th>F</th><td>Load Balancer Factor</td></tr>\n"
3236 "<tr><th>Acc</th><td>Number of uses</td></tr>\n"
3237 "<tr><th>Wr</th><td>Number of bytes transferred</td></tr>\n"
3238 "<tr><th>Rd</th><td>Number of bytes read</td></tr>\n"
3239 "</table>", r);
3240 }
3241
3242 return OK;
3243}
3244
3246{
3248
3251 p);
3252 if (rv != APR_SUCCESS) {
3254 "could not init proxy_mutex in child");
3255 exit(1); /* Ugly, but what else? */
3256 }
3257
3258 /* TODO */
3259 while (s) {
3260 void *sconf = s->module_config;
3261 proxy_server_conf *conf;
3262 proxy_worker *worker;
3263 int i;
3264
3265 conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
3266 /*
3267 * NOTE: non-balancer members don't use shm at all...
3268 * after all, why should they?
3269 */
3270 worker = (proxy_worker *)conf->workers->elts;
3271 for (i = 0; i < conf->workers->nelts; i++, worker++) {
3272 ap_proxy_initialize_worker(worker, s, p);
3273 }
3274 /* Create and initialize forward worker if defined */
3275 if (conf->req_set && conf->req) {
3276 proxy_worker *forward;
3277 ap_proxy_define_worker(conf->pool, &forward, NULL, NULL,
3278 "http://www.apache.org", 0);
3279 conf->forward = forward;
3280 PROXY_STRNCPY(conf->forward->s->name, "proxy:forward");
3281 PROXY_STRNCPY(conf->forward->s->name_ex, "proxy:forward");
3282 PROXY_STRNCPY(conf->forward->s->hostname, "*"); /* for compatibility */
3283 PROXY_STRNCPY(conf->forward->s->hostname_ex, "*");
3284 PROXY_STRNCPY(conf->forward->s->scheme, "*");
3285 conf->forward->hash.def = conf->forward->s->hash.def =
3287 conf->forward->hash.fnv = conf->forward->s->hash.fnv =
3289 /* Do not disable worker in case of errors */
3291 /* Mark as the "generic" worker */
3294 /* Disable address cache for generic forward worker */
3295 conf->forward->s->is_address_reusable = 0;
3296 }
3297 if (!reverse) {
3299 "http://www.apache.org", 0);
3300 PROXY_STRNCPY(reverse->s->name, "proxy:reverse");
3301 PROXY_STRNCPY(reverse->s->name_ex, "proxy:reverse");
3302 PROXY_STRNCPY(reverse->s->hostname, "*"); /* for compatibility */
3303 PROXY_STRNCPY(reverse->s->hostname_ex, "*");
3304 PROXY_STRNCPY(reverse->s->scheme, "*");
3305 reverse->hash.def = reverse->s->hash.def =
3307 reverse->hash.fnv = reverse->s->hash.fnv =
3309 /* Do not disable worker in case of errors */
3310 reverse->s->status |= PROXY_WORKER_IGNORE_ERRORS;
3311 /* Mark as the "generic" worker */
3312 reverse->s->status |= PROXY_WORKER_GENERIC;
3313 conf->reverse = reverse;
3315 /* Disable address cache for generic reverse worker */
3316 reverse->s->is_address_reusable = 0;
3317 }
3318 conf->reverse = reverse;
3319 s = s->next;
3320 }
3321}
3322
3323/*
3324 * This routine is called before the server processes the configuration
3325 * files.
3326 */
3328 apr_pool_t *ptemp)
3329{
3331 APR_LOCK_DEFAULT, 0);
3332 if (rv != APR_SUCCESS) {
3334 "failed to register %s mutex", proxy_id);
3335 return 500; /* An HTTP status would be a misnomer! */
3336 }
3337
3340 /* Reset workers count on graceful restart */
3341 proxy_lb_workers = 0;
3343 return OK;
3344}
3346{
3347 /* fixup before mod_rewrite, so that the proxied url will not
3348 * escaped accidentally by our fixup.
3349 */
3350 static const char * const aszSucc[] = { "mod_rewrite.c", NULL};
3351 /* Only the mpm_winnt has child init hook handler.
3352 * make sure that we are called after the mpm
3353 * initializes.
3354 */
3355 static const char *const aszPred[] = { "mpm_winnt.c", "mod_proxy_balancer.c",
3356 "mod_proxy_hcheck.c", NULL};
3357 /* handler */
3359 /* filename-to-URI translation */
3364 /* walk <Proxy > entries and suppress default TRACE behavior */
3366 /* fixups */
3368 /* post read_request handling */
3370 /* pre config handling */
3372 /* post config handling */
3374 /* child init handling */
3376
3377 /* register optional functions within proxy_util.c */
3379}
3380
3382{
3384 create_proxy_dir_config, /* create per-directory config structure */
3385 merge_proxy_dir_config, /* merge per-directory config structures */
3386 create_proxy_config, /* create per-server config structure */
3387 merge_proxy_config, /* merge per-server config structures */
3388 proxy_cmds, /* command table */
3390};
3391
3400
3402 (request_rec *r, proxy_worker *worker,
3403 proxy_server_conf *conf,
3404 char *url, const char *proxyhost,
3405 apr_port_t proxyport),(r,worker,conf,
3408 (request_rec *r, const char *url),
3411 (request_rec *r, char *url),(r,
3414 proxy_worker **worker,
3415 proxy_balancer **balancer,
3416 request_rec *r,
3417 proxy_server_conf *conf,
3418 char **url),(worker,balancer,
3421 (proxy_worker *worker,
3422 proxy_balancer *balancer,
3423 request_rec *r,
3424 proxy_server_conf *conf),(worker,
3425 balancer,r,conf),DECLINED)
3428 apr_pool_t *ptemp, server_rec *s,
3429 ap_conf_vector_t *section_config),
3430 (p, ptemp, plog, s, section_config),
3433 (request_rec *r), (r),
3436 (int *status, request_rec *r),
3437 (status, r),
int n
Definition ap_regex.h:278
int int const char ** match
Definition ap_regex.h:279
const char apr_size_t ap_regmatch_t * pmatch
Definition ap_regex.h:172
const char apr_size_t len
Definition ap_regex.h:187
#define AP_REG_MATCH
Definition ap_regex.h:89
const char apr_size_t nmatch
Definition ap_regex.h:172
#define AP_REG_EXTENDED
Definition ap_regex.h:78
#define APR_STRINGIFY(n)
Definition ap_release.h:62
#define AP_PROXY_RUN_FINISHED(arg0, arg1, arg2)
#define AP_PROXY_RUN(arg0, arg1, arg2, arg3, arg4)
APR-UTIL registration of functions exported by modules.
#define f1(x, y, z)
Definition apr_sha1.c:63
APR Strings library.
apr_array_append(apr_pool_t *p, const apr_array_header_t *first, const apr_array_header_t *second)
Definition apr_tables.c:213
ap_conf_vector_t * ap_merge_per_dir_configs(apr_pool_t *p, ap_conf_vector_t *base, ap_conf_vector_t *new_conf)
Definition config.c:285
void * ap_set_config_vectors(server_rec *server, ap_conf_vector_t *section_vector, const char *section, module *mod, apr_pool_t *pconf)
Definition config.c:1082
ap_conf_vector_t * ap_create_per_dir_config(apr_pool_t *p)
Definition config.c:366
return found
Definition core.c:2840
static apr_pool_t * pconf
Definition event.c:441
static void reverse(const char **argv, int start, int len)
Definition getopt.c:141
#define AP_INIT_TAKE123(directive, func, mconfig, where, help)
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
#define ap_get_module_config(v, m)
void ap_hook_post_config(ap_HOOK_post_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:105
struct ap_conf_vector_t ap_conf_vector_t
#define AP_DECLARE_MODULE(foo)
#define AP_INIT_FLAG(directive, func, mconfig, where, help)
ap_conf_vector_t * base
#define AP_INIT_ITERATE(directive, func, mconfig, where, help)
const char * ap_set_flag_slot_char(cmd_parms *cmd, void *struct_ptr, int arg)
Definition config.c:1523
#define AP_INIT_RAW_ARGS(directive, func, mconfig, where, help)
void ap_hook_handler(ap_HOOK_handler_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:170
void ap_hook_pre_config(ap_HOOK_pre_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:91
const char * hostname
request_rec int int apr_table_t const char * path
const char server_rec server_rec ** ps
request_rec * r
const char * ap_walk_config(ap_directive_t *conftree, cmd_parms *parms, ap_conf_vector_t *section_vector)
Definition config.c:1360
void ap_hook_child_init(ap_HOOK_child_init_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:167
#define AP_INIT_TAKE23(directive, func, mconfig, where, help)
#define HUGE_STRING_LEN
Definition httpd.h:303
#define ap_default_port(r)
Definition httpd.h:292
#define ap_http_scheme(r)
Definition httpd.h:297
#define AP_IOBUFSIZE
Definition httpd.h:306
#define AP_MAX_REG_MATCH
Definition httpd.h:309
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
#define DONE
Definition httpd.h:458
#define ap_get_core_module_config(v)
Definition http_core.h:383
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_STARTUP
Definition http_log.h:105
#define APLOG_INFO
Definition http_log.h:70
#define ap_log_rerror
Definition http_log.h:454
#define APLOG_ERR
Definition http_log.h:67
#define ap_log_error
Definition http_log.h:370
#define APLOG_MARK
Definition http_log.h:283
#define ap_log_perror
Definition http_log.h:412
#define APLOG_WARNING
Definition http_log.h:68
#define APLOG_CRIT
Definition http_log.h:66
#define APLOG_TRACE2
Definition http_log.h:73
#define APLOG_TRACE1
Definition http_log.h:72
#define APLOG_DEBUG
Definition http_log.h:71
apr_status_t ap_global_mutex_create(apr_global_mutex_t **mutex, const char **name, const char *type, const char *instance_id, server_rec *server, apr_pool_t *pool, apr_int32_t options)
Definition util_mutex.c:407
apr_status_t ap_mutex_register(apr_pool_t *pconf, const char *type, const char *default_dir, apr_lockmech_e default_mech, apr_int32_t options)
Definition util_mutex.c:254
int ap_rvputs(request_rec *r,...)
Definition protocol.c:2220
int ap_rprintf(request_rec *r, const char *fmt,...) __attribute__((format(printf
int ap_ssl_bind_outgoing(conn_rec *c, struct ap_conf_vector_t *dir_conf, int require_ssl)
Definition ssl.c:128
static APR_INLINE int ap_rputs(const char *str, request_rec *r)
void ap_hook_post_read_request(ap_HOOK_post_read_request_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition protocol.c:2585
const char * ap_ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *name)
Definition ssl.c:186
int ap_ssl_has_outgoing_handlers(void)
Definition ssl.c:164
int ap_ssl_conn_is_ssl(conn_rec *c)
Definition ssl.c:90
void * ap_lookup_provider(const char *provider_group, const char *provider_name, const char *provider_version)
Definition provider.c:99
void ap_hook_pre_translate_name(ap_HOOK_pre_translate_name_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition request.c:79
void ap_hook_translate_name(ap_HOOK_translate_name_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition request.c:81
void ap_hook_map_to_storage(ap_HOOK_map_to_storage_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition request.c:83
void ap_hook_fixups(ap_HOOK_fixups_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition request.c:87
void ap_die(int type, request_rec *r)
const char apr_port_t port
Definition http_vhost.h:125
void * dummy
Definition http_vhost.h:62
void const char * arg
Definition http_vhost.h:63
apr_file_t * f
apr_dbd_transaction_t int mode
Definition apr_dbd.h:261
apr_pool_t const char * params
Definition apr_dbd.h:141
const char apr_ssize_t int flags
Definition apr_encode.h:168
const char * url
Definition apr_escape.h:120
#define APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(ns, link, ret, name, args_decl, args_use, decline)
Definition apr_hooks.h:267
const char *const const char *const * aszSucc
Definition apr_hooks.h:346
#define APR_HOOK_FIRST
Definition apr_hooks.h:301
#define APR_HOOK_LINK(name)
Definition apr_hooks.h:139
#define APR_HOOK_STRUCT(members)
Definition apr_hooks.h:135
#define APR_HOOK_MIDDLE
Definition apr_hooks.h:303
#define APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ns, link, ret, name, args_decl, args_use, ok, decline)
#define APR_OPTIONAL_HOOK(ns, name, pfn, aszPre, aszSucc, nOrder)
#define APR_RETRIEVE_OPTIONAL_FN(name)
#define APR_OPTIONAL_FN_TYPE(name)
#define APR_DECLARE_OPTIONAL_FN(ret, name, args)
apr_redis_t * rc
Definition apr_redis.h:173
#define APR_URI_UNP_REVEALPASSWORD
Definition apr_uri.h:73
const char * uri
Definition apr_uri.h:159
#define APR_URI_UNP_OMITUSERINFO
Definition apr_uri.h:70
#define ACCESS_CONF
#define OR_ALL
#define RSRC_CONF
#define PROXY_CONF
#define HTTP_BAD_REQUEST
Definition httpd.h:508
#define ap_is_HTTP_VALID_RESPONSE(x)
Definition httpd.h:560
#define HTTP_SERVICE_UNAVAILABLE
Definition httpd.h:538
#define HTTP_CONTINUE
Definition httpd.h:487
#define HTTP_BAD_GATEWAY
Definition httpd.h:537
#define HTTP_INTERNAL_SERVER_ERROR
Definition httpd.h:535
#define ap_is_HTTP_REDIRECT(x)
Definition httpd.h:552
#define ap_is_HTTP_ERROR(x)
Definition httpd.h:554
#define HTTP_METHOD_NOT_ALLOWED
Definition httpd.h:513
#define HTTP_REQUEST_ENTITY_TOO_LARGE
Definition httpd.h:521
#define HTTP_MOVED_PERMANENTLY
Definition httpd.h:501
int ap_send_http_trace(request_rec *r)
int ap_send_http_options(request_rec *r)
const apr_strmatch_pattern * ap_proxy_strmatch_path
Definition proxy_util.c:73
const apr_strmatch_pattern * ap_proxy_strmatch_domain
Definition proxy_util.c:74
int proxy_lb_workers
Definition proxy_util.c:71
void proxy_util_register_hooks(apr_pool_t *p)
int proxy_run_section_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s, ap_conf_vector_t *section_config)
Definition mod_proxy.c:3431
#define PROXY_DECLARE_DATA
Definition mod_proxy.h:606
int ap_proxy_ssl_engine(conn_rec *c, ap_conf_vector_t *per_dir_config, int enable)
Definition mod_proxy.c:3061
#define PROXYPASS_MAP_ENCODED
Definition mod_proxy.h:132
#define PROXY_WORKER_IS_USABLE(f)
Definition mod_proxy.h:358
#define PROXYPASS_MAP_SERVLET
Definition mod_proxy.h:133
int proxy_run_request_status(int *status, request_rec *r)
Definition mod_proxy.c:3438
int ap_proxy_ssl_disable(conn_rec *c)
Definition mod_proxy.c:3056
#define PROXY_WORKER_DRAIN_FLAG
Definition mod_proxy.h:336
apr_status_t ap_proxy_set_wstatus(char c, int set, proxy_worker *w)
#define PROXY_WORKER_DISABLED_FLAG
Definition mod_proxy.h:339
#define PROXY_DECLARE(type)
Definition mod_proxy.h:604
#define PROXY_WORKER_STOPPED
Definition mod_proxy.h:326
#define PROXY_STRNCPY(dst, src)
Definition mod_proxy.h:395
#define PROXY_WORKER_GENERIC_FLAG
Definition mod_proxy.h:337
#define PROXY_WORKER_IN_ERROR
Definition mod_proxy.h:327
#define PROXY_WORKER_HC_FAIL
Definition mod_proxy.h:330
char * ap_proxy_define_balancer(apr_pool_t *p, proxy_balancer **balancer, proxy_server_conf *conf, const char *url, const char *alias, int do_malloc)
#define PROXY_WORKER_HOT_SPARE_FLAG
Definition mod_proxy.h:345
proxy_worker * ap_proxy_get_worker(apr_pool_t *p, proxy_balancer *balancer, proxy_server_conf *conf, const char *url)
#define PROXY_WORKER_IGNORE_ERRORS
Definition mod_proxy.h:321
char * ap_proxy_define_worker(apr_pool_t *p, proxy_worker **worker, proxy_balancer *balancer, proxy_server_conf *conf, const char *url, int do_malloc)
const char * ap_proxy_de_socketfy(apr_pool_t *p, const char *url)
Definition mod_proxy.c:1938
#define PROXY_COPY_CONF_PARAMS(w, c)
Definition mod_proxy.h:397
int proxy_run_scheme_handler(request_rec *r, proxy_worker *worker, proxy_server_conf *conf, char *url, const char *proxyhost, apr_port_t proxyport)
Definition mod_proxy.c:3406
int ap_proxy_trans_match(request_rec *r, struct proxy_alias *ent, proxy_dir_conf *dconf)
Definition mod_proxy.c:825
#define PROXYPASS_INTERPOLATE
Definition mod_proxy.h:130
#define PROXY_WORKER_INITIALIZED
Definition mod_proxy.h:320
#define PROXY_WORKER_IGNORE_ERRORS_FLAG
Definition mod_proxy.h:335
#define DEFAULT_MAX_FORWARDS
Definition mod_proxy.h:111
#define PROXY_WORKER_STOPPED_FLAG
Definition mod_proxy.h:340
char * ap_proxy_define_worker_ex(apr_pool_t *p, proxy_worker **worker, proxy_balancer *balancer, proxy_server_conf *conf, const char *url, unsigned int mask)
int ap_proxy_post_request(proxy_worker *worker, proxy_balancer *balancer, request_rec *r, proxy_server_conf *conf)
#define PROXYPASS_NOCANON
Definition mod_proxy.h:129
#define PROXY_WORKER_HOT_STANDBY
Definition mod_proxy.h:328
proxy_worker * ap_proxy_get_worker_ex(apr_pool_t *p, proxy_balancer *balancer, proxy_server_conf *conf, const char *url, unsigned int mask)
#define PROXY_LBMETHOD
Definition mod_proxy.h:1444
proxy_balancer * ap_proxy_get_balancer(apr_pool_t *p, proxy_server_conf *conf, const char *url, int careactive)
#define PROXY_WORKER_HOT_SPARE
Definition mod_proxy.h:331
int ap_proxy_valid_balancer_name(char *name, int i)
#define AP_PROXY_WORKER_IS_MATCH
Definition mod_proxy.h:774
#define PROXY_WORKER_INITIALIZED_FLAG
Definition mod_proxy.h:334
#define PROXY_WORKER_IN_SHUTDOWN
Definition mod_proxy.h:324
int ap_proxy_conn_is_https(conn_rec *c)
Definition mod_proxy.c:3075
#define PROXY_WORKER_GENERIC
Definition mod_proxy.h:323
proxy_wstat_t proxy_wstat_tbl[]
Definition mod_proxy.c:61
int ap_proxy_pre_request(proxy_worker **worker, proxy_balancer **balancer, request_rec *r, proxy_server_conf *conf, char **url)
#define PROXY_WORKER_IN_SHUTDOWN_FLAG
Definition mod_proxy.h:338
char * ap_proxy_parse_wstatus(apr_pool_t *p, proxy_worker *w)
int proxy_run_check_trans(request_rec *r, const char *url)
Definition mod_proxy.c:3409
unsigned int ap_proxy_hashfunc(const char *str, proxy_hash_t method)
apr_status_t ap_proxy_initialize_worker(proxy_worker *worker, server_rec *s, apr_pool_t *p)
#define PROXY_WORKER_HOT_STANDBY_FLAG
Definition mod_proxy.h:342
int ap_proxyerror(request_rec *r, int statuscode, const char *message)
Definition proxy_util.c:432
#define PROXYPASS_NOQUERY
Definition mod_proxy.h:131
#define PROXY_WORKER_DRAIN
Definition mod_proxy.h:322
#define PROXY_FLUSH_WAIT
Definition mod_proxy.h:524
#define PROXY_WORKER_HC_FAIL_FLAG
Definition mod_proxy.h:344
#define PROXY_WORKER_FREE
Definition mod_proxy.h:329
int ap_proxy_ssl_enable(conn_rec *c)
Definition mod_proxy.c:3044
#define PROXY_WORKER_DISABLED
Definition mod_proxy.h:325
#define PROXY_WORKER_IN_ERROR_FLAG
Definition mod_proxy.h:341
#define PROXY_WORKER_FREE_FLAG
Definition mod_proxy.h:343
proxy_hcmethods_t proxy_hcmethods[]
Definition mod_proxy.c:47
char * ap_proxy_worker_name(apr_pool_t *p, proxy_worker *worker)
#define AP_PROXY_WORKER_IS_PREFIX
Definition mod_proxy.h:773
const char * ap_proxy_ssl_val(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *var)
Definition mod_proxy.c:3080
char * ap_proxy_update_balancer(apr_pool_t *p, proxy_balancer *balancer, const char *url)
@ HEAD
Definition mod_proxy.h:84
@ HEAD11
Definition mod_proxy.h:84
@ GET
Definition mod_proxy.h:84
@ OPTIONS
Definition mod_proxy.h:84
@ PROVIDER
Definition mod_proxy.h:84
@ EOT
Definition mod_proxy.h:84
@ GET11
Definition mod_proxy.h:84
@ OPTIONS11
Definition mod_proxy.h:84
@ TCP
Definition mod_proxy.h:84
@ CPING
Definition mod_proxy.h:84
@ NONE
Definition mod_proxy.h:84
@ PROXY_HASHFUNC_DEFAULT
Definition mod_proxy.h:1234
@ PROXY_HASHFUNC_FNV
Definition mod_proxy.h:1234
#define AP_STATUS_SHORT
Definition mod_status.h:32
#define M_OPTIONS
Definition httpd.h:597
#define M_CONNECT
Definition httpd.h:596
#define M_TRACE
Definition httpd.h:598
#define M_GET
Definition httpd.h:592
#define STANDARD20_MODULE_STUFF
#define ap_strchr(s, c)
Definition httpd.h:2351
int ap_cstr_casecmp(const char *s1, const char *s2)
Definition util.c:3542
char * ap_pbase64encode(apr_pool_t *p, char *string)
Definition util.c:2487
#define ap_strrchr_c(s, c)
Definition httpd.h:2357
#define ap_strchr_c(s, c)
Definition httpd.h:2353
#define PROXYREQ_NONE
Definition httpd.h:1133
char * ap_pregsub(apr_pool_t *p, const char *input, const char *source, apr_size_t nmatch, ap_regmatch_t pmatch[])
Definition util.c:457
#define AP_DEBUG_ASSERT(exp)
Definition httpd.h:2283
int ap_cstr_casecmpn(const char *s1, const char *s2, apr_size_t n)
Definition util.c:3559
#define PROXYREQ_PROXY
Definition httpd.h:1134
void ap_str_tolower(char *s)
Definition util.c:2410
int ap_parse_strict_length(apr_off_t *len, const char *str)
Definition util.c:2683
#define PROXYREQ_REVERSE
Definition httpd.h:1135
ap_regex_t * ap_pregcomp(apr_pool_t *p, const char *pattern, int cflags)
Definition util.c:262
apr_status_t ap_timeout_parameter_parse(const char *timeout_parameter, apr_interval_time_t *timeout, const char *default_time_unit)
Definition util.c:2622
char * ap_getword_conf(apr_pool_t *p, const char **line)
Definition util.c:833
#define NOT_IN_FILES
#define NOT_IN_HTACCESS
#define NOT_IN_DIRECTORY
#define NOT_IN_DIR_CONTEXT
const char * ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden)
Definition core.c:1301
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
const apr_array_header_t * list
Definition apr_cstr.h:105
#define apr_isdigit(c)
Definition apr_lib.h:209
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
const char * key
const char apr_int32_t flag
void const char apr_status_t(* cleanup)(void *))
int strcasecmp(const char *a, const char *b)
int strncasecmp(const char *a, const char *b, size_t n)
apr_vformatter_buff_t * c
Definition apr_lib.h:175
apr_vformatter_buff_t const char va_list ap
Definition apr_lib.h:176
apr_byte_t ttl
apr_sockaddr_t * addr
apr_uint16_t apr_port_t
#define APR_UNSPEC
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
@ APR_LOCK_DEFAULT
const char char ** end
const char * s
Definition apr_strings.h:95
#define APR_ARRAY_PUSH(ary, type)
Definition apr_tables.h:150
const apr_array_header_t * arr
Definition apr_tables.h:187
int nelts
Definition apr_tables.h:122
#define APR_ARRAY_IDX(ary, i, type)
Definition apr_tables.h:141
apr_int32_t apr_int32_t apr_int32_t err
apr_cmdtype_e cmd
int int status
#define APR_TIME_T_FMT
Definition apr_time.h:52
apr_int64_t apr_interval_time_t
Definition apr_time.h:55
#define apr_time_sec(time)
Definition apr_time.h:63
#define apr_time_from_sec(sec)
Definition apr_time.h:78
#define AP_TRACE_EXTENDED
Definition http_core.h:730
#define AP_TRACE_DISABLE
Definition http_core.h:728
apr_pool_t * p
Definition md_event.c:32
mod_core private header file
int ssl_proxy_enable(conn_rec *c)
Definition mod_nw_ssl.c:936
int ssl_engine_disable(conn_rec *c)
Definition mod_nw_ssl.c:943
static int proxy_needsdomain(request_rec *r, const char *url, const char *domain)
Definition mod_proxy.c:1175
static const char *const proxy_id
Definition mod_proxy.c:77
static const char * set_io_buffer_size(cmd_parms *parms, void *dummy, const char *arg)
Definition mod_proxy.c:2452
static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv)
Definition mod_proxy.c:1695
static const char * set_inherit(cmd_parms *parms, void *dummy, int flag)
Definition mod_proxy.c:2582
static int proxy_detect(request_rec *r)
Definition mod_proxy.c:791
static const char * add_proxy_http_headers(cmd_parms *parms, void *dconf, int flag)
Definition mod_proxy.c:2411
static int proxy_fixup(request_rec *r)
Definition mod_proxy.c:1159
static const command_rec proxy_cmds[]
Definition mod_proxy.c:2964
static const char * add_pass_noregex(cmd_parms *cmd, void *dummy, const char *arg)
Definition mod_proxy.c:2171
static const char * add_pass_regex(cmd_parms *cmd, void *dummy, const char *arg)
Definition mod_proxy.c:2177
static const char * set_status_opt(cmd_parms *parms, void *dummy, const char *arg)
Definition mod_proxy.c:2538
static const char * add_proxy_noregex(cmd_parms *cmd, void *dummy, const char *f1, const char *r1, const char *creds)
Definition mod_proxy.c:1926
static apr_OFN_set_worker_hc_param_t * set_worker_hc_param_f
Definition mod_proxy.c:44
static const char * set_proxy_exclude(cmd_parms *parms, void *dummy, const char *arg)
Definition mod_proxy.c:2249
static const char * set_proxy_error_override(cmd_parms *parms, void *dconf, const char *arg)
Definition mod_proxy.c:2366
static const char * set_preserve_host(cmd_parms *parms, void *dconf, int flag)
Definition mod_proxy.c:2419
static const char * set_bad_opt(cmd_parms *parms, void *dummy, const char *arg)
Definition mod_proxy.c:2517
static const char * set_balancer_param(proxy_server_conf *conf, apr_pool_t *p, proxy_balancer *balancer, const char *key, const char *val)
Definition mod_proxy.c:365
static int proxy_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
Definition mod_proxy.c:3327
static const char * forward_100_continue(cmd_parms *parms, void *dconf, int flag)
Definition mod_proxy.c:2428
static int proxy_handler(request_rec *r)
Definition mod_proxy.c:1213
static const char * set_ppinherit(cmd_parms *parms, void *dummy, int flag)
Definition mod_proxy.c:2592
static int alias_match(const char *uri, const char *alias_fakename)
Definition mod_proxy.c:532
static const char * cookie_path(cmd_parms *cmd, void *dconf, const char *f, const char *r, const char *interp)
Definition mod_proxy.c:2222
static const char * add_proxy(cmd_parms *cmd, void *dummy, const char *f1, const char *r1, const char *creds, int regex)
Definition mod_proxy.c:1859
static int int_order(const void *i1, const void *i2)
Definition mod_proxy.c:1802
static const char * cookie_domain(cmd_parms *cmd, void *dconf, const char *f, const char *r, const char *interp)
Definition mod_proxy.c:2235
static const char * set_persist(cmd_parms *parms, void *dummy, int flag)
Definition mod_proxy.c:2573
static const char * set_max_forwards(cmd_parms *parms, void *dummy, const char *arg)
Definition mod_proxy.c:2466
static const char * proxysection(cmd_parms *cmd, void *mconfig, const char *arg)
Definition mod_proxy.c:2816
static const char * set_proxy_param(cmd_parms *cmd, void *dummy, const char *arg)
Definition mod_proxy.c:2707
static const char * set_proxy_dirconn(cmd_parms *parms, void *dummy, const char *arg)
Definition mod_proxy.c:2286
static void * create_proxy_dir_config(apr_pool_t *p, char *dummy)
Definition mod_proxy.c:1777
static apr_OFN_ssl_engine_disable_t * proxy_ssl_disable
Definition mod_proxy.c:3041
static int alias_match_servlet(apr_pool_t *p, const char **urip, const char *alias)
Definition mod_proxy.c:588
static apr_OFN_ssl_engine_set_t * proxy_ssl_engine
Definition mod_proxy.c:3042
static const char * set_proxy_timeout(cmd_parms *parms, void *dummy, const char *arg)
Definition mod_proxy.c:2477
static void register_hooks(apr_pool_t *p)
Definition mod_proxy.c:3345
static int proxy_pre_translate_name(request_rec *r)
Definition mod_proxy.c:1049
static int proxy_walk(request_rec *r)
Definition mod_proxy.c:1059
static void * create_proxy_config(apr_pool_t *p, server_rec *s)
Definition mod_proxy.c:1555
apr_global_mutex_t * proxy_mutex
Definition mod_proxy.c:78
static const char * add_pass(cmd_parms *cmd, void *dummy, const char *arg, int is_regex)
Definition mod_proxy.c:1969
static int proxy_status_hook(request_rec *r, int flags)
Definition mod_proxy.c:3127
static const char * set_proxy_req(cmd_parms *parms, void *dummy, int flag)
Definition mod_proxy.c:2355
static void ap_add_per_proxy_conf(server_rec *s, ap_conf_vector_t *dir_config)
Definition mod_proxy.c:2807
static int proxy_trans(request_rec *r, int pre_trans)
Definition mod_proxy.c:979
static const char * add_proxy_regex(cmd_parms *cmd, void *dummy, const char *f1, const char *r1, const char *creds)
Definition mod_proxy.c:1932
static void child_init(apr_pool_t *p, server_rec *s)
Definition mod_proxy.c:3245
static apr_array_header_t * merge_balancers(apr_pool_t *p, apr_array_header_t *base, apr_array_header_t *overrides)
Definition mod_proxy.c:1602
static int proxy_map_location(request_rec *r)
Definition mod_proxy.c:1135
static const char * set_source_address(cmd_parms *parms, void *dummy, const char *arg)
Definition mod_proxy.c:1758
static apr_OFN_ssl_proxy_enable_t * proxy_ssl_enable
Definition mod_proxy.c:3040
static const char * add_member(cmd_parms *cmd, void *dummy, const char *arg)
Definition mod_proxy.c:2602
static const char * set_proxy_domain(cmd_parms *parms, void *dummy, const char *arg)
Definition mod_proxy.c:2342
static const char * set_bgrowth(cmd_parms *parms, void *dummy, const char *arg)
Definition mod_proxy.c:2558
static void * merge_proxy_dir_config(apr_pool_t *p, void *basev, void *addv)
Definition mod_proxy.c:1807
static const char * add_pass_reverse(cmd_parms *cmd, void *dconf, const char *f, const char *r, const char *i)
Definition mod_proxy.c:2183
static const char * set_via_opt(cmd_parms *parms, void *dummy, const char *arg)
Definition mod_proxy.c:2494
static int proxy_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_s)
Definition mod_proxy.c:3087
static int proxy_translate_name(request_rec *r)
Definition mod_proxy.c:1054
static const char * set_worker_param(apr_pool_t *p, server_rec *s, proxy_worker *worker, const char *key, const char *val)
Definition mod_proxy.c:96
static const char * set_recv_buffer_size(cmd_parms *parms, void *dummy, const char *arg)
Definition mod_proxy.c:2437
Proxy Extension Module for Apache.
static const char * set_worker_hc_param(apr_pool_t *p, server_rec *s, proxy_worker *worker, const char *key, const char *val, void *v)
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
sconf
Definition mod_so.c:349
SSL extension module for Apache.
Status Report Extension Module to Apache.
int ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p)
Definition proxy_util.c:675
int ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
Definition proxy_util.c:466
int ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p)
Definition proxy_util.c:802
const char * ap_proxy_interpolate(request_rec *r, const char *str)
int ap_proxy_canon_url(request_rec *r)
int ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p)
Definition proxy_util.c:736
Internal interfaces private to mod_proxy.
Apache scoreboard library.
static int ssl_engine_set(conn_rec *c, ap_conf_vector_t *per_dir_config, int proxy, int enable)
Definition ssl.c:99
char * name
apr_pool_t * pool
Definition apr_tables.h:81
char * val
Definition apr_tables.h:87
char * key
Definition apr_tables.h:83
char * scheme
Definition apr_uri.h:87
apr_port_t port
Definition apr_uri.h:109
char * hostname
Definition apr_uri.h:95
char * port_str
Definition apr_uri.h:97
Structure to store things which are per connection.
Definition httpd.h:1152
Definition mod_proxy.h:142
Definition mod_proxy.h:149
proxy_balancer * balancer
Definition mod_proxy.h:139
const char * real
Definition mod_proxy.h:135
unsigned int flags
Definition mod_proxy.h:138
const char * fake
Definition mod_proxy.h:136
const char * name
Definition mod_proxy.h:583
unsigned int forcerecovery
Definition mod_proxy.h:547
unsigned int max_attempts_set
Definition mod_proxy.h:542
unsigned int sticky_separator_set
Definition mod_proxy.h:553
unsigned int scolonsep
Definition mod_proxy.h:541
unsigned int forcerecovery_set
Definition mod_proxy.h:549
unsigned int nonce_set
Definition mod_proxy.h:552
unsigned int sticky_force
Definition mod_proxy.h:540
apr_interval_time_t timeout
Definition mod_proxy.h:535
unsigned int sticky_force_set
Definition mod_proxy.h:551
unsigned int scolonsep_set
Definition mod_proxy.h:550
unsigned int failontimeout_set
Definition mod_proxy.h:576
ap_conf_vector_t * section_config
Definition mod_proxy.h:579
proxy_balancer_shared * s
Definition mod_proxy.h:574
unsigned int lbmethod_set
Definition mod_proxy.h:578
unsigned int growth_set
Definition mod_proxy.h:577
apr_array_header_t * errstatuses
Definition mod_proxy.h:560
proxy_balancer_method * lbmethod
Definition mod_proxy.h:567
apr_array_header_t * workers
Definition mod_proxy.h:559
apr_array_header_t * cookie_domains
Definition mod_proxy.h:228
signed char interpolate_env
Definition mod_proxy.h:230
unsigned int add_forwarded_headers_set
Definition mod_proxy.h:247
apr_array_header_t * raliases
Definition mod_proxy.h:226
unsigned int error_override_set
Definition mod_proxy.h:244
unsigned int error_override
Definition mod_proxy.h:241
unsigned int alias_set
Definition mod_proxy.h:245
apr_array_header_t * refs
Definition mod_proxy.h:250
ap_regex_t * r
Definition mod_proxy.h:216
struct proxy_alias * alias
Definition mod_proxy.h:231
unsigned int forward_100_continue
Definition mod_proxy.h:252
unsigned int preserve_host_set
Definition mod_proxy.h:243
signed char p_is_fnmatch
Definition mod_proxy.h:229
unsigned int preserve_host
Definition mod_proxy.h:242
const char * p
Definition mod_proxy.h:215
apr_array_header_t * cookie_paths
Definition mod_proxy.h:227
unsigned int forward_100_continue_set
Definition mod_proxy.h:253
unsigned int add_forwarded_headers
Definition mod_proxy.h:246
apr_array_header_t * error_override_codes
Definition mod_proxy.h:255
unsigned int fnv
Definition mod_proxy.h:419
unsigned int def
Definition mod_proxy.h:418
const char * creds
Definition mod_proxy.h:124
const char * scheme
Definition mod_proxy.h:120
unsigned int req_set
Definition mod_proxy.h:195
unsigned int map_encoded_all
Definition mod_proxy.h:211
apr_array_header_t * workers
Definition mod_proxy.h:160
apr_array_header_t * aliases
Definition mod_proxy.h:157
apr_array_header_t * proxies
Definition mod_proxy.h:155
proxy_worker * forward
Definition mod_proxy.h:162
const char * domain
Definition mod_proxy.h:164
apr_pool_t * pool
Definition mod_proxy.h:166
enum proxy_server_conf::@34 proxy_status
apr_array_header_t * dirconn
Definition mod_proxy.h:159
unsigned int map_encoded_one
Definition mod_proxy.h:210
apr_array_header_t * balancers
Definition mod_proxy.h:161
proxy_worker * reverse
Definition mod_proxy.h:163
apr_array_header_t * noproxies
Definition mod_proxy.h:158
apr_interval_time_t ttl
Definition mod_proxy.h:450
unsigned int conn_timeout_set
Definition mod_proxy.h:472
unsigned int keepalive
Definition mod_proxy.h:465
unsigned int timeout_set
Definition mod_proxy.h:469
apr_size_t recv_buffer_size
Definition mod_proxy.h:457
apr_interval_time_t timeout
Definition mod_proxy.h:453
char hostname_ex[256]
Definition mod_proxy.h:488
apr_time_t error_time
Definition mod_proxy.h:449
apr_interval_time_t retry
Definition mod_proxy.h:452
unsigned int ping_timeout_set
Definition mod_proxy.h:471
unsigned int disablereuse_set
Definition mod_proxy.h:476
enum proxy_worker_shared::@35 flush_packets
apr_size_t response_field_size
Definition mod_proxy.h:489
unsigned int status
Definition mod_proxy.h:442
unsigned int io_buffer_size_set
Definition mod_proxy.h:474
unsigned int keepalive_set
Definition mod_proxy.h:475
apr_size_t io_buffer_size
Definition mod_proxy.h:458
unsigned int address_ttl_set
Definition mod_proxy.h:493
apr_interval_time_t conn_timeout
Definition mod_proxy.h:456
proxy_hashes hash
Definition mod_proxy.h:441
unsigned int response_field_size_set
Definition mod_proxy.h:490
unsigned int retry_set
Definition mod_proxy.h:468
apr_int32_t address_ttl
Definition mod_proxy.h:494
apr_interval_time_t ping_timeout
Definition mod_proxy.h:455
unsigned int recv_buffer_size_set
Definition mod_proxy.h:473
unsigned int is_address_reusable
Definition mod_proxy.h:467
unsigned int disablereuse
Definition mod_proxy.h:466
apr_interval_time_t acquire
Definition mod_proxy.h:454
unsigned int acquire_set
Definition mod_proxy.h:470
ap_conf_vector_t * section_config
Definition mod_proxy.h:511
proxy_worker_shared * s
Definition mod_proxy.h:505
proxy_hashes hash
Definition mod_proxy.h:502
A structure that represents the current request.
Definition httpd.h:845
int status
Definition httpd.h:891
char * uri
Definition httpd.h:1016
const char * handler
Definition httpd.h:994
apr_table_t * notes
Definition httpd.h:985
const char * hostname
Definition httpd.h:883
int method_number
Definition httpd.h:898
apr_pool_t * pool
Definition httpd.h:847
char * filename
Definition httpd.h:1018
apr_off_t remaining
Definition httpd.h:959
apr_uri_t parsed_uri
Definition httpd.h:1092
char * unparsed_uri
Definition httpd.h:1014
int proxyreq
Definition httpd.h:873
apr_table_t * headers_in
Definition httpd.h:976
int read_chunked
Definition httpd.h:949
apr_off_t read_length
Definition httpd.h:961
apr_table_t * subprocess_env
Definition httpd.h:983
server_rec * server
Definition httpd.h:851
struct ap_conf_vector_t * per_dir_config
Definition httpd.h:1047
apr_table_t * headers_out
Definition httpd.h:978
A structure to store information for each virtual server.
Definition httpd.h:1322
apr_interval_time_t timeout
Definition httpd.h:1372
struct ap_conf_vector_t * module_config
Definition httpd.h:1341
#define var
#define str
#define regex
int ap_matches_request_vhost(request_rec *r, const char *host, apr_port_t port)
Definition vhost.c:953
IN ULONG IN INT timeout