📄 http_protocol.c
字号:
"misconfiguration and was unable to complete\n" "your request.</p>\n" "<p>Please contact the server " "administrator,\n ", ap_escape_html(r->pool, r->server->server_admin), " and inform them of the time the " "error occurred,\n" "and anything you might have done that " "may have\n" "caused the error.</p>\n" "<p>More information about this error " "may be available\n" "in the server error log.</p>\n", NULL)); } /* * It would be nice to give the user the information they need to * fix the problem directly since many users don't have access to * the error_log (think University sites) even though they can easily * get this error by misconfiguring an htaccess file. However, the * e error notes tend to include the real file pathname in this case, * which some people consider to be a breach of privacy. Until we * can figure out a way to remove the pathname, leave this commented. * * if ((error_notes = apr_table_get(r->notes, * "error-notes")) != NULL) { * return(apr_pstrcat(p, error_notes, "<p />\n", NULL); * } * else { * return ""; * } */ }}/* We should have named this send_canned_response, since it is used for any * response that can be generated by the server from the request record. * This includes all 204 (no content), 3xx (redirect), 4xx (client error), * and 5xx (server error) messages that have not been redirected to another * handler via the ErrorDocument feature. */AP_DECLARE(void) ap_send_error_response(request_rec *r, int recursive_error){ int status = r->status; int idx = ap_index_of_response(status); char *custom_response; const char *location = apr_table_get(r->headers_out, "Location"); /* At this point, we are starting the response over, so we have to reset * this value. */ r->eos_sent = 0; /* and we need to get rid of any RESOURCE filters that might be lurking * around, thinking they are in the middle of the original request */ r->output_filters = r->proto_output_filters; ap_run_insert_error_filter(r); /* * It's possible that the Location field might be in r->err_headers_out * instead of r->headers_out; use the latter if possible, else the * former. */ if (location == NULL) { location = apr_table_get(r->err_headers_out, "Location"); } /* We need to special-case the handling of 204 and 304 responses, * since they have specific HTTP requirements and do not include a * message body. Note that being assbackwards here is not an option. */ if (status == HTTP_NOT_MODIFIED) { ap_finalize_request_protocol(r); return; } if (status == HTTP_NO_CONTENT) { ap_finalize_request_protocol(r); return; } if (!r->assbackwards) { apr_table_t *tmp = r->headers_out; /* For all HTTP/1.x responses for which we generate the message, * we need to avoid inheriting the "normal status" header fields * that may have been set by the request handler before the * error or redirect, except for Location on external redirects. */ r->headers_out = r->err_headers_out; r->err_headers_out = tmp; apr_table_clear(r->err_headers_out); if (ap_is_HTTP_REDIRECT(status) || (status == HTTP_CREATED)) { if ((location != NULL) && *location) { apr_table_setn(r->headers_out, "Location", location); } else { location = ""; /* avoids coredump when printing, below */ } } r->content_languages = NULL; r->content_encoding = NULL; r->clength = 0; if (apr_table_get(r->subprocess_env, "suppress-error-charset") != NULL) { core_request_config *request_conf = ap_get_module_config(r->request_config, &core_module); request_conf->suppress_charset = 1; /* avoid adding default * charset later */ ap_set_content_type(r, "text/html"); } else { ap_set_content_type(r, "text/html; charset=iso-8859-1"); } if ((status == HTTP_METHOD_NOT_ALLOWED) || (status == HTTP_NOT_IMPLEMENTED)) { apr_table_setn(r->headers_out, "Allow", make_allow(r)); } if (r->header_only) { ap_finalize_request_protocol(r); return; } } if ((custom_response = ap_response_code_string(r, idx))) { /* * We have a custom response output. This should only be * a text-string to write back. But if the ErrorDocument * was a local redirect and the requested resource failed * for any reason, the custom_response will still hold the * redirect URL. We don't really want to output this URL * as a text message, so first check the custom response * string to ensure that it is a text-string (using the * same test used in ap_die(), i.e. does it start with a "). * * If it's not a text string, we've got a recursive error or * an external redirect. If it's a recursive error, ap_die passes * us the second error code so we can write both, and has already * backed up to the original error. If it's an external redirect, * it hasn't happened yet; we may never know if it fails. */ if (custom_response[0] == '\"') { ap_rputs(custom_response + 1, r); ap_finalize_request_protocol(r); return; } } { const char *title = status_lines[idx]; const char *h1; /* Accept a status_line set by a module, but only if it begins * with the 3 digit status code */ if (r->status_line != NULL && strlen(r->status_line) > 4 /* long enough */ && apr_isdigit(r->status_line[0]) && apr_isdigit(r->status_line[1]) && apr_isdigit(r->status_line[2]) && apr_isspace(r->status_line[3]) && apr_isalnum(r->status_line[4])) { title = r->status_line; } /* folks decided they didn't want the error code in the H1 text */ h1 = &title[4]; /* can't count on a charset filter being in place here, * so do ebcdic->ascii translation explicitly (if needed) */ ap_rvputs_proto_in_ascii(r, DOCTYPE_HTML_2_0 "<html><head>\n<title>", title, "</title>\n</head><body>\n<h1>", h1, "</h1>\n", NULL); ap_rvputs_proto_in_ascii(r, get_canned_error_string(status, r, location), NULL); if (recursive_error) { ap_rvputs_proto_in_ascii(r, "<p>Additionally, a ", status_lines[ap_index_of_response(recursive_error)], "\nerror was encountered while trying to use an " "ErrorDocument to handle the request.</p>\n", NULL); } ap_rvputs_proto_in_ascii(r, ap_psignature("<hr>\n", r), NULL); ap_rvputs_proto_in_ascii(r, "</body></html>\n", NULL); } ap_finalize_request_protocol(r);}/* * Create a new method list with the specified number of preallocated * extension slots. */AP_DECLARE(ap_method_list_t *) ap_make_method_list(apr_pool_t *p, int nelts){ ap_method_list_t *ml; ml = (ap_method_list_t *) apr_palloc(p, sizeof(ap_method_list_t)); ml->method_mask = 0; ml->method_list = apr_array_make(p, nelts, sizeof(char *)); return ml;}/* * Make a copy of a method list (primarily for subrequests that may * subsequently change it; don't want them changing the parent's, too!). */AP_DECLARE(void) ap_copy_method_list(ap_method_list_t *dest, ap_method_list_t *src){ int i; char **imethods; char **omethods; dest->method_mask = src->method_mask; imethods = (char **) src->method_list->elts; for (i = 0; i < src->method_list->nelts; ++i) { omethods = (char **) apr_array_push(dest->method_list); *omethods = apr_pstrdup(dest->method_list->pool, imethods[i]); }}/* * Return true if the specified HTTP method is in the provided * method list. */AP_DECLARE(int) ap_method_in_list(ap_method_list_t *l, const char *method){ int methnum; int i; char **methods; /* * If it's one of our known methods, use the shortcut and check the * bitmask. */ methnum = ap_method_number_of(method); if (methnum != M_INVALID) { return !!(l->method_mask & (AP_METHOD_BIT << methnum)); } /* * Otherwise, see if the method name is in the array or string names */ if ((l->method_list == NULL) || (l->method_list->nelts == 0)) { return 0; } methods = (char **)l->method_list->elts; for (i = 0; i < l->method_list->nelts; ++i) { if (strcmp(method, methods[i]) == 0) { return 1; } } return 0;}/* * Add the specified method to a method list (if it isn't already there). */AP_DECLARE(void) ap_method_list_add(ap_method_list_t *l, const char *method){ int methnum; int i; const char **xmethod; char **methods; /* * If it's one of our known methods, use the shortcut and use the * bitmask. */ methnum = ap_method_number_of(method); l->method_mask |= (AP_METHOD_BIT << methnum); if (methnum != M_INVALID) { return; } /* * Otherwise, see if the method name is in the array of string names. */ if (l->method_list->nelts != 0) { methods = (char **)l->method_list->elts; for (i = 0; i < l->method_list->nelts; ++i) { if (strcmp(method, methods[i]) == 0) { return; } } } xmethod = (const char **) apr_array_push(l->method_list); *xmethod = method;}/* * Remove the specified method from a method list. */AP_DECLARE(void) ap_method_list_remove(ap_method_list_t *l, const char *method){ int methnum; char **methods; /* * If it's a known methods, either builtin or registered * by a module, use the bitmask. */ methnum = ap_method_number_of(method); l->method_mask |= ~(AP_METHOD_BIT << methnum); if (methnum != M_INVALID) { return; } /* * Otherwise, see if the method name is in the array of string names. */ if (l->method_list->nelts != 0) { register int i, j, k; methods = (char **)l->method_list->elts; for (i = 0; i < l->method_list->nelts; ) { if (strcmp(method, methods[i]) == 0) { for (j = i, k = i + 1; k < l->method_list->nelts; ++j, ++k) { methods[j] = methods[k]; } --l->method_list->nelts; } else { ++i; } } }}/* * Reset a method list to be completely empty. */AP_DECLARE(void) ap_clear_method_list(ap_method_list_t *l){ l->method_mask = 0; l->method_list->nelts = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -