upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / modules / proxy / proxy_http.c
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 /* HTTP routines for Apache proxy */
18
19 #include "mod_proxy.h"
20
21 module AP_MODULE_DECLARE_DATA proxy_http_module;
22
23 int ap_proxy_http_canon(request_rec *r, char *url);
24 int ap_proxy_http_handler(request_rec *r, proxy_server_conf *conf,
25                           char *url, const char *proxyname, 
26                           apr_port_t proxyport);
27
28 typedef struct {
29     const char     *name;
30     apr_port_t      port;
31     apr_sockaddr_t *addr;
32     apr_socket_t   *sock;
33     int             close;
34 } proxy_http_conn_t;
35
36 static apr_status_t ap_proxy_http_cleanup(request_rec *r,
37                                           proxy_http_conn_t *p_conn,
38                                           proxy_conn_rec *backend);
39
40 /*
41  * Canonicalise http-like URLs.
42  *  scheme is the scheme for the URL
43  *  url    is the URL starting with the first '/'
44  *  def_port is the default port for this scheme.
45  */
46 int ap_proxy_http_canon(request_rec *r, char *url)
47 {
48     char *host, *path, *search, sport[7];
49     const char *err;
50     const char *scheme;
51     apr_port_t port, def_port;
52
53     /* ap_port_of_scheme() */
54     if (strncasecmp(url, "http:", 5) == 0) {
55         url += 5;
56         scheme = "http";
57     }
58     else if (strncasecmp(url, "https:", 6) == 0) {
59         url += 6;
60         scheme = "https";
61     }
62     else {
63         return DECLINED;
64     }
65     def_port = apr_uri_port_of_scheme(scheme);
66
67     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
68              "proxy: HTTP: canonicalising URL %s", url);
69
70     /* do syntatic check.
71      * We break the URL into host, port, path, search
72      */
73     port = def_port;
74     err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
75     if (err) {
76         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
77                       "error parsing URL %s: %s",
78                       url, err);
79         return HTTP_BAD_REQUEST;
80     }
81
82     /* now parse path/search args, according to rfc1738 */
83     /* N.B. if this isn't a true proxy request, then the URL _path_
84      * has already been decoded.  True proxy requests have r->uri
85      * == r->unparsed_uri, and no others have that property.
86      */
87     if (r->uri == r->unparsed_uri) {
88         search = strchr(url, '?');
89         if (search != NULL)
90             *(search++) = '\0';
91     }
92     else
93         search = r->args;
94
95     /* process path */
96     path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, r->proxyreq);
97     if (path == NULL)
98         return HTTP_BAD_REQUEST;
99
100     if (port != def_port)
101         apr_snprintf(sport, sizeof(sport), ":%d", port);
102     else
103         sport[0] = '\0';
104
105     if (ap_strchr_c(host, ':')) { /* if literal IPv6 address */
106         host = apr_pstrcat(r->pool, "[", host, "]", NULL);
107     }
108     r->filename = apr_pstrcat(r->pool, "proxy:", scheme, "://", host, sport, 
109             "/", path, (search) ? "?" : "", (search) ? search : "", NULL);
110     return OK;
111 }
112  
113 static const char *ap_proxy_location_reverse_map(request_rec *r, proxy_server_conf *conf, const char *url)
114 {
115     struct proxy_alias *ent;
116     int i, l1, l2;
117     char *u;
118
119     /* XXX FIXME: Make sure this handled the ambiguous case of the :80
120      * after the hostname */
121
122     l1 = strlen(url);
123     ent = (struct proxy_alias *)conf->raliases->elts;
124     for (i = 0; i < conf->raliases->nelts; i++) {
125         l2 = strlen(ent[i].real);
126         if (l1 >= l2 && strncmp(ent[i].real, url, l2) == 0) {
127             u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
128             return ap_construct_url(r->pool, u, r);
129         }
130     }
131     return url;
132 }
133
134 /* Clear all connection-based headers from the incoming headers table */
135 static void ap_proxy_clear_connection(apr_pool_t *p, apr_table_t *headers)
136 {
137     const char *name;
138     char *next = apr_pstrdup(p, apr_table_get(headers, "Connection"));
139
140     apr_table_unset(headers, "Proxy-Connection");
141     if (!next)
142         return;
143
144     while (*next) {
145         name = next;
146         while (*next && !apr_isspace(*next) && (*next != ',')) {
147             ++next;
148         }
149         while (*next && (apr_isspace(*next) || (*next == ','))) {
150             *next = '\0';
151             ++next;
152         }
153         apr_table_unset(headers, name);
154     }
155     apr_table_unset(headers, "Connection");
156 }
157
158 static
159 apr_status_t ap_proxy_http_determine_connection(apr_pool_t *p, request_rec *r,
160                                                 proxy_http_conn_t *p_conn,
161                                                 conn_rec *c,
162                                                 proxy_server_conf *conf,
163                                                 apr_uri_t *uri,
164                                                 char **url,
165                                                 const char *proxyname,
166                                                 apr_port_t proxyport,
167                                                 char *server_portstr,
168                                                 int server_portstr_size) {
169     int server_port;
170     apr_status_t err;
171     apr_sockaddr_t *uri_addr;
172     /*
173      * Break up the URL to determine the host to connect to
174      */
175
176     /* we break the URL into host, port, uri */
177     if (APR_SUCCESS != apr_uri_parse(p, *url, uri)) {
178         return ap_proxyerror(r, HTTP_BAD_REQUEST,
179                              apr_pstrcat(p,"URI cannot be parsed: ", *url,
180                                          NULL));
181     }
182     if (!uri->port) {
183         uri->port = apr_uri_port_of_scheme(uri->scheme);
184     }
185
186     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
187                  "proxy: HTTP connecting %s to %s:%d", *url, uri->hostname,
188                  uri->port);
189
190     /* do a DNS lookup for the destination host */
191     /* see memory note above */
192     err = apr_sockaddr_info_get(&uri_addr, apr_pstrdup(c->pool, uri->hostname),
193                                 APR_UNSPEC, uri->port, 0, c->pool);
194
195     /* allocate these out of the connection pool - the check on
196      * r->connection->id makes sure that this string does not get accessed
197      * past the connection lifetime */
198     /* are we connecting directly, or via a proxy? */
199     if (proxyname) {
200         p_conn->name = apr_pstrdup(c->pool, proxyname);
201         p_conn->port = proxyport;
202         /* see memory note above */
203         err = apr_sockaddr_info_get(&p_conn->addr, p_conn->name, APR_UNSPEC,
204                                     p_conn->port, 0, c->pool);
205     } else {
206         p_conn->name = apr_pstrdup(c->pool, uri->hostname);
207         p_conn->port = uri->port;
208         p_conn->addr = uri_addr;
209         *url = apr_pstrcat(p, uri->path, uri->query ? "?" : "",
210                            uri->query ? uri->query : "",
211                            uri->fragment ? "#" : "",
212                            uri->fragment ? uri->fragment : "", NULL);
213     }
214
215     if (err != APR_SUCCESS) {
216         return ap_proxyerror(r, HTTP_BAD_GATEWAY,
217                              apr_pstrcat(p, "DNS lookup failure for: ",
218                                          p_conn->name, NULL));
219     }
220
221     /* Get the server port for the Via headers */
222     {
223         server_port = ap_get_server_port(r);
224         if (ap_is_default_port(server_port, r)) {
225             strcpy(server_portstr,"");
226         } else {
227             apr_snprintf(server_portstr, server_portstr_size, ":%d",
228                          server_port);
229         }
230     }
231
232     /* check if ProxyBlock directive on this host */
233     if (OK != ap_proxy_checkproxyblock(r, conf, uri_addr)) {
234         return ap_proxyerror(r, HTTP_FORBIDDEN,
235                              "Connect to remote machine blocked");
236     }
237     return OK;
238 }
239
240 static
241 apr_status_t ap_proxy_http_create_connection(apr_pool_t *p, request_rec *r,
242                                              proxy_http_conn_t *p_conn,
243                                              conn_rec *c, conn_rec **origin,
244                                              proxy_conn_rec *backend,
245                                              proxy_server_conf *conf,
246                                              const char *proxyname) {
247     int failed=0, new=0;
248     apr_socket_t *client_socket = NULL;
249
250     /* We have determined who to connect to. Now make the connection, supporting
251      * a KeepAlive connection.
252      */
253
254     /* get all the possible IP addresses for the destname and loop through them
255      * until we get a successful connection
256      */
257
258     /* if a keepalive socket is already open, check whether it must stay
259      * open, or whether it should be closed and a new socket created.
260      */
261     /* see memory note above */
262     if (backend->connection) {
263         client_socket = ap_get_module_config(backend->connection->conn_config, &core_module);
264         if ((backend->connection->id == c->id) &&
265             (backend->port == p_conn->port) &&
266             (backend->hostname) &&
267             (!apr_strnatcasecmp(backend->hostname, p_conn->name))) {
268             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
269                          "proxy: keepalive address match (keep original socket)");
270         } else {
271             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
272                          "proxy: keepalive address mismatch / connection has"
273                          " changed (close old socket (%s/%s, %d/%d))", 
274                          p_conn->name, backend->hostname, p_conn->port,
275                          backend->port);
276             apr_socket_close(client_socket);
277             backend->connection = NULL;
278         }
279     }
280
281     /* get a socket - either a keepalive one, or a new one */
282     new = 1;
283     if ((backend->connection) && (backend->connection->id == c->id)) {
284         apr_size_t buffer_len = 1;
285         char test_buffer[1]; 
286         apr_status_t socket_status;
287         apr_interval_time_t current_timeout;
288
289         /* use previous keepalive socket */
290         *origin = backend->connection;
291         p_conn->sock = client_socket;
292         new = 0;
293
294         /* save timeout */
295         apr_socket_timeout_get(p_conn->sock, &current_timeout);
296         /* set no timeout */
297         apr_socket_timeout_set(p_conn->sock, 0);
298         socket_status = apr_recv(p_conn->sock, test_buffer, &buffer_len);
299         /* put back old timeout */
300         apr_socket_timeout_set(p_conn->sock, current_timeout);
301         if ( APR_STATUS_IS_EOF(socket_status) ) {
302             ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL,
303                          "proxy: previous connection is closed, creating a new connection.");
304             new = 1;
305         }
306     }
307     if (new) {
308         int rc;
309
310         /* create a new socket */
311         backend->connection = NULL;
312
313         /*
314          * At this point we have a list of one or more IP addresses of
315          * the machine to connect to. If configured, reorder this
316          * list so that the "best candidate" is first try. "best
317          * candidate" could mean the least loaded server, the fastest
318          * responding server, whatever.
319          *
320          * For now we do nothing, ie we get DNS round robin.
321          * XXX FIXME
322          */
323         failed = ap_proxy_connect_to_backend(&p_conn->sock, "HTTP",
324                                              p_conn->addr, p_conn->name,
325                                              conf, r->server, c->pool);
326
327         /* handle a permanent error on the connect */
328         if (failed) {
329             if (proxyname) {
330                 return DECLINED;
331             } else {
332                 return HTTP_BAD_GATEWAY;
333             }
334         }
335
336         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
337                      "proxy: socket is connected");
338
339         /* the socket is now open, create a new backend server connection */
340         *origin = ap_run_create_connection(c->pool, r->server, p_conn->sock,
341                                            r->connection->id,
342                                            r->connection->sbh, c->bucket_alloc);
343         if (!*origin) {
344         /* the peer reset the connection already; ap_run_create_connection() 
345          * closed the socket
346          */
347             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
348                          r->server, "proxy: an error occurred creating a "
349                          "new connection to %pI (%s)", p_conn->addr,
350                          p_conn->name);
351             apr_socket_close(p_conn->sock);
352             return HTTP_INTERNAL_SERVER_ERROR;
353         }
354         backend->connection = *origin;
355         backend->hostname = apr_pstrdup(c->pool, p_conn->name);
356         backend->port = p_conn->port;
357
358         if (backend->is_ssl) {
359             if (!ap_proxy_ssl_enable(backend->connection)) {
360                 ap_log_error(APLOG_MARK, APLOG_ERR, 0,
361                              r->server, "proxy: failed to enable ssl support "
362                              "for %pI (%s)", p_conn->addr, p_conn->name);
363                 return HTTP_INTERNAL_SERVER_ERROR;
364             }
365         }
366         else {
367             ap_proxy_ssl_disable(backend->connection);
368         }
369
370         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
371                      "proxy: connection complete to %pI (%s)",
372                      p_conn->addr, p_conn->name);
373
374         /* set up the connection filters */
375         rc = ap_run_pre_connection(*origin, p_conn->sock);
376         if (rc != OK && rc != DONE) {
377             (*origin)->aborted = 1;
378             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
379                          "proxy: HTTP: pre_connection setup failed (%d)",
380                          rc);
381             return rc;
382         }
383     }
384     return OK;
385 }
386
387 static void add_te_chunked(apr_pool_t *p,
388                            apr_bucket_alloc_t *bucket_alloc,
389                            apr_bucket_brigade *header_brigade)
390 {
391     apr_bucket *e;
392     char *buf;
393     const char te_hdr[] = "Transfer-Encoding: chunked" CRLF;
394
395     buf = apr_pmemdup(p, te_hdr, sizeof(te_hdr)-1);
396     ap_xlate_proto_to_ascii(buf, sizeof(te_hdr)-1);
397
398     e = apr_bucket_pool_create(buf, sizeof(te_hdr)-1, p, bucket_alloc);
399     APR_BRIGADE_INSERT_TAIL(header_brigade, e);
400 }
401
402 static void add_cl(apr_pool_t *p,
403                    apr_bucket_alloc_t *bucket_alloc,
404                    apr_bucket_brigade *header_brigade,
405                    const char *cl_val)
406 {
407     apr_bucket *e;
408     char *buf;
409
410     buf = apr_pstrcat(p, "Content-Length: ",
411                       cl_val,
412                       CRLF,
413                       NULL);
414     ap_xlate_proto_to_ascii(buf, strlen(buf));
415     e = apr_bucket_pool_create(buf, strlen(buf), p, bucket_alloc);
416     APR_BRIGADE_INSERT_TAIL(header_brigade, e);
417 }
418
419 #define ASCII_CRLF  "\015\012"
420 #define ASCII_ZERO  "\060"
421
422 static void terminate_headers(apr_bucket_alloc_t *bucket_alloc,
423                               apr_bucket_brigade *header_brigade)
424 {
425     apr_bucket *e;
426
427     /* add empty line at the end of the headers */
428     e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
429     APR_BRIGADE_INSERT_TAIL(header_brigade, e);
430 }
431
432 static apr_status_t pass_brigade(apr_bucket_alloc_t *bucket_alloc,
433                                  request_rec *r, proxy_http_conn_t *p_conn,
434                                  conn_rec *origin, apr_bucket_brigade *bb,
435                                  int flush)
436 {
437     apr_status_t status;
438
439     if (flush) {
440         apr_bucket *e = apr_bucket_flush_create(bucket_alloc);
441         APR_BRIGADE_INSERT_TAIL(bb, e);
442     }
443     status = ap_pass_brigade(origin->output_filters, bb);
444     if (status != APR_SUCCESS) {
445         ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
446                      "proxy: pass request body failed to %pI (%s)",
447                      p_conn->addr, p_conn->name);
448         return status;
449     }
450     apr_brigade_cleanup(bb);
451     return APR_SUCCESS;
452 }
453
454 static apr_status_t stream_reqbody_chunked(apr_pool_t *p,
455                                            request_rec *r,
456                                            proxy_http_conn_t *p_conn,
457                                            conn_rec *origin,
458                                            apr_bucket_brigade *header_brigade,
459                                            apr_bucket_brigade *input_brigade)
460 {
461     int seen_eos = 0;
462     apr_size_t hdr_len;
463     apr_off_t bytes;
464     apr_status_t status;
465     apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
466     apr_bucket_brigade *bb;
467     apr_bucket *e;
468
469     add_te_chunked(p, bucket_alloc, header_brigade);
470     terminate_headers(bucket_alloc, header_brigade);
471
472     while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
473     {
474         char chunk_hdr[20];  /* must be here due to transient bucket. */
475
476         /* If this brigade contains EOS, either stop or remove it. */
477         if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
478             seen_eos = 1;
479
480             /* We can't pass this EOS to the output_filters. */
481             e = APR_BRIGADE_LAST(input_brigade);
482             apr_bucket_delete(e);
483         }
484
485         apr_brigade_length(input_brigade, 1, &bytes);
486
487         hdr_len = apr_snprintf(chunk_hdr, sizeof(chunk_hdr),
488                                "%" APR_UINT64_T_HEX_FMT CRLF, 
489                                (apr_uint64_t)bytes);
490         
491         ap_xlate_proto_to_ascii(chunk_hdr, hdr_len);
492         e = apr_bucket_transient_create(chunk_hdr, hdr_len,
493                                         bucket_alloc);
494         APR_BRIGADE_INSERT_HEAD(input_brigade, e);
495         
496         /*
497          * Append the end-of-chunk CRLF
498          */
499         e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
500         APR_BRIGADE_INSERT_TAIL(input_brigade, e);
501         
502         if (header_brigade) {
503             /* we never sent the header brigade, so go ahead and
504              * take care of that now
505              */
506             bb = header_brigade;
507
508             /*
509              * Save input_brigade in bb brigade. (At least) in the SSL case
510              * input_brigade contains transient buckets whose data would get
511              * overwritten during the next call of ap_get_brigade in the loop.
512              * ap_save_brigade ensures these buckets to be set aside.
513              * Calling ap_save_brigade with NULL as filter is OK, because
514              * bb brigade already has been created and does not need to get
515              * created by ap_save_brigade.
516              */
517             status = ap_save_brigade(NULL, &bb, &input_brigade, p);
518             if (status != APR_SUCCESS) {
519                 return status;
520             }
521
522             header_brigade = NULL;
523         }
524         else {
525             bb = input_brigade;
526         }
527         
528         /* The request is flushed below this loop with chunk EOS header */
529         status = pass_brigade(bucket_alloc, r, p_conn, origin, bb, 0);
530         if (status != APR_SUCCESS) {
531             return status;
532         }
533
534         if (seen_eos) {
535             break;
536         }
537
538         status = ap_get_brigade(r->input_filters, input_brigade,
539                                 AP_MODE_READBYTES, APR_BLOCK_READ,
540                                 HUGE_STRING_LEN);
541
542         if (status != APR_SUCCESS) {
543             return status;
544         }
545     }
546
547     if (header_brigade) {
548         /* we never sent the header brigade because there was no request body;
549          * send it now
550          */
551         bb = header_brigade;
552     }
553     else {
554         if (!APR_BRIGADE_EMPTY(input_brigade)) {
555             /* input brigade still has an EOS which we can't pass to the output_filters. */
556             e = APR_BRIGADE_LAST(input_brigade);
557             AP_DEBUG_ASSERT(APR_BUCKET_IS_EOS(e));
558             apr_bucket_delete(e);
559         }
560         bb = input_brigade;
561     }
562
563     e = apr_bucket_immortal_create(ASCII_ZERO ASCII_CRLF
564                                    /* <trailers> */
565                                    ASCII_CRLF,
566                                    5, bucket_alloc);
567     APR_BRIGADE_INSERT_TAIL(bb, e);
568
569     /* Now we have headers-only, or the chunk EOS mark; flush it */
570     status = pass_brigade(bucket_alloc, r, p_conn, origin, bb, 1);
571     return status;
572 }
573
574 static apr_status_t stream_reqbody_cl(apr_pool_t *p,
575                                       request_rec *r,
576                                       proxy_http_conn_t *p_conn,
577                                       conn_rec *origin,
578                                       apr_bucket_brigade *header_brigade,
579                                       apr_bucket_brigade *input_brigade,
580                                       const char *old_cl_val)
581 {
582     int seen_eos = 0;
583     apr_status_t status = APR_SUCCESS;
584     apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
585     apr_bucket_brigade *bb;
586     apr_bucket *e;
587     apr_off_t cl_val = 0;
588     apr_off_t bytes;
589     apr_off_t bytes_streamed = 0;
590
591     if (old_cl_val) {
592         add_cl(p, bucket_alloc, header_brigade, old_cl_val);
593         cl_val = atol(old_cl_val);
594     }
595     terminate_headers(bucket_alloc, header_brigade);
596
597     while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
598     {
599         apr_brigade_length(input_brigade, 1, &bytes);
600         bytes_streamed += bytes;
601
602         /* If this brigade contains EOS, either stop or remove it. */
603         if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
604             seen_eos = 1;
605
606             /* We can't pass this EOS to the output_filters. */
607             e = APR_BRIGADE_LAST(input_brigade);
608             apr_bucket_delete(e);
609         }
610
611         /* C-L < bytes streamed?!?
612          * We will error out after the body is completely
613          * consumed, but we can't stream more bytes at the
614          * back end since they would in part be interpreted
615          * as another request!  If nothing is sent, then
616          * just send nothing.
617          *
618          * Prevents HTTP Response Splitting.
619          */
620         if (bytes_streamed > cl_val)
621              continue;
622
623         if (header_brigade) {
624             /* we never sent the header brigade, so go ahead and
625              * take care of that now
626              */
627             bb = header_brigade;
628
629             /*
630              * Save input_brigade in bb brigade. (At least) in the SSL case
631              * input_brigade contains transient buckets whose data would get
632              * overwritten during the next call of ap_get_brigade in the loop.
633              * ap_save_brigade ensures these buckets to be set aside.
634              * Calling ap_save_brigade with NULL as filter is OK, because
635              * bb brigade already has been created and does not need to get
636              * created by ap_save_brigade.
637              */
638             status = ap_save_brigade(NULL, &bb, &input_brigade, p);
639             if (status != APR_SUCCESS) {
640                 return status;
641             }
642
643             header_brigade = NULL;
644         }
645         else {
646             bb = input_brigade;
647         }
648         
649         /* Once we hit EOS, we are ready to flush. */
650         status = pass_brigade(bucket_alloc, r, p_conn, origin, bb, seen_eos);
651         if (status != APR_SUCCESS) {
652             return status;
653         }
654
655         if (seen_eos) {
656             break;
657         }
658
659         status = ap_get_brigade(r->input_filters, input_brigade,
660                                 AP_MODE_READBYTES, APR_BLOCK_READ,
661                                 HUGE_STRING_LEN);
662
663         if (status != APR_SUCCESS) {
664             return status;
665         }
666     }
667     
668     if (bytes_streamed != cl_val) {
669         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
670                      "proxy: client %s given Content-Length did not match"
671                      " number of body bytes read", r->connection->remote_ip);
672         return APR_EOF;
673     }
674
675     if (header_brigade) {
676         /* we never sent the header brigade since there was no request
677          * body; send it now with the flush flag
678          */
679         bb = header_brigade;
680         status = pass_brigade(bucket_alloc, r, p_conn, origin, bb, 1);
681     }
682     return status;
683 }
684
685 #define MAX_MEM_SPOOL 16384
686
687 static apr_status_t spool_reqbody_cl(apr_pool_t *p,
688                                      request_rec *r,
689                                      proxy_http_conn_t *p_conn,
690                                      conn_rec *origin,
691                                      apr_bucket_brigade *header_brigade,
692                                      apr_bucket_brigade *input_brigade,
693                                      int force_cl)
694 {
695     int seen_eos = 0;
696     apr_status_t status;
697     apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
698     apr_bucket_brigade *body_brigade;
699     apr_bucket *e;
700     apr_off_t bytes, bytes_spooled = 0, fsize = 0;
701     apr_file_t *tmpfile = NULL;
702
703     body_brigade = apr_brigade_create(p, bucket_alloc);
704
705     while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
706     {
707         /* If this brigade contains EOS, either stop or remove it. */
708         if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
709             seen_eos = 1;
710
711             /* We can't pass this EOS to the output_filters. */
712             e = APR_BRIGADE_LAST(input_brigade);
713             apr_bucket_delete(e);
714         }
715
716         apr_brigade_length(input_brigade, 1, &bytes);
717
718         if (bytes_spooled + bytes > MAX_MEM_SPOOL) {
719             /* can't spool any more in memory; write latest brigade to disk */
720             if (tmpfile == NULL) {
721                 const char *temp_dir;
722                 char *template;
723
724                 status = apr_temp_dir_get(&temp_dir, p);
725                 if (status != APR_SUCCESS) {
726                     ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
727                                  "proxy: search for temporary directory failed");
728                     return status;
729                 }
730                 apr_filepath_merge(&template, temp_dir,
731                                    "modproxy.tmp.XXXXXX",
732                                    APR_FILEPATH_NATIVE, p);
733                 status = apr_file_mktemp(&tmpfile, template, 0, p);
734                 if (status != APR_SUCCESS) {
735                     ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
736                                  "proxy: creation of temporary file in directory %s failed",
737                                  temp_dir);
738                     return status;
739                 }
740             }
741             for (e = APR_BRIGADE_FIRST(input_brigade);
742                  e != APR_BRIGADE_SENTINEL(input_brigade);
743                  e = APR_BUCKET_NEXT(e)) {
744                 const char *data;
745                 apr_size_t bytes_read, bytes_written;
746
747                 apr_bucket_read(e, &data, &bytes_read, APR_BLOCK_READ);
748                 status = apr_file_write_full(tmpfile, data, bytes_read, &bytes_written);
749                 if (status != APR_SUCCESS) {
750                     const char *tmpfile_name;
751
752                     if (apr_file_name_get(&tmpfile_name, tmpfile) != APR_SUCCESS) {
753                         tmpfile_name = "(unknown)";
754                     }
755                     ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
756                                  "proxy: write to temporary file %s failed",
757                                  tmpfile_name);
758                     return status;
759                 }
760                 AP_DEBUG_ASSERT(bytes_read == bytes_written);
761                 fsize += bytes_written;
762             }
763             apr_brigade_cleanup(input_brigade);
764         }
765         else {
766
767             /*
768              * Save input_brigade in body_brigade. (At least) in the SSL case
769              * input_brigade contains transient buckets whose data would get
770              * overwritten during the next call of ap_get_brigade in the loop.
771              * ap_save_brigade ensures these buckets to be set aside.
772              * Calling ap_save_brigade with NULL as filter is OK, because
773              * body_brigade already has been created and does not need to get
774              * created by ap_save_brigade.
775              */
776             status = ap_save_brigade(NULL, &body_brigade, &input_brigade, p);
777             if (status != APR_SUCCESS) {
778                 return status;
779             }
780
781         }
782         
783         bytes_spooled += bytes;
784
785         if (seen_eos) {
786             break;
787         }
788
789         status = ap_get_brigade(r->input_filters, input_brigade,
790                                 AP_MODE_READBYTES, APR_BLOCK_READ,
791                                 HUGE_STRING_LEN);
792
793         if (status != APR_SUCCESS) {
794             return status;
795         }
796     }
797
798     if (bytes_spooled || force_cl) {
799         add_cl(p, bucket_alloc, header_brigade, apr_off_t_toa(p, bytes_spooled));
800     }
801     terminate_headers(bucket_alloc, header_brigade);
802     APR_BRIGADE_CONCAT(header_brigade, body_brigade);
803     if (tmpfile) {
804         /* For platforms where the size of the file may be larger than
805          * that which can be stored in a single bucket (where the
806          * length field is an apr_size_t), split it into several
807          * buckets: */
808         if (sizeof(apr_off_t) > sizeof(apr_size_t)
809             && fsize > AP_MAX_SENDFILE) {
810             e = apr_bucket_file_create(tmpfile, 0, AP_MAX_SENDFILE, p,
811                                        bucket_alloc);
812             while (fsize > AP_MAX_SENDFILE) {
813                 apr_bucket *ce;
814                 apr_bucket_copy(e, &ce);
815                 APR_BRIGADE_INSERT_TAIL(header_brigade, ce);
816                 e->start += AP_MAX_SENDFILE;
817                 fsize -= AP_MAX_SENDFILE;
818             }
819             e->length = (apr_size_t)fsize; /* Resize just the last bucket */
820         }
821         else {
822             e = apr_bucket_file_create(tmpfile, 0, (apr_size_t)fsize, p,
823                                        bucket_alloc);
824         }
825         APR_BRIGADE_INSERT_TAIL(header_brigade, e);
826     }
827     /* This is all a single brigade, pass with flush flagged */
828     status = pass_brigade(bucket_alloc, r, p_conn, origin, header_brigade, 1);
829     return status;
830 }
831
832 static
833 apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r,
834                                    proxy_http_conn_t *p_conn, conn_rec *origin, 
835                                    proxy_server_conf *conf,
836                                    apr_uri_t *uri,
837                                    char *url, 
838                                    apr_bucket_brigade *header_brigade,
839                                    char *server_portstr) 
840 {
841     conn_rec *c = r->connection;
842     apr_bucket_alloc_t *bucket_alloc = c->bucket_alloc;
843     apr_bucket_brigade *input_brigade;
844     apr_bucket_brigade *temp_brigade;
845     apr_bucket *e;
846     char *buf;
847     const apr_array_header_t *headers_in_array;
848     const apr_table_entry_t *headers_in;
849     int counter;
850     apr_status_t status;
851     enum rb_methods {RB_INIT, RB_STREAM_CL, RB_STREAM_CHUNKED, RB_SPOOL_CL};
852     enum rb_methods rb_method = RB_INIT;
853     const char *old_cl_val = NULL;
854     const char *old_te_val = NULL;
855     apr_off_t bytes_read = 0;
856     apr_off_t bytes;
857     int force10;
858
859     /*
860      * Send the HTTP/1.1 request to the remote server
861      */
862
863     /* strip connection listed hop-by-hop headers from the request */
864     /* even though in theory a connection: close coming from the client
865      * should not affect the connection to the server, it's unlikely
866      * that subsequent client requests will hit this thread/process, 
867      * so we cancel server keepalive if the client does.
868      */
869     if (ap_proxy_liststr(apr_table_get(r->headers_in,
870                          "Connection"), "close")) {
871         p_conn->close++;
872         /* XXX: we are abusing r->headers_in rather than a copy,
873          * give the core output handler a clue the client would
874          * rather just close.
875          */
876         c->keepalive = AP_CONN_CLOSE;
877     }
878     ap_proxy_clear_connection(p, r->headers_in);
879
880     if (apr_table_get(r->subprocess_env, "force-proxy-request-1.0")) {
881         buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.0" CRLF, NULL);
882         force10 = 1;
883         p_conn->close++;
884     } else {
885         buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.1" CRLF, NULL);
886         force10 = 0;
887     }
888     if (apr_table_get(r->subprocess_env, "proxy-nokeepalive")) {
889         origin->keepalive = AP_CONN_CLOSE;
890         p_conn->close++;
891     }
892     ap_xlate_proto_to_ascii(buf, strlen(buf));
893     e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);
894     APR_BRIGADE_INSERT_TAIL(header_brigade, e);
895     if (conf->preserve_host == 0) {
896         if (uri->port_str && uri->port != DEFAULT_HTTP_PORT) {
897             buf = apr_pstrcat(p, "Host: ", uri->hostname, ":", uri->port_str,
898                               CRLF, NULL);
899         } else {
900             buf = apr_pstrcat(p, "Host: ", uri->hostname, CRLF, NULL);
901         }
902     } 
903     else {
904         /* don't want to use r->hostname, as the incoming header might have a 
905          * port attached 
906          */
907         const char* hostname = apr_table_get(r->headers_in,"Host");        
908         if (!hostname) {
909             hostname =  r->server->server_hostname;
910             ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
911                           "proxy: no HTTP 0.9 request (with no host line) "
912                           "on incoming request and preserve host set "
913                           "forcing hostname to be %s for uri %s", 
914                           hostname, 
915                           r->uri );
916         }
917         buf = apr_pstrcat(p, "Host: ", hostname, CRLF, NULL);
918     }
919     ap_xlate_proto_to_ascii(buf, strlen(buf));
920     e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);        
921     APR_BRIGADE_INSERT_TAIL(header_brigade, e);
922
923     /* handle Via */
924     if (conf->viaopt == via_block) {
925         /* Block all outgoing Via: headers */
926         apr_table_unset(r->headers_in, "Via");
927     } else if (conf->viaopt != via_off) {
928         const char *server_name = ap_get_server_name(r);
929         /* If USE_CANONICAL_NAME_OFF was configured for the proxy virtual host,
930          * then the server name returned by ap_get_server_name() is the
931          * origin server name (which does make too much sense with Via: headers)
932          * so we use the proxy vhost's name instead.
933          */
934         if (server_name == r->hostname)
935             server_name = r->server->server_hostname;
936         /* Create a "Via:" request header entry and merge it */
937         /* Generate outgoing Via: header with/without server comment: */
938         apr_table_mergen(r->headers_in, "Via",
939                          (conf->viaopt == via_full)
940                          ? apr_psprintf(p, "%d.%d %s%s (%s)",
941                                         HTTP_VERSION_MAJOR(r->proto_num),
942                                         HTTP_VERSION_MINOR(r->proto_num),
943                                         server_name, server_portstr,
944                                         AP_SERVER_BASEVERSION)
945                          : apr_psprintf(p, "%d.%d %s%s",
946                                         HTTP_VERSION_MAJOR(r->proto_num),
947                                         HTTP_VERSION_MINOR(r->proto_num),
948                                         server_name, server_portstr)
949         );
950     }
951
952     /* X-Forwarded-*: handling
953      *
954      * XXX Privacy Note:
955      * -----------------
956      *
957      * These request headers are only really useful when the mod_proxy
958      * is used in a reverse proxy configuration, so that useful info
959      * about the client can be passed through the reverse proxy and on
960      * to the backend server, which may require the information to
961      * function properly.
962      *
963      * In a forward proxy situation, these options are a potential
964      * privacy violation, as information about clients behind the proxy
965      * are revealed to arbitrary servers out there on the internet.
966      *
967      * The HTTP/1.1 Via: header is designed for passing client
968      * information through proxies to a server, and should be used in
969      * a forward proxy configuation instead of X-Forwarded-*. See the
970      * ProxyVia option for details.
971      */
972
973     if (PROXYREQ_REVERSE == r->proxyreq) {
974         const char *buf;
975
976         /* Add X-Forwarded-For: so that the upstream has a chance to
977          * determine, where the original request came from.
978          */
979         apr_table_mergen(r->headers_in, "X-Forwarded-For",
980                          r->connection->remote_ip);
981
982         /* Add X-Forwarded-Host: so that upstream knows what the
983          * original request hostname was.
984          */
985         if ((buf = apr_table_get(r->headers_in, "Host"))) {
986             apr_table_mergen(r->headers_in, "X-Forwarded-Host", buf);
987         }
988
989         /* Add X-Forwarded-Server: so that upstream knows what the
990          * name of this proxy server is (if there are more than one)
991          * XXX: This duplicates Via: - do we strictly need it?
992          */
993         apr_table_mergen(r->headers_in, "X-Forwarded-Server",
994                          r->server->server_hostname);
995     }
996
997     /* send request headers */
998     proxy_run_fixups(r);
999     headers_in_array = apr_table_elts(r->headers_in);
1000     headers_in = (const apr_table_entry_t *) headers_in_array->elts;
1001     for (counter = 0; counter < headers_in_array->nelts; counter++) {
1002         if (headers_in[counter].key == NULL 
1003              || headers_in[counter].val == NULL
1004
1005             /* Already sent */
1006              || !strcasecmp(headers_in[counter].key, "Host")
1007
1008             /* Clear out hop-by-hop request headers not to send
1009              * RFC2616 13.5.1 says we should strip these headers
1010              */
1011              || !strcasecmp(headers_in[counter].key, "Keep-Alive")
1012              || !strcasecmp(headers_in[counter].key, "TE")
1013              || !strcasecmp(headers_in[counter].key, "Trailer")
1014              || !strcasecmp(headers_in[counter].key, "Upgrade")
1015
1016             /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be 
1017              * suppressed if THIS server requested the authentication,
1018              * not when a frontend proxy requested it!
1019              *
1020              * The solution to this problem is probably to strip out
1021              * the Proxy-Authorisation header in the authorisation
1022              * code itself, not here. This saves us having to signal
1023              * somehow whether this request was authenticated or not.
1024              */
1025              || !strcasecmp(headers_in[counter].key,"Proxy-Authorization")
1026              || !strcasecmp(headers_in[counter].key,"Proxy-Authenticate")) {
1027             continue;
1028         }
1029
1030         /* Skip Transfer-Encoding and Content-Length for now.
1031          */
1032         if (!strcasecmp(headers_in[counter].key, "Transfer-Encoding")) {
1033             old_te_val = headers_in[counter].val;
1034             continue;
1035         }
1036         if (!strcasecmp(headers_in[counter].key, "Content-Length")) {
1037             old_cl_val = headers_in[counter].val;
1038             continue;
1039         }
1040
1041         /* for sub-requests, ignore freshness/expiry headers */
1042         if (r->main) {
1043             if (    !strcasecmp(headers_in[counter].key, "If-Match")
1044                  || !strcasecmp(headers_in[counter].key, "If-Modified-Since")
1045                  || !strcasecmp(headers_in[counter].key, "If-Range")
1046                  || !strcasecmp(headers_in[counter].key, "If-Unmodified-Since")
1047                  || !strcasecmp(headers_in[counter].key, "If-None-Match")) {
1048                 continue;
1049             }
1050         }
1051
1052         buf = apr_pstrcat(p, headers_in[counter].key, ": ",
1053                           headers_in[counter].val, CRLF,
1054                           NULL);
1055         ap_xlate_proto_to_ascii(buf, strlen(buf));
1056         e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);
1057         APR_BRIGADE_INSERT_TAIL(header_brigade, e);
1058     }
1059
1060     /* We have headers, let's figure out our request body... */
1061     input_brigade = apr_brigade_create(p, bucket_alloc);
1062
1063     /* sub-requests never use keepalives, and mustn't pass request bodies.
1064      * Because the new logic looks at input_brigade, we will self-terminate
1065      * input_brigade and jump past all of the request body logic...
1066      * Reading anything with ap_get_brigade is likely to consume the
1067      * main request's body or read beyond EOS - which would be unplesant.
1068      */
1069     if (r->main) {
1070         p_conn->close++;
1071         if (old_cl_val) {
1072             old_cl_val = NULL;
1073             apr_table_unset(r->headers_in, "Content-Length");
1074         }
1075         if (old_te_val) {
1076             old_te_val = NULL;
1077             apr_table_unset(r->headers_in, "Transfer-Encoding");
1078         }
1079         rb_method = RB_STREAM_CL;
1080         e = apr_bucket_eos_create(input_brigade->bucket_alloc);
1081         APR_BRIGADE_INSERT_TAIL(input_brigade, e);
1082         goto skip_body;
1083     }
1084
1085     /* WE only understand chunked.  Other modules might inject
1086      * (and therefore, decode) other flavors but we don't know
1087      * that the can and have done so unless they they remove
1088      * their decoding from the headers_in T-E list.
1089      * XXX: Make this extensible, but in doing so, presume the
1090      * encoding has been done by the extensions' handler, and 
1091      * do not modify add_te_chunked's logic
1092      */
1093     if (old_te_val && strcmp(old_te_val, "chunked") != 0) {
1094         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
1095                      "proxy: %s Transfer-Encoding is not supported",
1096                      old_te_val);
1097         return APR_EINVAL;
1098     }
1099
1100     if (old_cl_val && old_te_val) {
1101         ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_ENOTIMPL, r->server,
1102                      "proxy: client %s (%s) requested Transfer-Encoding body"
1103                      " with Content-Length (C-L ignored)",
1104                      c->remote_ip, c->remote_host ? c->remote_host: "");
1105         apr_table_unset(r->headers_in, "Content-Length");
1106         old_cl_val = NULL;
1107         origin->keepalive = AP_CONN_CLOSE;
1108         p_conn->close++;
1109     }
1110
1111     /* Prefetch MAX_MEM_SPOOL bytes
1112      *
1113      * This helps us avoid any election of C-L v.s. T-E
1114      * request bodies, since we are willing to keep in
1115      * memory this much data, in any case.  This gives
1116      * us an instant C-L election if the body is of some
1117      * reasonable size.
1118      */
1119     temp_brigade = apr_brigade_create(p, bucket_alloc);
1120     do {
1121         status = ap_get_brigade(r->input_filters, temp_brigade,
1122                                 AP_MODE_READBYTES, APR_BLOCK_READ,
1123                                 MAX_MEM_SPOOL - bytes_read);
1124         if (status != APR_SUCCESS) {
1125             ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
1126                          "proxy: prefetch request body failed to %s"
1127                          " from %s (%s)",
1128                          p_conn->name ? p_conn->name: "",
1129                          c->remote_ip, c->remote_host ? c->remote_host: "");
1130             return status;
1131         }
1132
1133         apr_brigade_length(temp_brigade, 1, &bytes);
1134         bytes_read += bytes;
1135
1136         /*
1137          * Save temp_brigade in input_brigade. (At least) in the SSL case
1138          * temp_brigade contains transient buckets whose data would get
1139          * overwritten during the next call of ap_get_brigade in the loop.
1140          * ap_save_brigade ensures these buckets to be set aside.
1141          * Calling ap_save_brigade with NULL as filter is OK, because
1142          * input_brigade already has been created and does not need to get
1143          * created by ap_save_brigade.
1144          */
1145         status = ap_save_brigade(NULL, &input_brigade, &temp_brigade, p);
1146         if (status != APR_SUCCESS) {
1147             ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
1148                          "proxy: processing prefetched request body failed"
1149                          " to %s from %s (%s)",
1150                          p_conn->name ? p_conn->name: "",
1151                          c->remote_ip, c->remote_host ? c->remote_host: "");
1152             return status;
1153         }
1154
1155     /* Ensure we don't hit a wall where we have a buffer too small
1156      * for ap_get_brigade's filters to fetch us another bucket,
1157      * surrender once we hit 80 bytes less than MAX_MEM_SPOOL
1158      * (an arbitrary value.)
1159      */
1160     } while ((bytes_read < MAX_MEM_SPOOL - 80) 
1161               && !APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade)));
1162
1163     /* Use chunked request body encoding or send a content-length body?
1164      *
1165      * Prefer C-L when:
1166      *
1167      *   We have no request body (handled by RB_STREAM_CL)
1168      *
1169      *   We have a request body length <= MAX_MEM_SPOOL 
1170      *
1171      *   The administrator has setenv force-proxy-request-1.0
1172      *   
1173      *   The client sent a C-L body, and the administrator has
1174      *   not setenv proxy-sendchunked or has set setenv proxy-sendcl
1175      *
1176      *   The client sent a T-E body, and the administrator has
1177      *   setenv proxy-sendcl, and not setenv proxy-sendchunked
1178      *
1179      * If both proxy-sendcl and proxy-sendchunked are set, the
1180      * behavior is the same as if neither were set, large bodies
1181      * that can't be read will be forwarded in their original
1182      * form of C-L, or T-E.
1183      *
1184      * To ensure maximum compatibility, setenv proxy-sendcl
1185      * To reduce server resource use,   setenv proxy-sendchunked
1186      *
1187      * Then address specific servers with conditional setenv
1188      * options to restore the default behavior where desireable.
1189      *
1190      * We have to compute content length by reading the entire request
1191      * body; if request body is not small, we'll spool the remaining
1192      * input to a temporary file.  Chunked is always preferable.
1193      *
1194      * We can only trust the client-provided C-L if the T-E header
1195      * is absent, and the filters are unchanged (the body won't 
1196      * be resized by another content filter).
1197      */
1198     if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
1199         /* The whole thing fit, so our decision is trivial, use
1200          * the filtered bytes read from the client for the request 
1201          * body Content-Length.
1202          *
1203          * If we expected no body, and read no body, do not set
1204          * the Content-Length.
1205          */
1206         if (old_cl_val || old_te_val || bytes_read) {
1207             old_cl_val = apr_off_t_toa(r->pool, bytes_read);
1208         }
1209         rb_method = RB_STREAM_CL;
1210     }
1211     else if (old_te_val) {
1212         if (force10 
1213              || (apr_table_get(r->subprocess_env, "proxy-sendcl")
1214                   && !apr_table_get(r->subprocess_env, "proxy-sendchunks")
1215                   && !apr_table_get(r->subprocess_env, "proxy-sendchunked"))) {
1216             rb_method = RB_SPOOL_CL;
1217         }
1218         else {
1219             rb_method = RB_STREAM_CHUNKED;
1220         }
1221     }
1222     else if (old_cl_val) {
1223         if (r->input_filters == r->proto_input_filters) {
1224             rb_method = RB_STREAM_CL;
1225         }
1226         else if (!force10 
1227                   && (apr_table_get(r->subprocess_env, "proxy-sendchunks")
1228                       || apr_table_get(r->subprocess_env, "proxy-sendchunked"))
1229                   && !apr_table_get(r->subprocess_env, "proxy-sendcl")) {
1230             rb_method = RB_STREAM_CHUNKED;
1231         }
1232         else {
1233             rb_method = RB_SPOOL_CL;
1234         }
1235     }
1236     else {
1237         /* This is an appropriate default; very efficient for no-body
1238          * requests, and has the behavior that it will not add any C-L
1239          * when the old_cl_val is NULL.
1240          */
1241         rb_method = RB_SPOOL_CL;
1242     }
1243
1244 /* Yes I hate gotos.  This is the subrequest shortcut */
1245 skip_body:
1246     /* Handle Connection: header */
1247     if (!force10 && p_conn->close) {
1248         buf = apr_pstrdup(p, "Connection: close" CRLF);
1249         ap_xlate_proto_to_ascii(buf, strlen(buf));
1250         e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);
1251         APR_BRIGADE_INSERT_TAIL(header_brigade, e);
1252     }
1253
1254     /* send the request body, if any. */
1255     switch(rb_method) {
1256     case RB_STREAM_CHUNKED:
1257         status = stream_reqbody_chunked(p, r, p_conn, origin, header_brigade, 
1258                                         input_brigade);
1259         break;
1260     case RB_STREAM_CL:
1261         status = stream_reqbody_cl(p, r, p_conn, origin, header_brigade, 
1262                                    input_brigade, old_cl_val);
1263         break;
1264     case RB_SPOOL_CL:
1265         status = spool_reqbody_cl(p, r, p_conn, origin, header_brigade,
1266                                   input_brigade, (old_cl_val != NULL)
1267                                               || (old_te_val != NULL)
1268                                               || (bytes_read > 0));
1269         break;
1270     default:
1271         ap_assert(1 != 1);
1272         break;
1273     }
1274
1275     if (status != APR_SUCCESS) {
1276         ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
1277                      "proxy: pass request body failed to %pI (%s)"
1278                      " from %s (%s)",
1279                      p_conn->addr, p_conn->name ? p_conn->name: "",
1280                      c->remote_ip, c->remote_host ? c->remote_host: "");
1281         return status;
1282     }
1283
1284     return APR_SUCCESS;
1285 }
1286
1287 static int addit_dammit(void *v, const char *key, const char *val)
1288 {
1289     apr_table_addn(v, key, val);
1290     return 1;
1291 }
1292
1293 /*
1294  * Limit the number of interim respones we sent back to the client. Otherwise
1295  * we suffer from a memory build up. Besides there is NO sense in sending back
1296  * an unlimited number of interim responses to the client. Thus if we cross
1297  * this limit send back a 502 (Bad Gateway).
1298  */
1299 #ifndef AP_MAX_INTERIM_RESPONSES
1300 #define AP_MAX_INTERIM_RESPONSES 10
1301 #endif
1302
1303 static
1304 apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
1305                                             proxy_http_conn_t *p_conn,
1306                                             conn_rec *origin,
1307                                             proxy_conn_rec *backend,
1308                                             proxy_server_conf *conf,
1309                                             apr_bucket_brigade *bb,
1310                                             char *server_portstr) {
1311     conn_rec *c = r->connection;
1312     char buffer[HUGE_STRING_LEN];
1313     const char *buf;
1314     char keepchar;
1315     request_rec *rp;
1316     apr_bucket *e;
1317     apr_table_t *save_table;
1318     int len, backasswards;
1319     int received_continue = 1; /* flag to indicate if we should
1320                                 * loop over response parsing logic
1321                                 * in the case that the origin told us
1322                                 * to HTTP_CONTINUE
1323                                 */
1324
1325     /* Get response from the remote server, and pass it up the
1326      * filter chain
1327      */
1328
1329     rp = ap_proxy_make_fake_req(origin, r);
1330     /* In case anyone needs to know, this is a fake request that is really a
1331      * response.
1332      */
1333     rp->proxyreq = PROXYREQ_RESPONSE;
1334
1335     while (received_continue && (received_continue <= AP_MAX_INTERIM_RESPONSES)) {
1336         apr_brigade_cleanup(bb);
1337
1338         len = ap_getline(buffer, sizeof(buffer), rp, 0);
1339         if (len == 0) {
1340             /* handle one potential stray CRLF */
1341             len = ap_getline(buffer, sizeof(buffer), rp, 0);
1342         }
1343         if (len <= 0) {
1344             apr_socket_close(p_conn->sock);
1345             backend->connection = NULL;
1346             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1347                           "proxy: error reading status line from remote "
1348                           "server %s", p_conn->name);
1349             return ap_proxyerror(r, HTTP_BAD_GATEWAY,
1350                                  "Error reading from remote server");
1351         }
1352
1353         /* Is it an HTTP/1 response?
1354          * This is buggy if we ever see an HTTP/1.10
1355          */
1356         if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
1357             int major, minor;
1358
1359             if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) {
1360                 major = 1;
1361                 minor = 1;
1362             }
1363             /* If not an HTTP/1 message or
1364              * if the status line was > 8192 bytes
1365              */
1366             else if ((buffer[5] != '1') || (len >= sizeof(buffer)-1)) {
1367                 apr_socket_close(p_conn->sock);
1368                 backend->connection = NULL;
1369                 return ap_proxyerror(r, HTTP_BAD_GATEWAY,
1370                 apr_pstrcat(p, "Corrupt status line returned by remote "
1371                             "server: ", buffer, NULL));
1372             }
1373             backasswards = 0;
1374
1375             keepchar = buffer[12];
1376             buffer[12] = '\0';
1377             r->status = atoi(&buffer[9]);
1378
1379             if (keepchar != '\0') {
1380                 buffer[12] = keepchar;
1381             } else {
1382                 /* 2616 requires the space in Status-Line; the origin
1383                  * server may have sent one but ap_rgetline_core will
1384                  * have stripped it. */
1385                 buffer[12] = ' ';
1386                 buffer[13] = '\0';
1387             }
1388             r->status_line = apr_pstrdup(p, &buffer[9]);
1389             
1390             /* read the headers. */
1391             /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers*/
1392             /* Also, take care with headers with multiple occurences. */
1393
1394             /* First, tuck away all already existing cookies */
1395             save_table = apr_table_make(r->pool, 2);
1396             apr_table_do(addit_dammit, save_table, r->headers_out,
1397                          "Set-Cookie", NULL);
1398
1399             r->headers_out = ap_proxy_read_headers(r, rp, buffer,
1400                                                    sizeof(buffer), origin);
1401             if (r->headers_out == NULL) {
1402                 ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
1403                              r->server, "proxy: bad HTTP/%d.%d header "
1404                              "returned by %s (%s)", major, minor, r->uri,
1405                              r->method);
1406                 p_conn->close += 1;
1407                 /*
1408                  * ap_send_error relies on a headers_out to be present. we
1409                  * are in a bad position here.. so force everything we send out
1410                  * to have nothing to do with the incoming packet
1411                  */
1412                 r->headers_out = apr_table_make(r->pool,1);
1413                 r->status = HTTP_BAD_GATEWAY;
1414                 r->status_line = "bad gateway";
1415                 return r->status;
1416             }
1417
1418             /* Now, add in the just read cookies */
1419             apr_table_do(addit_dammit, save_table, r->headers_out,
1420                          "Set-Cookie", NULL);
1421
1422             /* and now load 'em all in */
1423             if (!apr_is_empty_table(save_table)) {
1424                 apr_table_unset(r->headers_out, "Set-Cookie");
1425                 r->headers_out = apr_table_overlay(r->pool,
1426                                                    r->headers_out,
1427                                                    save_table);
1428             }
1429
1430             /* can't have both Content-Length and Transfer-Encoding */
1431             if (apr_table_get(r->headers_out, "Transfer-Encoding")
1432                 && apr_table_get(r->headers_out, "Content-Length")) {
1433                 /* 2616 section 4.4, point 3: "if both Transfer-Encoding
1434                  * and Content-Length are received, the latter MUST be
1435                  * ignored"; so unset it here to prevent any confusion
1436                  * later. */
1437                 apr_table_unset(r->headers_out, "Content-Length");
1438                 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
1439                              r->server,
1440                              "proxy: server %s returned Transfer-Encoding and Content-Length",
1441                              p_conn->name);
1442                 p_conn->close += 1;
1443             }
1444             
1445             /* strip connection listed hop-by-hop headers from response */
1446             p_conn->close += ap_proxy_liststr(apr_table_get(r->headers_out,
1447                                                             "Connection"),
1448                                               "close");
1449             ap_proxy_clear_connection(p, r->headers_out);
1450             if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
1451                 ap_set_content_type(r, apr_pstrdup(p, buf));
1452             }            
1453             if (!ap_is_HTTP_INFO(r->status)) {
1454                 ap_proxy_pre_http_request(origin, rp);
1455             }
1456
1457             /* handle Via header in response */
1458             if (conf->viaopt != via_off && conf->viaopt != via_block) {
1459                 const char *server_name = ap_get_server_name(r);
1460                 /* If USE_CANONICAL_NAME_OFF was configured for the proxy virtual host,
1461                  * then the server name returned by ap_get_server_name() is the
1462                  * origin server name (which does make too much sense with Via: headers)
1463                  * so we use the proxy vhost's name instead.
1464                  */
1465                 if (server_name == r->hostname)
1466                     server_name = r->server->server_hostname;
1467
1468                 /* create a "Via:" response header entry and merge it */
1469                 apr_table_mergen(r->headers_out, "Via",
1470                                  (conf->viaopt == via_full)
1471                                      ? apr_psprintf(p, "%d.%d %s%s (%s)",
1472                                            HTTP_VERSION_MAJOR(r->proto_num),
1473                                            HTTP_VERSION_MINOR(r->proto_num),
1474                                            server_name,
1475                                            server_portstr,
1476                                            AP_SERVER_BASEVERSION)
1477                                      : apr_psprintf(p, "%d.%d %s%s",
1478                                            HTTP_VERSION_MAJOR(r->proto_num),
1479                                            HTTP_VERSION_MINOR(r->proto_num),
1480                                            server_name,
1481                                            server_portstr)
1482                 );
1483             }
1484
1485             /* cancel keepalive if HTTP/1.0 or less */
1486             if ((major < 1) || (minor < 1)) {
1487                 p_conn->close += 1;
1488                 origin->keepalive = AP_CONN_CLOSE;
1489             }
1490         } else {
1491             /* an http/0.9 response */
1492             backasswards = 1;
1493             r->status = 200;
1494             r->status_line = "200 OK";
1495             p_conn->close += 1;
1496         }
1497
1498         if ( r->status != HTTP_CONTINUE ) {
1499             received_continue = 0;
1500         } else {
1501             received_continue++;
1502             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
1503                          "proxy: HTTP: received 100 CONTINUE");
1504         }
1505
1506         /* we must accept 3 kinds of date, but generate only 1 kind of date */
1507         if ((buf = apr_table_get(r->headers_out, "Date")) != NULL) {
1508             apr_table_set(r->headers_out, "Date",
1509                           ap_proxy_date_canon(p, buf));
1510         }
1511         if ((buf = apr_table_get(r->headers_out, "Expires")) != NULL) {
1512             apr_table_set(r->headers_out, "Expires",
1513                           ap_proxy_date_canon(p, buf));
1514         }
1515         if ((buf = apr_table_get(r->headers_out, "Last-Modified")) != NULL) {
1516             apr_table_set(r->headers_out, "Last-Modified",
1517                           ap_proxy_date_canon(p, buf));
1518         }
1519
1520         /* munge the Location and URI response headers according to
1521          * ProxyPassReverse
1522          */
1523         if ((buf = apr_table_get(r->headers_out, "Location")) != NULL) {
1524             apr_table_set(r->headers_out, "Location",
1525                           ap_proxy_location_reverse_map(r, conf, buf));
1526         }
1527         if ((buf = apr_table_get(r->headers_out, "Content-Location")) != NULL) {
1528             apr_table_set(r->headers_out, "Content-Location",
1529                           ap_proxy_location_reverse_map(r, conf, buf));
1530         }
1531         if ((buf = apr_table_get(r->headers_out, "URI")) != NULL) {
1532             apr_table_set(r->headers_out, "URI",
1533                           ap_proxy_location_reverse_map(r, conf, buf));
1534         }
1535
1536         if ((r->status == 401) && (conf->error_override != 0)) {
1537             const char *wa = "WWW-Authenticate";
1538             if ((buf = apr_table_get(r->headers_out, wa))) {
1539                 apr_table_set(r->err_headers_out, wa, buf);
1540             } else {
1541                 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
1542                              "proxy: origin server sent 401 without WWW-Authenticate header");
1543             }
1544         }
1545
1546         r->sent_bodyct = 1;
1547         /* Is it an HTTP/0.9 response? If so, send the extra data */
1548         if (backasswards) {
1549             apr_ssize_t cntr = len;
1550             e = apr_bucket_heap_create(buffer, cntr, NULL, c->bucket_alloc);
1551             APR_BRIGADE_INSERT_TAIL(bb, e);
1552         }
1553
1554         /* send body - but only if a body is expected */
1555         if ((!r->header_only) &&                   /* not HEAD request */
1556             (r->status > 199) &&                   /* not any 1xx response */
1557             (r->status != HTTP_NO_CONTENT) &&      /* not 204 */
1558             (r->status != HTTP_RESET_CONTENT) &&   /* not 205 */
1559             (r->status != HTTP_NOT_MODIFIED)) {    /* not 304 */
1560
1561             /* We need to copy the output headers and treat them as input
1562              * headers as well.  BUT, we need to do this before we remove
1563              * TE, so that they are preserved accordingly for
1564              * ap_http_filter to know where to end.
1565              */
1566             rp->headers_in = apr_table_copy(r->pool, r->headers_out);
1567
1568             apr_table_unset(r->headers_out,"Transfer-Encoding");
1569
1570             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
1571                          "proxy: start body send");
1572              
1573             /*
1574              * if we are overriding the errors, we can't put the content
1575              * of the page into the brigade
1576              */
1577             if ( (conf->error_override ==0) || r->status < 400 ) {
1578
1579                 /* read the body, pass it to the output filters */
1580                 int finish = FALSE;
1581                 while (ap_get_brigade(rp->input_filters, 
1582                                       bb, 
1583                                       AP_MODE_READBYTES, 
1584                                       APR_BLOCK_READ, 
1585                                       conf->io_buffer_size) == APR_SUCCESS) {
1586 #if DEBUGGING
1587                     {
1588                     apr_off_t readbytes;
1589                     apr_brigade_length(bb, 0, &readbytes);
1590                     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
1591                                  r->server, "proxy (PID %d): readbytes: %#x",
1592                                  getpid(), readbytes);
1593                     }
1594 #endif
1595                     /* sanity check */
1596                     if (APR_BRIGADE_EMPTY(bb)) {
1597                         apr_brigade_cleanup(bb);
1598                         break;
1599                     }
1600
1601                     /* found the last brigade? */
1602                     if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
1603                         /* if this is the last brigade, cleanup the
1604                          * backend connection first to prevent the
1605                          * backend server from hanging around waiting
1606                          * for a slow client to eat these bytes
1607                          */
1608                         ap_proxy_http_cleanup(r, p_conn, backend);
1609                         /* signal that we must leave */
1610                         finish = TRUE;
1611                     }
1612
1613                     /* try send what we read */
1614                     if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS
1615                         || c->aborted) {
1616                         /* Ack! Phbtt! Die! User aborted! */
1617                         p_conn->close = 1;  /* this causes socket close below */
1618                         finish = TRUE;
1619                     }
1620
1621                     /* make sure we always clean up after ourselves */
1622                     apr_brigade_cleanup(bb);
1623
1624                     /* if we are done, leave */
1625                     if (TRUE == finish) {
1626                         break;
1627                     }
1628                 }
1629             }
1630             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
1631                          "proxy: end body send");
1632         } else {
1633             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
1634                          "proxy: header only");
1635         }
1636     }
1637
1638     /* See define of AP_MAX_INTERIM_RESPONSES for why */
1639     if (received_continue > AP_MAX_INTERIM_RESPONSES) {
1640         return ap_proxyerror(r, HTTP_BAD_GATEWAY,
1641                              apr_psprintf(p, 
1642                              "Too many (%d) interim responses from origin server",
1643                              received_continue));
1644     }
1645
1646     if ( conf->error_override ) {
1647         /* the code above this checks for 'OK' which is what the hook expects */
1648         if ( r->status == HTTP_OK )
1649             return OK;
1650         else  {
1651             /* clear r->status for override error, otherwise ErrorDocument
1652              * thinks that this is a recursive error, and doesn't find the
1653              * custom error page
1654              */
1655             int status = r->status;
1656             r->status = HTTP_OK;
1657             /* Discard body, if one is expected */
1658             if ((status > 199) && /* not any 1xx response */
1659                 (status != HTTP_NO_CONTENT) && /* not 204 */
1660                 (status != HTTP_RESET_CONTENT) && /* not 205 */
1661                 (status != HTTP_NOT_MODIFIED)) { /* not 304 */
1662                ap_discard_request_body(rp);
1663            }
1664             return status;
1665         }
1666     } else 
1667         return OK;
1668 }
1669
1670 static
1671 apr_status_t ap_proxy_http_cleanup(request_rec *r, proxy_http_conn_t *p_conn,
1672                                    proxy_conn_rec *backend) {
1673     /* If there are no KeepAlives, or if the connection has been signalled
1674      * to close, close the socket and clean up
1675      */
1676
1677     /* if the connection is < HTTP/1.1, or Connection: close,
1678      * we close the socket, otherwise we leave it open for KeepAlive support
1679      */
1680     if (p_conn->close || (r->proto_num < HTTP_VERSION(1,1))) {
1681         if (p_conn->sock) {
1682             apr_socket_close(p_conn->sock);
1683             p_conn->sock = NULL;
1684             backend->connection = NULL;
1685         }
1686     }
1687     return OK;
1688 }
1689
1690 /*
1691  * This handles http:// URLs, and other URLs using a remote proxy over http
1692  * If proxyhost is NULL, then contact the server directly, otherwise
1693  * go via the proxy.
1694  * Note that if a proxy is used, then URLs other than http: can be accessed,
1695  * also, if we have trouble which is clearly specific to the proxy, then
1696  * we return DECLINED so that we can try another proxy. (Or the direct
1697  * route.)
1698  */
1699 int ap_proxy_http_handler(request_rec *r, proxy_server_conf *conf,
1700                           char *url, const char *proxyname, 
1701                           apr_port_t proxyport)
1702 {
1703     int status;
1704     char server_portstr[32];
1705     conn_rec *origin = NULL;
1706     proxy_conn_rec *backend = NULL;
1707     int is_ssl = 0;
1708
1709     /* Note: Memory pool allocation.
1710      * A downstream keepalive connection is always connected to the existence
1711      * (or not) of an upstream keepalive connection. If this is not done then
1712      * load balancing against multiple backend servers breaks (one backend
1713      * server ends up taking 100% of the load), and the risk is run of
1714      * downstream keepalive connections being kept open unnecessarily. This
1715      * keeps webservers busy and ties up resources.
1716      *
1717      * As a result, we allocate all sockets out of the upstream connection
1718      * pool, and when we want to reuse a socket, we check first whether the
1719      * connection ID of the current upstream connection is the same as that
1720      * of the connection when the socket was opened.
1721      */
1722     apr_pool_t *p = r->connection->pool;
1723     conn_rec *c = r->connection;
1724     apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc);
1725     apr_uri_t *uri = apr_palloc(r->connection->pool, sizeof(*uri));
1726     proxy_http_conn_t *p_conn = apr_pcalloc(r->connection->pool,
1727                                            sizeof(*p_conn));
1728
1729     /* is it for us? */
1730     if (strncasecmp(url, "https:", 6) == 0) {
1731         if (!ap_proxy_ssl_enable(NULL)) {
1732             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
1733                          "proxy: HTTPS: declining URL %s"
1734                          " (mod_ssl not configured?)", url);
1735             return DECLINED;
1736         }
1737         is_ssl = 1;
1738     }
1739     else if (!(strncasecmp(url, "http:", 5)==0 || (strncasecmp(url, "ftp:", 4)==0 && proxyname))) {
1740         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
1741                      "proxy: HTTP: declining URL %s", url);
1742         return DECLINED; /* only interested in HTTP, or FTP via proxy */
1743     }
1744     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
1745              "proxy: HTTP: serving URL %s", url);
1746     
1747     
1748     /* only use stored info for top-level pages. Sub requests don't share 
1749      * in keepalives
1750      */
1751     if (!r->main) {
1752         backend = (proxy_conn_rec *) ap_get_module_config(c->conn_config,
1753                                                       &proxy_http_module);
1754     }
1755     /* create space for state information */
1756     if (!backend) {
1757         backend = apr_pcalloc(c->pool, sizeof(proxy_conn_rec));
1758         backend->connection = NULL;
1759         backend->hostname = NULL;
1760         backend->port = 0;
1761         if (!r->main) {
1762             ap_set_module_config(c->conn_config, &proxy_http_module, backend);
1763         }
1764     }
1765
1766     backend->is_ssl = is_ssl;
1767
1768     /* Step One: Determine Who To Connect To */
1769     status = ap_proxy_http_determine_connection(p, r, p_conn, c, conf, uri,
1770                                                 &url, proxyname, proxyport,
1771                                                 server_portstr,
1772                                                 sizeof(server_portstr));
1773     if ( status != OK ) {
1774         return status;
1775     }
1776
1777     /* Step Two: Make the Connection */
1778     status = ap_proxy_http_create_connection(p, r, p_conn, c, &origin, backend,
1779                                              conf, proxyname);
1780     if ( status != OK ) {
1781         return status;
1782     }
1783    
1784     /* Step Three: Send the Request */
1785     status = ap_proxy_http_request(p, r, p_conn, origin, conf, uri, url, bb,
1786                                    server_portstr);
1787     if ( status != OK ) {
1788         return status;
1789     }
1790
1791     /* Step Four: Receive the Response */
1792     status = ap_proxy_http_process_response(p, r, p_conn, origin, backend, conf,
1793                                             bb, server_portstr);
1794     if ( status != OK ) {
1795         /* clean up even if there is an error */
1796         ap_proxy_http_cleanup(r, p_conn, backend);
1797         return status;
1798     }
1799
1800     /* Step Five: Clean Up */
1801     status = ap_proxy_http_cleanup(r, p_conn, backend);
1802     if ( status != OK ) {
1803         return status;
1804     }
1805
1806     return OK;
1807 }
1808
1809 static void ap_proxy_http_register_hook(apr_pool_t *p)
1810 {
1811     proxy_hook_scheme_handler(ap_proxy_http_handler, NULL, NULL, APR_HOOK_FIRST);
1812     proxy_hook_canon_handler(ap_proxy_http_canon, NULL, NULL, APR_HOOK_FIRST);
1813 }
1814
1815 module AP_MODULE_DECLARE_DATA proxy_http_module = {
1816     STANDARD20_MODULE_STUFF,
1817     NULL,              /* create per-directory config structure */
1818     NULL,              /* merge per-directory config structures */
1819     NULL,              /* create per-server config structure */
1820     NULL,              /* merge per-server config structures */
1821     NULL,              /* command apr_table_t */
1822     ap_proxy_http_register_hook/* register hooks */
1823 };
1824