in modules/http/httpd.hpp [504:592]
const failable<request_rec*> internalRedirectRequest(const string& nr_uri, request_rec* const r) {
if (ap_is_recursion_limit_exceeded(r))
return mkfailure<request_rec*>("Redirect recursion limit exceeded", HTTP_INTERNAL_SERVER_ERROR);
// Create a new request
request_rec* nr = (request_rec*)apr_pcalloc(r->pool, sizeof(request_rec));
nr->connection = r->connection;
nr->server = r->server;
nr->pool = r->pool;
nr->method = r->method;
nr->method_number = r->method_number;
nr->allowed_methods = ap_make_method_list(nr->pool, 2);
ap_parse_uri(nr, apr_pstrdup(nr->pool, c_str(nr_uri)));
nr->parsed_uri.port_str = r->parsed_uri.port_str;
nr->parsed_uri.port = r->parsed_uri.port;
nr->filename = apr_pstrdup(nr->pool, c_str(string("/redirected:") + nr_uri));
nr->request_config = ap_create_request_config(r->pool);
nr->per_dir_config = r->server->lookup_defaults;
nr->prev = r;
r->next = nr;
nr->useragent_addr = r->useragent_addr;
nr->useragent_ip = r->useragent_ip;
// Run create request hook
ap_run_create_request(nr);
// Inherit protocol info from the original request
nr->the_request = r->the_request;
nr->allowed = r->allowed;
nr->status = r->status;
nr->assbackwards = r->assbackwards;
nr->header_only = r->header_only;
nr->protocol = r->protocol;
nr->proto_num = r->proto_num;
nr->hostname = r->hostname;
nr->request_time = r->request_time;
nr->main = r->main;
nr->headers_in = r->headers_in;
nr->headers_out = apr_table_make(r->pool, 12);
if (ap_is_HTTP_REDIRECT(nr->status)) {
const char *location = apr_table_get(r->headers_out, "Location");
if (location)
apr_table_setn(nr->headers_out, "Location", location);
}
nr->err_headers_out = r->err_headers_out;
nr->subprocess_env = r->subprocess_env;
nr->subprocess_env = internalRenameOriginalEnv(r->pool, r->subprocess_env);
nr->notes = apr_table_make(r->pool, 5);
nr->htaccess = r->htaccess;
nr->no_cache = r->no_cache;
nr->expecting_100 = r->expecting_100;
nr->no_local_copy = r->no_local_copy;
nr->read_length = r->read_length;
nr->vlist_validator = r->vlist_validator;
nr->user = r->user;
// Setup input and output filters
nr->proto_output_filters = r->proto_output_filters;
nr->proto_input_filters = r->proto_input_filters;
nr->output_filters = nr->proto_output_filters;
nr->input_filters = nr->proto_input_filters;
if (nr->main) {
ap_filter_t *f, *nextf;
nr->output_filters = r->output_filters;
f = nr->output_filters;
do {
nextf = f->next;
if (f->r == r && f->frec != ap_subreq_core_filter_handle) {
f->r = nr;
ap_remove_output_filter(f);
}
f = nextf;
} while(f && f != nr->proto_output_filters);
}
else {
nr->output_filters = nr->proto_output_filters;
}
internalUpdateFilters(nr->input_filters, r, nr);
internalUpdateFilters(nr->output_filters, r, nr);
apr_table_setn(nr->subprocess_env, "REDIRECT_STATUS", apr_itoa(r->pool, r->status));
nr->used_path_info = AP_REQ_DEFAULT_PATH_INFO;
const int rrc = ap_run_post_read_request(nr);
if (rrc != OK && rrc != DECLINED)
return mkfailure<request_rec*>("Error handling internal redirect", rrc);
return nr;
}