Hi all,

This patch pulls in the Connection: header handling and the hop-by-hop
header stripping from the v1.3 HTTP/1.1 patch. It changes the client
level to HTTP/1.1, and adds some comments.

I'll apply it once the auth patch is sorted out, unless there are
objections.

Regards,
Graham
-- 
-----------------------------------------
[EMAIL PROTECTED]               "There's a moon
                                        over Bourbon Street
                                                tonight..."
diff -c -r --exclude CVS tmp/CHANGES httpd-proxy/CHANGES
*** tmp/CHANGES Tue Mar 13 01:03:46 2001
--- httpd-proxy/CHANGES Tue Mar 13 16:25:25 2001
***************
*** 1,5 ****
! =======
! Last modified at [$Date: 2001/03/13 00:03:46 $]
  
  mod_proxy changes for 2.0build14
  
--- 1,11 ----
! 
!   *) Some small changes:
!      - Ensured hop-by-hop headers were stripped as per
!        RFC2616 13.5.1.
!      - Upgraded version code to HTTP/1.1.
!      - Added Connection: close until Keepalives come.
!      - Some cosmetic fixes and commenting.
!      [Graham Leggett <[EMAIL PROTECTED]>]
  
  mod_proxy changes for 2.0build14
  
diff -c -r --exclude CVS tmp/module-2.0/proxy_http.c 
httpd-proxy/module-2.0/proxy_http.c
*** tmp/module-2.0/proxy_http.c Mon Mar 12 00:33:14 2001
--- httpd-proxy/module-2.0/proxy_http.c Tue Mar 13 16:07:52 2001
***************
*** 119,125 ****
      return OK;
  }
   
! static const char *proxy_location_reverse_map(request_rec *r, const char *url)
  {
      void *sconf;
      proxy_server_conf *conf;
--- 119,125 ----
      return OK;
  }
   
! static const char *ap_proxy_location_reverse_map(request_rec *r, const char 
*url)
  {
      void *sconf;
      proxy_server_conf *conf;
***************
*** 127,132 ****
--- 127,135 ----
      int i, l1, l2;
      char *u;
  
+     /* XXX FIXME: Make sure this handled the ambiguous case of the :80
+      * after the hostname */
+ 
      sconf = r->server->module_config;
      conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
      l1 = strlen(url);
***************
*** 142,148 ****
  }
  
  /* Clear all connection-based headers from the incoming headers table */
! static void clear_connection(apr_pool_t *p, apr_table_t *headers)
  {
      const char *name;
      char *next = apr_pstrdup(p, apr_table_get(headers, "Connection"));
--- 145,151 ----
  }
  
  /* Clear all connection-based headers from the incoming headers table */
! static void ap_proxy_clear_connection(apr_pool_t *p, apr_table_t *headers)
  {
      const char *name;
      char *next = apr_pstrdup(p, apr_table_get(headers, "Connection"));
***************
*** 185,190 ****
--- 188,194 ----
      apr_array_header_t *reqhdrs_arr;
      apr_table_t *resp_hdrs = NULL;
      apr_table_entry_t *reqhdrs;
+     const char *table_buf;
      struct sockaddr_in server;
      struct in_addr destaddr;
      char buffer[HUGE_STRING_LEN];
***************
*** 210,216 ****
      memset(&server, '\0', sizeof(server));
      server.sin_family = AF_INET;
  
! /* We break the URL into host, port, path-search */
  
      urlptr = strstr(url, "://");
      if (urlptr == NULL)
--- 214,220 ----
      memset(&server, '\0', sizeof(server));
      server.sin_family = AF_INET;
  
!     /* We break the URL into host, port, path-search */
  
      urlptr = strstr(url, "://");
      if (urlptr == NULL)
***************
*** 239,245 ****
        }
      }
  
! /* check if ProxyBlock directive on this host */
      destaddr.s_addr = apr_inet_addr(desthost);
      for (i = 0; i < conf->noproxies->nelts; i++) {
        if ((npent[i].name != NULL
--- 243,249 ----
        }
      }
  
!     /* check if ProxyBlock directive on this host */
      destaddr.s_addr = apr_inet_addr(desthost);
      for (i = 0; i < conf->noproxies->nelts; i++) {
        if ((npent[i].name != NULL
***************
*** 285,298 ****
          /* the peer reset the connection already; ap_new_connection() 
           * closed the socket */
          /* XXX somebody that knows what they're doing add an error path */
      }
  
      ap_add_output_filter("CORE", NULL, NULL, origin);
  
!     clear_connection(r->pool, r->headers_in); /* Strip connection-based 
headers */
  
      buf = apr_pstrcat(r->pool, r->method, " ", proxyhost ? url : urlptr,
!                       " HTTP/1.0" CRLF, NULL);
      e = apr_bucket_pool_create(buf, strlen(buf), r->pool);
      APR_BRIGADE_INSERT_TAIL(bb, e);
      if (destportstr != NULL && destport != DEFAULT_HTTP_PORT) {
--- 289,307 ----
          /* the peer reset the connection already; ap_new_connection() 
           * closed the socket */
          /* XXX somebody that knows what they're doing add an error path */
+       /* XXX how's this? */
+       return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(r->pool,
+                            "Connection reset by peer: ",
+                            desthost, NULL));
      }
  
      ap_add_output_filter("CORE", NULL, NULL, origin);
  
!     /* strip connection listed hop-by-hop headers from the request */
!     ap_proxy_clear_connection(r->pool, r->headers_in);
  
      buf = apr_pstrcat(r->pool, r->method, " ", proxyhost ? url : urlptr,
!                       " HTTP/1.1" CRLF, NULL);
      e = apr_bucket_pool_create(buf, strlen(buf), r->pool);
      APR_BRIGADE_INSERT_TAIL(bb, e);
      if (destportstr != NULL && destport != DEFAULT_HTTP_PORT) {
***************
*** 306,311 ****
--- 315,321 ----
          APR_BRIGADE_INSERT_TAIL(bb, e);
      }
  
+     /* handle Via */
      if (conf->viaopt == via_block) {
        /* Block all outgoing Via: headers */
        apr_table_unset(r->headers_in, "Via");
***************
*** 318,324 ****
            apr_snprintf(portstr, sizeof portstr, ":%d", i);
        }
        /* Generate outgoing Via: header with/without server comment: */
!       ap_table_mergen(r->headers_in, "Via",
                    (conf->viaopt == via_full)
                        ? apr_psprintf(p, "%d.%d %s%s (%s)",
                                HTTP_VERSION_MAJOR(r->proto_num),
--- 328,334 ----
            apr_snprintf(portstr, sizeof portstr, ":%d", i);
        }
        /* Generate outgoing Via: header with/without server comment: */
!       apr_table_mergen(r->headers_in, "Via",
                    (conf->viaopt == via_full)
                        ? apr_psprintf(p, "%d.%d %s%s (%s)",
                                HTTP_VERSION_MAJOR(r->proto_num),
***************
*** 332,363 ****
                        );
      }
  
      reqhdrs_arr = apr_table_elts(r->headers_in);
      reqhdrs = (apr_table_entry_t *) reqhdrs_arr->elts;
      for (i = 0; i < reqhdrs_arr->nelts; i++) {
        if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL
!       /* Clear out headers not to send */
            || !strcasecmp(reqhdrs[i].key, "Host")      /* Already sent */
            /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be 
             * suppressed if THIS server requested the authentication,
             * not when a frontend proxy requested it!
             */
!           || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization"))
            continue;
          buf = apr_pstrcat(r->pool, reqhdrs[i].key, ": ", reqhdrs[i].val, 
CRLF, NULL);
          e = apr_bucket_pool_create(buf, strlen(buf), r->pool);
          APR_BRIGADE_INSERT_TAIL(bb, e);
  
      }
  
      e = apr_bucket_pool_create(CRLF, strlen(CRLF), r->pool);
      APR_BRIGADE_INSERT_TAIL(bb, e);
      e = apr_bucket_flush_create();
      APR_BRIGADE_INSERT_TAIL(bb, e);
  
      ap_pass_brigade(origin->output_filters, bb);
- /* send the request data, if any. */
  
      if (ap_should_client_block(r)) {
        while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) {
              e = apr_bucket_pool_create(buffer, i, r->pool);
--- 342,396 ----
                        );
      }
  
+     /* send request headers */
      reqhdrs_arr = apr_table_elts(r->headers_in);
      reqhdrs = (apr_table_entry_t *) reqhdrs_arr->elts;
      for (i = 0; i < reqhdrs_arr->nelts; i++) {
        if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL
! 
!       /* Clear out hop-by-hop request headers not to send
!        * RFC2616 13.5.1 says we should strip these headers
!        */
            || !strcasecmp(reqhdrs[i].key, "Host")      /* Already sent */
+             || !strcasecmp(reqhdrs[i].key, "Keep-Alive")
+             || !strcasecmp(reqhdrs[i].key, "TE")
+             || !strcasecmp(reqhdrs[i].key, "Trailer")
+             || !strcasecmp(reqhdrs[i].key, "Transfer-Encoding")
+             || !strcasecmp(reqhdrs[i].key, "Upgrade")
+ 
            /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be 
             * suppressed if THIS server requested the authentication,
             * not when a frontend proxy requested it!
+              *
+              * The solution to this problem is probably to strip out
+              * the Proxy-Authorisation header in the authorisation
+              * code itself, not here. This saves us having to signal
+              * somehow whether this request was authenticated or not.
             */
!           || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization")
!           || !strcasecmp(reqhdrs[i].key, "Proxy-Authenticate"))
            continue;
+ 
          buf = apr_pstrcat(r->pool, reqhdrs[i].key, ": ", reqhdrs[i].val, 
CRLF, NULL);
          e = apr_bucket_pool_create(buf, strlen(buf), r->pool);
          APR_BRIGADE_INSERT_TAIL(bb, e);
  
      }
  
+     /* we don't yet support keepalives - but we will soon, I promise! */
+     buf = apr_pstrcat(r->pool, "Connection: close", CRLF, NULL);
+     e = apr_bucket_pool_create(buf, strlen(buf), r->pool);
+     APR_BRIGADE_INSERT_TAIL(bb, e);
+ 
+     /* add empty line at the end of the headers */
      e = apr_bucket_pool_create(CRLF, strlen(CRLF), r->pool);
      APR_BRIGADE_INSERT_TAIL(bb, e);
      e = apr_bucket_flush_create();
      APR_BRIGADE_INSERT_TAIL(bb, e);
  
      ap_pass_brigade(origin->output_filters, bb);
  
+     /* send the request data, if any. */
      if (ap_should_client_block(r)) {
        while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) {
              e = apr_bucket_pool_create(buffer, i, r->pool);
***************
*** 396,410 ****
      APR_BUCKET_REMOVE(e);
      apr_bucket_destroy(e);
  
! /* Is it an HTTP/1 response?  This is buggy if we ever see an HTTP/1.10 */
      if (ap_checkmask(buffer2, "HTTP/#.# ###*")) {
        int major, minor;
        if (2 != sscanf(buffer2, "HTTP/%u.%u", &major, &minor)) {
            major = 1;
!           minor = 0;
        }
  
! /* If not an HTTP/1 message or if the status line was > 8192 bytes */
        if (buffer2[5] != '1' || buffer2[len - 1] != '\n') {
            apr_socket_close(sock);
            return HTTP_BAD_GATEWAY;
--- 429,443 ----
      APR_BUCKET_REMOVE(e);
      apr_bucket_destroy(e);
  
!     /* Is it an HTTP/1 response?  This is buggy if we ever see an HTTP/1.10 */
      if (ap_checkmask(buffer2, "HTTP/#.# ###*")) {
        int major, minor;
        if (2 != sscanf(buffer2, "HTTP/%u.%u", &major, &minor)) {
            major = 1;
!           minor = 1;
        }
  
!         /* If not an HTTP/1 message or if the status line was > 8192 bytes */
        if (buffer2[5] != '1' || buffer2[len - 1] != '\n') {
            apr_socket_close(sock);
            return HTTP_BAD_GATEWAY;
***************
*** 418,426 ****
        buffer2[12] = ' ';
        r->status_line = apr_pstrdup(p, &buffer2[9]);
  
! /* read the headers. */
! /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */
! /* Also, take care with headers with multiple occurences. */
  
        resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, origin);
        if (resp_hdrs == NULL) {
--- 451,459 ----
        buffer2[12] = ' ';
        r->status_line = apr_pstrdup(p, &buffer2[9]);
  
!         /* read the headers. */
!         /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */
!         /* Also, take care with headers with multiple occurences. */
  
        resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, origin);
        if (resp_hdrs == NULL) {
***************
*** 431,442 ****
        }
          else
          {
!             clear_connection(p, resp_hdrs);    /* Strip Connection hdrs */
              if (apr_table_get(resp_hdrs, "Content-type")) {
                  r->content_type = apr_pstrdup(r->pool, 
apr_table_get(resp_hdrs, "Content-type"));
              }
          }
  
        if (conf->viaopt != via_off && conf->viaopt != via_block) {
            /* Create a "Via:" response header entry and merge it */
            i = ap_get_server_port(r);
--- 464,477 ----
        }
          else
          {
!           /* strip connection listed hop-by-hop headers from response */
!             ap_proxy_clear_connection(p, resp_hdrs);
              if (apr_table_get(resp_hdrs, "Content-type")) {
                  r->content_type = apr_pstrdup(r->pool, 
apr_table_get(resp_hdrs, "Content-type"));
              }
          }
  
+         /* handle Via header in response */
        if (conf->viaopt != via_off && conf->viaopt != via_block) {
            /* Create a "Via:" response header entry and merge it */
            i = ap_get_server_port(r);
***************
*** 448,470 ****
        }
      }
      else {
! /* an http/0.9 response */
        backasswards = 1;
        r->status = 200;
        r->status_line = "200 OK";
      }
  
! /*
!  * HTTP/1.0 requires us to accept 3 types of dates, but only generate
!  * one type
!  */
  
  /*
      if (!r->assbackwards)
        ap_rputs(CRLF, r);
  */
      r->sent_bodyct = 1;
! /* Is it an HTTP/0.9 response? If so, send the extra data */
      if (backasswards) {
          cntr = len;
          e = apr_bucket_heap_create(buffer, cntr, 0, NULL);
--- 483,508 ----
        }
      }
      else {
!         /* an http/0.9 response */
        backasswards = 1;
        r->status = 200;
        r->status_line = "200 OK";
      }
  
!     /* munge the Location and URI response headers according to 
ProxyPassReverse */
!     if ((table_buf = apr_table_get(resp_hdrs, "Location")) != NULL)
!         apr_table_set(resp_hdrs, "Location", ap_proxy_location_reverse_map(r, 
buf));
!     if ((table_buf = apr_table_get(resp_hdrs, "Content-Location")) != NULL)
!         apr_table_set(resp_hdrs, "Content-Location", 
ap_proxy_location_reverse_map(r, buf));
!     if ((table_buf = apr_table_get(resp_hdrs, "URI")) != NULL)
!         apr_table_set(resp_hdrs, "URI", ap_proxy_location_reverse_map(r, 
buf));
  
  /*
      if (!r->assbackwards)
        ap_rputs(CRLF, r);
  */
      r->sent_bodyct = 1;
!     /* Is it an HTTP/0.9 response? If so, send the extra data */
      if (backasswards) {
          cntr = len;
          e = apr_bucket_heap_create(buffer, cntr, 0, NULL);
diff -c -r --exclude CVS tmp/module-2.0/proxy_util.c 
httpd-proxy/module-2.0/proxy_util.c
*** tmp/module-2.0/proxy_util.c Mon Mar 12 00:33:24 2001
--- httpd-proxy/module-2.0/proxy_util.c Tue Mar 13 16:08:37 2001
***************
*** 450,456 ****
        for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); 
--end)
            *end = '\0';
  
!         ap_table_add(resp_hdrs, buffer, value);
  
        /* the header was too long; at the least we should skip extra data */
        if (len >= size - 1) { 
--- 450,456 ----
        for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); 
--end)
            *end = '\0';
  
!         apr_table_add(resp_hdrs, buffer, value);
  
        /* the header was too long; at the least we should skip extra data */
        if (len >= size - 1) { 
***************
*** 482,488 ****
        apr_size_t len = strlen(temp);
        apr_send(fp, temp, &len);
  
!       for (i = 0; i < ap_table_elts(t)->nelts; ++i) {
              if (elts[i].key != NULL) {
                  temp = apr_pstrcat(r->pool, elts[i].key, ": ", elts[i].val, 
CRLF, NULL);
                  apr_send(fp, temp, &len);
--- 482,488 ----
        apr_size_t len = strlen(temp);
        apr_send(fp, temp, &len);
  
!       for (i = 0; i < apr_table_elts(t)->nelts; ++i) {
              if (elts[i].key != NULL) {
                  temp = apr_pstrcat(r->pool, elts[i].key, ": ", elts[i].val, 
CRLF, NULL);
                  apr_send(fp, temp, &len);
***************
*** 1046,1052 ****
      return rv;
  }
  
! /* This function is called by ap_table_do() for all header lines */
  /* (from proxy_http.c and proxy_ftp.c) */
  /* It is passed a table_do_args struct pointer and a MIME field and value 
pair */
  int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
--- 1046,1052 ----
      return rv;
  }
  
! /* This function is called by apr_table_do() for all header lines */
  /* (from proxy_http.c and proxy_ftp.c) */
  /* It is passed a table_do_args struct pointer and a MIME field and value 
pair */
  int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
***************
*** 1056,1062 ****
          return 1;
      if (!r->assbackwards)
          ap_rvputs(r, key, ": ", value, CRLF, NULL);
!     return 1; /* tell ap_table_do() to continue calling us for more headers */
  }
  
  #if defined WIN32
--- 1056,1062 ----
          return 1;
      if (!r->assbackwards)
          ap_rvputs(r, key, ": ", value, CRLF, NULL);
!     return 1; /* tell apr_table_do() to continue calling us for more headers 
*/
  }
  
  #if defined WIN32

Reply via email to