]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Haven't heard any vetoes regarding this, so might as well fold it
authorJim Jagielski <jim@apache.org>
Mon, 14 Oct 2002 14:11:24 +0000 (14:11 +0000)
committerJim Jagielski <jim@apache.org>
Mon, 14 Oct 2002 14:11:24 +0000 (14:11 +0000)
in. Not too happy about cluttering up the list of directives either.
But, at least, it allows 2.0 to proxy stupid IIS as much as 1.3.
Docs to come soon.
PR:
Obtained from:
Submitted by:
Reviewed by:

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@97202 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/proxy/mod_proxy.c
modules/proxy/mod_proxy.h
modules/proxy/proxy_util.c

diff --git a/CHANGES b/CHANGES
index 632c728aa8c8b8013cb45de6f05dbbb1bb420625..93623a2f915d4330a3f7e87a3abaa848515d5e89 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,10 @@
 Changes with Apache 2.0.44
 
+  *) Add the ProxyBadHeader directive, which gives the admin some
+     control on how mod_proxy should handle bogus HTTP headers from
+     proxied servers. This allows 2.0 to "emulate" 1.3's behavior if
+     desired. [Jim Jagielski]
+
   *) Change the LDAP modules to export their symbols correctly
      during a Windows build. Add dsp files for Windows. Update
      README.ldap file for Windows build instructions.
index 58eadbf989a3489ff5e61527c3d22b6a243c7b63..1092cce778867d3f59d30afe50173b4cdda6e7cb 100644 (file)
@@ -63,8 +63,6 @@
 
 #include "apr_optional.h"
 
-extern module AP_MODULE_DECLARE_DATA proxy_module;
-
 #ifndef MAX
 #define MAX(x,y) ((x) >= (y) ? (x) : (y))
 #endif
@@ -499,10 +497,12 @@ static void * create_proxy_config(apr_pool_t *p, server_rec *s)
     ps->maxfwd_set = 0;
     ps->error_override = 0; 
     ps->error_override_set = 0; 
-    ps->preserve_host_set =0;
-    ps->preserve_host =0;    
-    ps->timeout=0;
-    ps->timeout_set=0;
+    ps->preserve_host_set = 0;
+    ps->preserve_host = 0;    
+    ps->timeout = 0;
+    ps->timeout_set = 0;
+    ps->badopt = bad_error;
+    ps->badopt_set = 0;
     return ps;
 }
 
@@ -529,6 +529,7 @@ static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv)
     ps->error_override = (overrides->error_override_set == 0) ? base->error_override : overrides->error_override;
     ps->preserve_host = (overrides->preserve_host_set == 0) ? base->preserve_host : overrides->preserve_host;
     ps->timeout= (overrides->timeout_set == 0) ? base->timeout : overrides->timeout;
+    ps->badopt = (overrides->badopt_set == 0) ? base->badopt : overrides->badopt;
 
     return ps;
 }
@@ -914,6 +915,27 @@ static const char*
     return NULL;    
 }
 
+static const char*
+    set_bad_opt(cmd_parms *parms, void *dummy, const char *arg)
+{
+    proxy_server_conf *psf =
+    ap_get_module_config(parms->server->module_config, &proxy_module);
+
+    if (strcasecmp(arg, "IsError") == 0)
+        psf->badopt = bad_error;
+    else if (strcasecmp(arg, "Ignore") == 0)
+        psf->badopt = bad_ignore;
+    else if (strcasecmp(arg, "StartBody") == 0)
+        psf->badopt = bad_body;
+    else {
+        return "ProxyBadHeader must be one of: "
+            "IsError | Ignore | StartBody";
+    }
+
+    psf->badopt_set = 1;
+    return NULL;    
+}
+
 static void ap_add_per_proxy_conf(server_rec *s, ap_conf_vector_t *dir_config)
 {
     proxy_server_conf *sconf = ap_get_module_config(s->module_config,
@@ -1042,6 +1064,8 @@ static const command_rec proxy_cmds[] =
     AP_INIT_TAKE1("ProxyTimeout", set_proxy_timeout, NULL, RSRC_CONF,
      "Set the timeout (in seconds) for a proxied connection. "
      "This overrides the server timeout"),
+    AP_INIT_TAKE1("ProxyBadHeader", set_bad_opt, NULL, RSRC_CONF,
+     "How to handle bad header line in response: IsError | Ignore | StartBody"),
  
     {NULL}
 };
index b971ceff8712208b46c99dd35ac862d85159ea34..930aa97b3c11b7d66c96c90216e2f4de50e81e16 100644 (file)
@@ -195,6 +195,12 @@ typedef struct {
     int preserve_host_set;
     apr_interval_time_t timeout;
     apr_interval_time_t timeout_set;
+    enum {
+      bad_error,
+      bad_ignore,
+      bad_body
+    } badopt;                   /* how to deal with bad headers */
+    char badopt_set;
 
 } proxy_server_conf;
 
@@ -284,4 +290,7 @@ PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, ap
 PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
 PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
 
+/* For proxy_util */
+extern module AP_MODULE_DECLARE_DATA proxy_module;
+
 #endif /*MOD_PROXY_H*/
index d989372c77708fd925a5f537549f2c7c0a71e024..e447f98fe7e6922edfa4cf0e622f51884ca2e8cd 100644 (file)
@@ -433,6 +433,11 @@ PROXY_DECLARE(apr_table_t *)ap_proxy_read_headers(request_rec *r, request_rec *r
     int len;
     char *value, *end;
     char field[MAX_STRING_LEN];
+    int saw_headers = 0;
+    void *sconf = r->server->module_config;
+    proxy_server_conf *psc;
+
+    psc = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
 
     headers_out = apr_table_make(r->pool, 20);
 
@@ -444,19 +449,47 @@ PROXY_DECLARE(apr_table_t *)ap_proxy_read_headers(request_rec *r, request_rec *r
 
        if (!(value = strchr(buffer, ':'))) {     /* Find the colon separator */
 
-           /* Buggy MS IIS servers sometimes return invalid headers
-            * (an extra "HTTP/1.0 200, OK" line sprinkled in between
-            * the usual MIME headers). Try to deal with it in a sensible
-            * way, but log the fact.
-            * XXX: The mask check is buggy if we ever see an HTTP/1.10 */
+           /* We may encounter invalid headers, usually from buggy
+            * MS IIS servers, so we need to determine just how to handle
+            * them. We can either ignore them, assume that they mark the
+            * start-of-body (eg: a missing CRLF) or (the default) mark
+            * the headers as totally bogus and return a 500. The sole
+            * exception is an extra "HTTP/1.0 200, OK" line sprinkled
+            * in between the usual MIME headers, which is a favorite
+            * IIS bug.
+            */
+            /* XXX: The mask check is buggy if we ever see an HTTP/1.10 */
 
            if (!apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
-               /* Nope, it wasn't even an extra HTTP header. Give up. */
-               return NULL;
+               if (psc->badopt == bad_error) {
+                   /* Nope, it wasn't even an extra HTTP header. Give up. */
+                   return NULL;
+               }
+               else if (psc->badopt == bad_body) {
+                   /* if we've already started loading headers_out, then
+                    * return what we've accumulated so far, in the hopes
+                    * that they are useful. Otherwise, we completely bail.
+                    */
+                   /* FIXME: We've already scarfed the supposed 1st line of
+                    * the body, so the actual content may end up being bogus
+                    * as well. If the content is HTML, we may be lucky.
+                    */
+                   if (saw_headers) {
+                       ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server,
+                        "proxy: Starting body due to bogus non-header in headers "
+                        "returned by %s (%s)", r->uri, r->method);
+                       return headers_out;
+                   } else {
+                        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server,
+                        "proxy: No HTTP headers "
+                        "returned by %s (%s)", r->uri, r->method);
+                       return NULL;
+                   }
+               }
            }
-
+           /* this is the psc->badopt == bad_ignore case */
            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server,
-                        "proxy: Ignoring duplicate HTTP header "
+                        "proxy: Ignoring bogus HTTP header "
                         "returned by %s (%s)", r->uri, r->method);
            continue;
        }
@@ -475,6 +508,7 @@ PROXY_DECLARE(apr_table_t *)ap_proxy_read_headers(request_rec *r, request_rec *r
 
         /* make sure we add so as not to destroy duplicated headers */
         apr_table_add(headers_out, buffer, value);
+        saw_headers = 1;
 
        /* the header was too long; at the least we should skip extra data */
        if (len >= size - 1) {