request.c
来自「Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相」· C语言 代码 · 共 1,783 行 · 第 1/5 页
C
1,783 行
/* Merge our cache->dir_conf_merged construct with the r->per_dir_configs, * and note the end result to (potentially) skip this step next time. */ if (now_merged) { r->per_dir_config = ap_merge_per_dir_configs(r->pool, r->per_dir_config, now_merged); } cache->per_dir_result = r->per_dir_config; return OK;}/***************************************************************** * * The sub_request mechanism. * * Fns to look up a relative URI from, e.g., a map file or SSI document. * These do all access checks, etc., but don't actually run the transaction * ... use run_sub_req below for that. Also, be sure to use destroy_sub_req * as appropriate if you're likely to be creating more than a few of these. * (An early Apache version didn't destroy the sub_reqs used in directory * indexing. The result, when indexing a directory with 800-odd files in * it, was massively excessive storage allocation). * * Note more manipulation of protocol-specific vars in the request * structure... */static request_rec *make_sub_request(const request_rec *r, ap_filter_t *next_filter){ apr_pool_t *rrp; request_rec *rnew; apr_pool_create(&rrp, r->pool); apr_pool_tag(rrp, "subrequest"); rnew = apr_pcalloc(rrp, sizeof(request_rec)); rnew->pool = rrp; rnew->hostname = r->hostname; rnew->request_time = r->request_time; rnew->connection = r->connection; rnew->server = r->server; 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); /* make a copy of the allowed-methods list */ ap_copy_method_list(rnew->allowed_methods, r->allowed_methods); /* start with the same set of output filters */ if (next_filter) { /* while there are no input filters for a subrequest, we will * try to insert some, so if we don't have valid data, the code * will seg fault. */ rnew->input_filters = r->input_filters; rnew->proto_input_filters = r->proto_input_filters; rnew->output_filters = next_filter; rnew->proto_output_filters = r->proto_output_filters; ap_add_output_filter_handle(ap_subreq_core_filter_handle, NULL, rnew, rnew->connection); } else { /* If NULL - we are expecting to be internal_fast_redirect'ed * to this subrequest - or this request will never be invoked. * Ignore the original request filter stack entirely, and * drill the input and output stacks back to the connection. */ rnew->proto_input_filters = r->proto_input_filters; rnew->proto_output_filters = r->proto_output_filters; rnew->input_filters = r->proto_input_filters; rnew->output_filters = r->proto_output_filters; } /* no input filters for a subrequest */ ap_set_sub_req_protocol(rnew, r); /* We have to run this after we fill in sub req vars, * or the r->main pointer won't be setup */ ap_run_create_request(rnew); return rnew;}AP_CORE_DECLARE_NONSTD(apr_status_t) ap_sub_req_output_filter(ap_filter_t *f, apr_bucket_brigade *bb){ apr_bucket *e = APR_BRIGADE_LAST(bb); if (APR_BUCKET_IS_EOS(e)) { apr_bucket_delete(e); } if (!APR_BRIGADE_EMPTY(bb)) { return ap_pass_brigade(f->next, bb); } return APR_SUCCESS;}AP_DECLARE(int) ap_some_auth_required(request_rec *r){ /* Is there a require line configured for the type of *this* req? */ const apr_array_header_t *reqs_arr = ap_requires(r); require_line *reqs; int i; if (!reqs_arr) { return 0; } reqs = (require_line *) reqs_arr->elts; for (i = 0; i < reqs_arr->nelts; ++i) { if (reqs[i].method_mask & (AP_METHOD_BIT << r->method_number)) { return 1; } } return 0;}AP_DECLARE(request_rec *) ap_sub_req_method_uri(const char *method, const char *new_uri, const request_rec *r, ap_filter_t *next_filter){ request_rec *rnew; int res; char *udir; rnew = make_sub_request(r, next_filter); /* would be nicer to pass "method" to ap_set_sub_req_protocol */ rnew->method = method; rnew->method_number = ap_method_number_of(method); if (new_uri[0] == '/') { ap_parse_uri(rnew, new_uri); } else { udir = ap_make_dirstr_parent(rnew->pool, r->uri); udir = ap_escape_uri(rnew->pool, udir); /* re-escape it */ ap_parse_uri(rnew, ap_make_full_path(rnew->pool, udir, new_uri)); } /* We cannot return NULL without violating the API. So just turn this * subrequest into a 500 to indicate the failure. */ if (ap_is_recursion_limit_exceeded(r)) { rnew->status = HTTP_INTERNAL_SERVER_ERROR; return rnew; } /* lookup_uri * If the content can be served by the quick_handler, we can * safely bypass request_internal processing. */ res = ap_run_quick_handler(rnew, 1); if (res != OK) { if ((res = ap_process_request_internal(rnew))) { rnew->status = res; } } return rnew;}AP_DECLARE(request_rec *) ap_sub_req_lookup_uri(const char *new_uri, const request_rec *r, ap_filter_t *next_filter){ return ap_sub_req_method_uri("GET", new_uri, r, next_filter);}AP_DECLARE(request_rec *) ap_sub_req_lookup_dirent(const apr_finfo_t *dirent, const request_rec *r, int subtype, ap_filter_t *next_filter){ request_rec *rnew; int res; char *fdir; char *udir; rnew = make_sub_request(r, next_filter); /* Special case: we are looking at a relative lookup in the same directory. * This is 100% safe, since dirent->name just came from the filesystem. */ if (r->path_info && *r->path_info) { /* strip path_info off the end of the uri to keep it in sync * with r->filename, which has already been stripped by directory_walk, * merge the dirent->name, and then, if the caller wants us to remerge * the original path info, do so. Note we never fix the path_info back * to r->filename, since dir_walk would do so (but we don't expect it * to happen in the usual cases) */ udir = apr_pstrdup(rnew->pool, r->uri); udir[ap_find_path_info(udir, r->path_info)] = '\0'; udir = ap_make_dirstr_parent(rnew->pool, udir); rnew->uri = ap_make_full_path(rnew->pool, udir, dirent->name); if (subtype == AP_SUBREQ_MERGE_ARGS) { rnew->uri = ap_make_full_path(rnew->pool, rnew->uri, r->path_info + 1); rnew->path_info = apr_pstrdup(rnew->pool, r->path_info); } rnew->uri = ap_escape_uri(rnew->pool, rnew->uri); } else { udir = ap_make_dirstr_parent(rnew->pool, r->uri); rnew->uri = ap_escape_uri(rnew->pool, ap_make_full_path(rnew->pool, udir, dirent->name)); } fdir = ap_make_dirstr_parent(rnew->pool, r->filename); rnew->filename = ap_make_full_path(rnew->pool, fdir, dirent->name); if (r->canonical_filename == r->filename) { rnew->canonical_filename = rnew->filename; } /* XXX This is now less relevant; we will do a full location walk * these days for this case. Preserve the apr_stat results, and * perhaps we also tag that symlinks were tested and/or found for * r->filename. */ rnew->per_dir_config = r->server->lookup_defaults; if ((dirent->valid & APR_FINFO_MIN) != APR_FINFO_MIN) { /* * apr_dir_read isn't very complete on this platform, so * we need another apr_lstat (or simply apr_stat if we allow * all symlinks here.) If this is an APR_LNK that resolves * to an APR_DIR, then we will rerun everything anyways... * this should be safe. */ apr_status_t rv; if (ap_allow_options(rnew) & OPT_SYM_LINKS) { if (((rv = apr_stat(&rnew->finfo, rnew->filename, APR_FINFO_MIN, rnew->pool)) != APR_SUCCESS) && (rv != APR_INCOMPLETE)) { rnew->finfo.filetype = 0; } } else { if (((rv = apr_lstat(&rnew->finfo, rnew->filename, APR_FINFO_MIN, rnew->pool)) != APR_SUCCESS) && (rv != APR_INCOMPLETE)) { rnew->finfo.filetype = 0; } } } else { memcpy(&rnew->finfo, dirent, sizeof(apr_finfo_t)); } if (rnew->finfo.filetype == APR_LNK) { /* * Resolve this symlink. We should tie this back to dir_walk's cache */ if ((res = resolve_symlink(rnew->filename, &rnew->finfo, ap_allow_options(rnew), rnew->pool)) != OK) { rnew->status = res; return rnew; } } if (rnew->finfo.filetype == APR_DIR) { /* ap_make_full_path overallocated the buffers * by one character to help us out here. */ strcpy(rnew->filename + strlen(rnew->filename), "/"); if (!rnew->path_info || !*rnew->path_info) { strcpy(rnew->uri + strlen(rnew->uri ), "/"); } } /* fill in parsed_uri values */ if (r->args && *r->args && (subtype == AP_SUBREQ_MERGE_ARGS)) { ap_parse_uri(rnew, apr_pstrcat(r->pool, rnew->uri, "?", r->args, NULL)); } else { ap_parse_uri(rnew, rnew->uri); } /* We cannot return NULL without violating the API. So just turn this * subrequest into a 500. */ if (ap_is_recursion_limit_exceeded(r)) { rnew->status = HTTP_INTERNAL_SERVER_ERROR; return rnew; } if ((res = ap_process_request_internal(rnew))) { rnew->status = res; } return rnew;}AP_DECLARE(request_rec *) ap_sub_req_lookup_file(const char *new_file, const request_rec *r, ap_filter_t *next_filter){ request_rec *rnew; int res; char *fdir; apr_size_t fdirlen; rnew = make_sub_request(r, next_filter); fdir = ap_make_dirstr_parent(rnew->pool, r->filename); fdirlen = strlen(fdir); /* Translate r->filename, if it was canonical, it stays canonical */ if (r->canonical_filename == r->filename) { rnew->canonical_filename = (char*)(1); } if (apr_filepath_merge(&rnew->filename, fdir, new_file, APR_FILEPATH_TRUENAME, rnew->pool) != APR_SUCCESS) { rnew->status = HTTP_FORBIDDEN; return rnew; } if (rnew->canonical_filename) { rnew->canonical_filename = rnew->filename; } /* * Check for a special case... if there are no '/' characters in new_file * at all, and the path was the same, then we
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?