]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Overhaul the compatibility with 1.3's subrequest and redirect processing.
authorWilliam A. Rowe Jr <wrowe@apache.org>
Fri, 28 Sep 2001 04:46:37 +0000 (04:46 +0000)
committerWilliam A. Rowe Jr <wrowe@apache.org>
Fri, 28 Sep 2001 04:46:37 +0000 (04:46 +0000)
  Eliminate URI-centric phases in ap_process_request_internal() for pure
  file subrequests (that don't correspond to URI space.)  translate_name
  hook and location_walks are skipped for these requests.

  Moves the reset of the per_dir_config out of directory_walk into the
  internal request processing code, so that resources with alternate
  map_to_storage requirements start with clean r->server->lookup_defaults.

  Optimizes out the authn/authz of effectively identical subreqests and
  redirects, as the sub_req_lookup calls once did.  Unlike 1.3, we copy
  r->user and r->ap_auth_type from main/prev for the request's reference.

  Stop copying the subrequest's r->chunked flag (Rbb assured me it looked
  bogus, chunking is on the parent request) and clean out other #if 0'ed
  cruft we don't need to refer back to anymore.

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

server/request.c

index fc75c45104e2cf66dd2137ef3b8bd10169967e7c..b7bb3ee7db34e2264371f1769480c1893e0391f7 100644 (file)
@@ -151,22 +151,41 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
 
     ap_getparents(r->uri);     /* OK --- shrinking transformations... */
 
-    if ((access_status = ap_location_walk(r))) {
-        return access_status;
-    }
+    /* File-specific requests with no 'true' URI are a huge pain... they 
+     * cannot bubble through the next several steps.  Only subrequests may 
+     * have an empty uri, otherwise let translate_name kill the request.
+     */
+    if (!r->main || (r->uri && r->uri[0]))
+    {
+        if ((access_status = ap_location_walk(r))) {
+            return access_status;
+        }
 
-    if ((access_status = ap_run_translate_name(r))) {
-        return decl_die(access_status, "translate", r);
-        return access_status;
+        if ((access_status = ap_run_translate_name(r))) {
+            return decl_die(access_status, "translate", r);
+            return access_status;
+        }
     }
 
-    if ((access_status = ap_run_map_to_storage(r))) {
+    /* Reset to the server default config prior to running map_to_storage 
+     */
+    r->per_dir_config = r->server->lookup_defaults;
+
+    if ((access_status = ap_run_map_to_storage(r))) 
+    {
         /* This request wasn't in storage (e.g. TRACE) */
         return access_status;
     }
 
-    if ((access_status = ap_location_walk(r))) {
-        return access_status;
+    /* Excluding file-specific requests with no 'true' URI...
+     */
+    if (!r->main || (r->uri && r->uri[0]))
+    {
+        /* Rerun the location walk, which overrides any map_to_storage config.
+         */
+        if ((access_status = ap_location_walk(r))) {
+            return access_status;
+        }
     }
 
     /* Only on the main request! */
@@ -176,46 +195,61 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
         }
     }
 
-    switch (ap_satisfies(r)) {
-    case SATISFY_ALL:
-    case SATISFY_NOSPEC:
-        if ((access_status = ap_run_access_checker(r)) != 0) {
-            return decl_die(access_status, "check access", r);
-        }
-        if (ap_some_auth_required(r)) {
-            if (((access_status = ap_run_check_user_id(r)) != 0) || !ap_auth_type(r)) {
-                return decl_die(access_status, ap_auth_type(r)
-                           ? "check user.  No user file?"
-                           : "perform authentication. AuthType not set!", r);
-            }
-            if (((access_status = ap_run_auth_checker(r)) != 0) || !ap_auth_type(r)) {
-                return decl_die(access_status, ap_auth_type(r)
-                           ? "check access.  No groups file?"
-                           : "perform authentication. AuthType not set!", r);
-            }
-        }
-        break;
-    case SATISFY_ANY:
-        if (((access_status = ap_run_access_checker(r)) != 0) || !ap_auth_type(r)) {
-            if (!ap_some_auth_required(r)) {
-                return decl_die(access_status, ap_auth_type(r)
-                           ? "check access"
-                           : "perform authentication. AuthType not set!", r);
+    /* Skip authn/authz if the parent or prior request passed the authn/authz,
+     * and that configuration didn't change (this requires optimized _walk()
+     * functions in map_to_storage that use the same merge results given
+     * identical input.)  If the config changes, we must re-auth.
+     */
+    if (r->main && (r->main->per_dir_config == r->per_dir_config)) {
+        r->user = r->main->user;       
+        r->ap_auth_type = r->main->ap_auth_type;
+    } 
+    else if (r->prev && (r->prev->per_dir_config == r->per_dir_config)) {
+        r->user = r->prev->user;       
+        r->ap_auth_type = r->prev->ap_auth_type;
+    }
+    else
+    {
+        switch (ap_satisfies(r)) {
+        case SATISFY_ALL:
+        case SATISFY_NOSPEC:
+            if ((access_status = ap_run_access_checker(r)) != 0) {
+                return decl_die(access_status, "check access", r);
             }
-            if (((access_status = ap_run_check_user_id(r)) != 0) || !ap_auth_type(r)) {
-                return decl_die(access_status, ap_auth_type(r)
-                           ? "check user.  No user file?"
-                           : "perform authentication. AuthType not set!", r);
+            if (ap_some_auth_required(r)) {
+                if (((access_status = ap_run_check_user_id(r)) != 0) || !ap_auth_type(r)) {
+                    return decl_die(access_status, ap_auth_type(r)
+                               ? "check user.  No user file?"
+                               : "perform authentication. AuthType not set!", r);
+                }
+                if (((access_status = ap_run_auth_checker(r)) != 0) || !ap_auth_type(r)) {
+                    return decl_die(access_status, ap_auth_type(r)
+                               ? "check access.  No groups file?"
+                               : "perform authentication. AuthType not set!", r);
+                }
             }
-            if (((access_status = ap_run_auth_checker(r)) != 0) || !ap_auth_type(r)) {
-                return decl_die(access_status, ap_auth_type(r)
-                           ? "check access.  No groups file?"
-                           : "perform authentication. AuthType not set!", r);
+            break;
+        case SATISFY_ANY:
+            if (((access_status = ap_run_access_checker(r)) != 0) || !ap_auth_type(r)) {
+                if (!ap_some_auth_required(r)) {
+                    return decl_die(access_status, ap_auth_type(r)
+                               ? "check access"
+                               : "perform authentication. AuthType not set!", r);
+                }
+                if (((access_status = ap_run_check_user_id(r)) != 0) || !ap_auth_type(r)) {
+                    return decl_die(access_status, ap_auth_type(r)
+                               ? "check user.  No user file?"
+                               : "perform authentication. AuthType not set!", r);
+                }
+                if (((access_status = ap_run_auth_checker(r)) != 0) || !ap_auth_type(r)) {
+                    return decl_die(access_status, ap_auth_type(r)
+                               ? "check access.  No groups file?"
+                               : "perform authentication. AuthType not set!", r);
+                }
             }
+            break;
         }
-        break;
     }
-
     /* XXX Must make certain the ap_run_type_checker short circuits mime
      * in mod-proxy for r->proxyreq && r->parsed_uri.scheme 
      *                              && !strcmp(r->parsed_uri.scheme, "http")
@@ -792,7 +826,7 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r)
 {
     core_server_config *sconf = ap_get_module_config(r->server->module_config,
                                                      &core_module);
-    ap_conf_vector_t *per_dir_defaults = r->server->lookup_defaults;
+    ap_conf_vector_t *per_dir_defaults = r->per_dir_config;
     ap_conf_vector_t **sec_ent = (ap_conf_vector_t **) sconf->sec_dir->elts;
     int num_sec = sconf->sec_dir->nelts;
     int sec_idx;
@@ -1143,13 +1177,6 @@ AP_DECLARE(int) ap_location_walk(request_rec *r)
         apr_pool_userdata_set(cache, "ap_location_walk::cache", 
                               apr_pool_cleanup_null, r->pool);
     }
-
-    /* If the initial request creation logic failed to reset the
-     * per_dir_config, we will do so here.
-     * ### at this time, only subreq creation fails to do so.
-     */
-    if (!r->per_dir_config)
-        r->per_dir_config = r->server->lookup_defaults;
     
     /* No tricks here, there are no <Locations > to parse in this vhost.
      * We won't destroy the cache, just in case _this_ redirect is later
@@ -1386,6 +1413,14 @@ static void fill_in_sub_req_vars(request_rec *rnew, const request_rec *r,
 
     rnew->request_config = ap_create_request_config(rnew->pool);
 
+    /* Start a clean config from this subrequest's vhost.  Optimization in
+     * Location/File/Dir walks from the parent request assure that if the
+     * config blocks of the subrequest match the parent request, no merges
+     * will actually occur (and generally a minimal number of merges are 
+     * required, even if the parent and subrequest aren't quite identical.)
+     */
+    rnew->per_dir_config = r->server->lookup_defaults;
+
     rnew->htaccess       = r->htaccess;
     rnew->allowed_methods = ap_make_method_list(rnew->pool, 2);
 
@@ -1451,8 +1486,6 @@ AP_DECLARE(request_rec *) ap_sub_req_method_uri(const char *method,
     rnew = make_sub_request(r);
     fill_in_sub_req_vars(rnew, r, next_filter);
 
-    rnew->per_dir_config = r->server->lookup_defaults;
-
     /* We have to run this after fill_in_sub_req_vars, or the r->main
      * pointer won't be setup
      */
@@ -1496,8 +1529,6 @@ AP_DECLARE(request_rec *) ap_sub_req_lookup_dirent(const apr_finfo_t *dirent,
     rnew = make_sub_request(r);
     fill_in_sub_req_vars(rnew, r, next_filter);
 
-    rnew->chunked        = r->chunked;
-
     /* We have to run this after fill_in_sub_req_vars, or the r->main
      * pointer won't be setup
      */
@@ -1522,7 +1553,10 @@ AP_DECLARE(request_rec *) ap_sub_req_lookup_dirent(const apr_finfo_t *dirent,
     ap_parse_uri(rnew, rnew->uri);    /* fill in parsed_uri values */
 
 #if 0 /* XXX When this is reenabled, the cache triggers need to be set to faux
-       * dir_walk/file_walk values.
+       * dir_walk/file_walk values.  We also need to preserve the apr_stat
+       * results into the new parser, which can't happen until the new dir_walk
+       * is taught to recognize the condition, and perhaps we also tag that
+       * symlinks were tested and/or found for r->filename.  
        */
     rnew->per_dir_config = r->per_dir_config;
 
@@ -1611,12 +1645,6 @@ AP_DECLARE(request_rec *) ap_sub_req_lookup_file(const char *new_file,
     rnew = make_sub_request(r);
     fill_in_sub_req_vars(rnew, r, next_filter);
 
-    /* XXX Either this is needed for all subreq types (move into
-     * fill_in_sub_req_vars), or it isn't needed at all.  
-     * WHICH IS IT?
-     */
-    rnew->chunked        = r->chunked;
-
     /* We have to run this after fill_in_sub_req_vars, or the r->main
      * pointer won't be setup
      */
@@ -1736,20 +1764,8 @@ AP_DECLARE(request_rec *) ap_sub_req_lookup_file(const char *new_file,
          * file may not have a uri associated with it -djg
          */
         rnew->uri = apr_pstrdup(rnew->pool, "");
-
-#if 0 /* XXX When this is reenabled, the cache triggers need to be set to faux
-       * dir_walk/file_walk values.
-       */
-
-        rnew->per_dir_config = r->server->lookup_defaults;
-        res = ap_directory_walk(rnew);
-        if (!res) {
-            res = ap_file_walk(rnew);
-        }
-#endif
     }
 
-
     if ((res = ap_process_request_internal(rnew))) {
         rnew->status = res;
     }