1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * http_protocol.c --- routines which directly communicate with the client.
20 * Code originally by Rob McCool; much redone by Robert S. Thau
21 * and the Apache Software Foundation.
25 #include "apr_strings.h"
26 #include "apr_buckets.h"
28 #include "apr_signal.h"
30 #define APR_WANT_STDIO /* for sscanf */
31 #define APR_WANT_STRFUNC
32 #define APR_WANT_MEMFUNC
36 #include "util_filter.h"
37 #include "ap_config.h"
39 #include "http_config.h"
40 #include "http_core.h"
41 #include "http_protocol.h"
42 #include "http_main.h"
43 #include "http_request.h"
44 #include "http_vhost.h"
45 #include "http_log.h" /* For errors detected in basic auth common
47 #include "apr_date.h" /* For apr_date_parse_http and APR_DATE_BAD */
48 #include "util_charset.h"
49 #include "util_ebcdic.h"
50 #include "util_time.h"
62 /* New Apache routine to map status codes into array indicies
63 * e.g. 100 -> 0, 101 -> 1, 200 -> 2 ...
64 * The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
65 * and must be listed in order.
69 /* The second const triggers an assembler bug on UTS 2.1.
70 * Another workaround is to move some code out of this file into another,
71 * but this is easier. Dave Dykstra, 3/31/99
73 static const char * status_lines[RESPONSE_CODES] =
75 static const char * const status_lines[RESPONSE_CODES] =
79 "101 Switching Protocols",
85 "203 Non-Authoritative Information",
88 "206 Partial Content",
91 "300 Multiple Choices",
92 "301 Moved Permanently",
98 "307 Temporary Redirect",
101 "401 Authorization Required",
102 "402 Payment Required",
105 "405 Method Not Allowed",
106 "406 Not Acceptable",
107 "407 Proxy Authentication Required",
108 "408 Request Time-out",
111 "411 Length Required",
112 "412 Precondition Failed",
113 "413 Request Entity Too Large",
114 "414 Request-URI Too Large",
115 "415 Unsupported Media Type",
116 "416 Requested Range Not Satisfiable",
117 "417 Expectation Failed",
122 "422 Unprocessable Entity",
124 "424 Failed Dependency",
125 /* This is a hack, but it is required for ap_index_of_response
129 "426 Upgrade Required",
131 "500 Internal Server Error",
132 "501 Method Not Implemented",
134 "503 Service Temporarily Unavailable",
135 "504 Gateway Time-out",
136 "505 HTTP Version Not Supported",
137 "506 Variant Also Negotiates",
138 "507 Insufficient Storage",
145 APR_HOOK_LINK(insert_error_filter)
148 AP_IMPLEMENT_HOOK_VOID(insert_error_filter, (request_rec *r), (r))
150 /* The index of the first bit field that is used to index into a limit
151 * bitmask. M_INVALID + 1 to METHOD_NUMBER_LAST.
153 #define METHOD_NUMBER_FIRST (M_INVALID + 1)
155 /* The max method number. Method numbers are used to shift bitmasks,
156 * so this cannot exceed 63, and all bits high is equal to -1, which is a
157 * special flag, so the last bit used has index 62.
159 #define METHOD_NUMBER_LAST 62
162 AP_DECLARE(int) ap_set_keepalive(request_rec *r)
165 int wimpy = ap_find_token(r->pool,
166 apr_table_get(r->headers_out, "Connection"),
168 const char *conn = apr_table_get(r->headers_in, "Connection");
170 /* The following convoluted conditional determines whether or not
171 * the current connection should remain persistent after this response
172 * (a.k.a. HTTP Keep-Alive) and whether or not the output message
173 * body should use the HTTP/1.1 chunked transfer-coding. In English,
175 * IF we have not marked this connection as errored;
176 * and the response body has a defined length due to the status code
177 * being 304 or 204, the request method being HEAD, already
178 * having defined Content-Length or Transfer-Encoding: chunked, or
179 * the request version being HTTP/1.1 and thus capable of being set
180 * as chunked [we know the (r->chunked = 1) side-effect is ugly];
181 * and the server configuration enables keep-alive;
182 * and the server configuration has a reasonable inter-request timeout;
183 * and there is no maximum # requests or the max hasn't been reached;
184 * and the response status does not require a close;
185 * and the response generator has not already indicated close;
186 * and the client did not request non-persistence (Connection: close);
187 * and we haven't been configured to ignore the buggy twit
188 * or they're a buggy twit coming through a HTTP/1.1 proxy
189 * and the client is requesting an HTTP/1.0-style keep-alive
190 * or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
191 * and this MPM process is not already exiting
192 * THEN we can be persistent, which requires more headers be output.
194 * Note that the condition evaluation order is extremely important.
196 if ((r->connection->keepalive != AP_CONN_CLOSE)
197 && ((r->status == HTTP_NOT_MODIFIED)
198 || (r->status == HTTP_NO_CONTENT)
200 || apr_table_get(r->headers_out, "Content-Length")
201 || ap_find_last_token(r->pool,
202 apr_table_get(r->headers_out,
203 "Transfer-Encoding"),
205 || ((r->proto_num >= HTTP_VERSION(1,1))
206 && (r->chunked = 1))) /* THIS CODE IS CORRECT, see above. */
207 && r->server->keep_alive
208 && (r->server->keep_alive_timeout > 0)
209 && ((r->server->keep_alive_max == 0)
210 || (r->server->keep_alive_max > r->connection->keepalives))
211 && !ap_status_drops_connection(r->status)
213 && !ap_find_token(r->pool, conn, "close")
214 && (!apr_table_get(r->subprocess_env, "nokeepalive")
215 || apr_table_get(r->headers_in, "Via"))
216 && ((ka_sent = ap_find_token(r->pool, conn, "keep-alive"))
217 || (r->proto_num >= HTTP_VERSION(1,1)))
218 && !ap_graceful_stop_signalled()) {
219 int left = r->server->keep_alive_max - r->connection->keepalives;
221 r->connection->keepalive = AP_CONN_KEEPALIVE;
222 r->connection->keepalives++;
224 /* If they sent a Keep-Alive token, send one back */
226 if (r->server->keep_alive_max) {
227 apr_table_setn(r->headers_out, "Keep-Alive",
228 apr_psprintf(r->pool, "timeout=%d, max=%d",
229 (int)apr_time_sec(r->server->keep_alive_timeout),
233 apr_table_setn(r->headers_out, "Keep-Alive",
234 apr_psprintf(r->pool, "timeout=%d",
235 (int)apr_time_sec(r->server->keep_alive_timeout)));
237 apr_table_mergen(r->headers_out, "Connection", "Keep-Alive");
243 /* Otherwise, we need to indicate that we will be closing this
244 * connection immediately after the current response.
246 * We only really need to send "close" to HTTP/1.1 clients, but we
247 * always send it anyway, because a broken proxy may identify itself
248 * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
249 * to a HTTP/1.1 client. Better safe than sorry.
252 apr_table_mergen(r->headers_out, "Connection", "close");
255 r->connection->keepalive = AP_CONN_CLOSE;
260 AP_DECLARE(int) ap_meets_conditions(request_rec *r)
263 const char *if_match, *if_modified_since, *if_unmodified, *if_nonematch;
266 int not_modified = 0;
268 /* Check for conditional requests --- note that we only want to do
269 * this if we are successful so far and we are not processing a
270 * subrequest or an ErrorDocument.
272 * The order of the checks is important, since ETag checks are supposed
273 * to be more accurate than checks relative to the modification time.
274 * However, not all documents are guaranteed to *have* ETags, and some
275 * might have Last-Modified values w/o ETags, so this gets a little
279 if (!ap_is_HTTP_SUCCESS(r->status) || r->no_local_copy) {
283 etag = apr_table_get(r->headers_out, "ETag");
285 /* All of our comparisons must be in seconds, because that's the
286 * highest time resolution the HTTP specification allows.
288 /* XXX: we should define a "time unset" constant */
289 tmp_time = ((r->mtime != 0) ? r->mtime : apr_time_now());
290 mtime = apr_time_sec(tmp_time);
292 /* If an If-Match request-header field was given
293 * AND the field value is not "*" (meaning match anything)
294 * AND if our strong ETag does not match any entity tag in that field,
295 * respond with a status of 412 (Precondition Failed).
297 if ((if_match = apr_table_get(r->headers_in, "If-Match")) != NULL) {
298 if (if_match[0] != '*'
299 && (etag == NULL || etag[0] == 'W'
300 || !ap_find_list_item(r->pool, if_match, etag))) {
301 return HTTP_PRECONDITION_FAILED;
305 /* Else if a valid If-Unmodified-Since request-header field was given
306 * AND the requested resource has been modified since the time
307 * specified in this field, then the server MUST
308 * respond with a status of 412 (Precondition Failed).
310 if_unmodified = apr_table_get(r->headers_in, "If-Unmodified-Since");
311 if (if_unmodified != NULL) {
312 apr_time_t ius = apr_date_parse_http(if_unmodified);
314 if ((ius != APR_DATE_BAD) && (mtime > apr_time_sec(ius))) {
315 return HTTP_PRECONDITION_FAILED;
320 /* If an If-None-Match request-header field was given
321 * AND the field value is "*" (meaning match anything)
322 * OR our ETag matches any of the entity tags in that field, fail.
324 * If the request method was GET or HEAD, failure means the server
325 * SHOULD respond with a 304 (Not Modified) response.
326 * For all other request methods, failure means the server MUST
327 * respond with a status of 412 (Precondition Failed).
329 * GET or HEAD allow weak etag comparison, all other methods require
330 * strong comparison. We can only use weak if it's not a range request.
332 if_nonematch = apr_table_get(r->headers_in, "If-None-Match");
333 if (if_nonematch != NULL) {
334 if (r->method_number == M_GET) {
335 if (if_nonematch[0] == '*') {
338 else if (etag != NULL) {
339 if (apr_table_get(r->headers_in, "Range")) {
340 not_modified = etag[0] != 'W'
341 && ap_find_list_item(r->pool,
345 not_modified = ap_find_list_item(r->pool,
350 else if (if_nonematch[0] == '*'
352 && ap_find_list_item(r->pool, if_nonematch, etag))) {
353 return HTTP_PRECONDITION_FAILED;
357 /* If a valid If-Modified-Since request-header field was given
358 * AND it is a GET or HEAD request
359 * AND the requested resource has not been modified since the time
360 * specified in this field, then the server MUST
361 * respond with a status of 304 (Not Modified).
362 * A date later than the server's current request time is invalid.
364 if (r->method_number == M_GET
365 && (not_modified || !if_nonematch)
366 && (if_modified_since =
367 apr_table_get(r->headers_in,
368 "If-Modified-Since")) != NULL) {
370 apr_int64_t ims, reqtime;
372 ims_time = apr_date_parse_http(if_modified_since);
373 ims = apr_time_sec(ims_time);
374 reqtime = apr_time_sec(r->request_time);
376 not_modified = ims >= mtime && ims <= reqtime;
380 return HTTP_NOT_MODIFIED;
387 * Singleton registry of additional methods. This maps new method names
388 * such as "MYGET" to methnums, which are int offsets into bitmasks.
390 * This follows the same technique as standard M_GET, M_POST, etc. These
391 * are dynamically assigned when modules are loaded and <Limit GET MYGET>
392 * directives are processed.
394 static apr_hash_t *methods_registry = NULL;
395 static int cur_method_number = METHOD_NUMBER_FIRST;
397 /* internal function to register one method/number pair */
398 static void register_one_method(apr_pool_t *p, const char *methname,
401 int *pnum = apr_palloc(p, sizeof(*pnum));
404 apr_hash_set(methods_registry, methname, APR_HASH_KEY_STRING, pnum);
407 /* This internal function is used to clear the method registry
408 * and reset the cur_method_number counter.
410 static apr_status_t ap_method_registry_destroy(void *notused)
412 methods_registry = NULL;
413 cur_method_number = METHOD_NUMBER_FIRST;
417 AP_DECLARE(void) ap_method_registry_init(apr_pool_t *p)
419 methods_registry = apr_hash_make(p);
420 apr_pool_cleanup_register(p, NULL,
421 ap_method_registry_destroy,
422 apr_pool_cleanup_null);
424 /* put all the standard methods into the registry hash to ease the
425 mapping operations between name and number */
426 register_one_method(p, "GET", M_GET);
427 register_one_method(p, "PUT", M_PUT);
428 register_one_method(p, "POST", M_POST);
429 register_one_method(p, "DELETE", M_DELETE);
430 register_one_method(p, "CONNECT", M_CONNECT);
431 register_one_method(p, "OPTIONS", M_OPTIONS);
432 register_one_method(p, "TRACE", M_TRACE);
433 register_one_method(p, "PATCH", M_PATCH);
434 register_one_method(p, "PROPFIND", M_PROPFIND);
435 register_one_method(p, "PROPPATCH", M_PROPPATCH);
436 register_one_method(p, "MKCOL", M_MKCOL);
437 register_one_method(p, "COPY", M_COPY);
438 register_one_method(p, "MOVE", M_MOVE);
439 register_one_method(p, "LOCK", M_LOCK);
440 register_one_method(p, "UNLOCK", M_UNLOCK);
441 register_one_method(p, "VERSION-CONTROL", M_VERSION_CONTROL);
442 register_one_method(p, "CHECKOUT", M_CHECKOUT);
443 register_one_method(p, "UNCHECKOUT", M_UNCHECKOUT);
444 register_one_method(p, "CHECKIN", M_CHECKIN);
445 register_one_method(p, "UPDATE", M_UPDATE);
446 register_one_method(p, "LABEL", M_LABEL);
447 register_one_method(p, "REPORT", M_REPORT);
448 register_one_method(p, "MKWORKSPACE", M_MKWORKSPACE);
449 register_one_method(p, "MKACTIVITY", M_MKACTIVITY);
450 register_one_method(p, "BASELINE-CONTROL", M_BASELINE_CONTROL);
451 register_one_method(p, "MERGE", M_MERGE);
454 AP_DECLARE(int) ap_method_register(apr_pool_t *p, const char *methname)
458 if (methods_registry == NULL) {
459 ap_method_registry_init(p);
462 if (methname == NULL) {
466 /* Check if the method was previously registered. If it was
467 * return the associated method number.
469 methnum = (int *)apr_hash_get(methods_registry, methname,
470 APR_HASH_KEY_STRING);
474 if (cur_method_number > METHOD_NUMBER_LAST) {
475 /* The method registry has run out of dynamically
476 * assignable method numbers. Log this and return M_INVALID.
478 ap_log_perror(APLOG_MARK, APLOG_ERR, 0, p,
479 "Maximum new request methods %d reached while "
480 "registering method %s.",
481 METHOD_NUMBER_LAST, methname);
485 register_one_method(p, methname, cur_method_number);
486 return cur_method_number++;
489 #define UNKNOWN_METHOD (-1)
491 static int lookup_builtin_method(const char *method, apr_size_t len)
493 /* Note: the following code was generated by the "shilka" tool from
494 the "cocom" parsing/compilation toolkit. It is an optimized lookup
495 based on analysis of the input keywords. Postprocessing was done
496 on the shilka output, but the basic structure and analysis is
497 from there. Should new HTTP methods be added, then manual insertion
498 into this code is fine, or simply re-running the shilka tool on
499 the appropriate input. */
501 /* Note: it is also quite reasonable to just use our method_registry,
502 but I'm assuming (probably incorrectly) we want more speed here
503 (based on the optimizations the previous code was doing). */
511 return (method[1] == 'U'
513 ? M_PUT : UNKNOWN_METHOD);
515 return (method[1] == 'E'
517 ? M_GET : UNKNOWN_METHOD);
519 return UNKNOWN_METHOD;
526 return (method[1] == 'E'
529 ? M_GET : UNKNOWN_METHOD);
531 return (method[1] == 'O'
534 ? M_POST : UNKNOWN_METHOD);
536 return (method[1] == 'O'
539 ? M_MOVE : UNKNOWN_METHOD);
541 return (method[1] == 'O'
544 ? M_LOCK : UNKNOWN_METHOD);
546 return (method[1] == 'O'
549 ? M_COPY : UNKNOWN_METHOD);
551 return UNKNOWN_METHOD;
558 return (memcmp(method, "PATCH", 5) == 0
559 ? M_PATCH : UNKNOWN_METHOD);
561 return (memcmp(method, "MERGE", 5) == 0
562 ? M_MERGE : UNKNOWN_METHOD);
564 return (memcmp(method, "MKCOL", 5) == 0
565 ? M_MKCOL : UNKNOWN_METHOD);
567 return (memcmp(method, "LABEL", 5) == 0
568 ? M_LABEL : UNKNOWN_METHOD);
570 return (memcmp(method, "TRACE", 5) == 0
571 ? M_TRACE : UNKNOWN_METHOD);
573 return UNKNOWN_METHOD;
583 return (memcmp(method, "UNLOCK", 6) == 0
584 ? M_UNLOCK : UNKNOWN_METHOD);
586 return (memcmp(method, "UPDATE", 6) == 0
587 ? M_UPDATE : UNKNOWN_METHOD);
589 return UNKNOWN_METHOD;
592 return (memcmp(method, "REPORT", 6) == 0
593 ? M_REPORT : UNKNOWN_METHOD);
595 return (memcmp(method, "DELETE", 6) == 0
596 ? M_DELETE : UNKNOWN_METHOD);
598 return UNKNOWN_METHOD;
605 return (memcmp(method, "OPTIONS", 7) == 0
606 ? M_OPTIONS : UNKNOWN_METHOD);
608 return (memcmp(method, "CONNECT", 7) == 0
609 ? M_CONNECT : UNKNOWN_METHOD);
611 return (memcmp(method, "CHECKIN", 7) == 0
612 ? M_CHECKIN : UNKNOWN_METHOD);
614 return UNKNOWN_METHOD;
621 return (memcmp(method, "PROPFIND", 8) == 0
622 ? M_PROPFIND : UNKNOWN_METHOD);
624 return (memcmp(method, "CHECKOUT", 8) == 0
625 ? M_CHECKOUT : UNKNOWN_METHOD);
627 return UNKNOWN_METHOD;
631 return (memcmp(method, "PROPPATCH", 9) == 0
632 ? M_PROPPATCH : UNKNOWN_METHOD);
638 return (memcmp(method, "UNCHECKOUT", 10) == 0
639 ? M_UNCHECKOUT : UNKNOWN_METHOD);
641 return (memcmp(method, "MKACTIVITY", 10) == 0
642 ? M_MKACTIVITY : UNKNOWN_METHOD);
644 return UNKNOWN_METHOD;
648 return (memcmp(method, "MKWORKSPACE", 11) == 0
649 ? M_MKWORKSPACE : UNKNOWN_METHOD);
652 return (memcmp(method, "VERSION-CONTROL", 15) == 0
653 ? M_VERSION_CONTROL : UNKNOWN_METHOD);
656 return (memcmp(method, "BASELINE-CONTROL", 16) == 0
657 ? M_BASELINE_CONTROL : UNKNOWN_METHOD);
660 return UNKNOWN_METHOD;
666 /* Get the method number associated with the given string, assumed to
667 * contain an HTTP method. Returns M_INVALID if not recognized.
669 * This is the first step toward placing method names in a configurable
670 * list. Hopefully it (and other routines) can eventually be moved to
671 * something like a mod_http_methods.c, complete with config stuff.
673 AP_DECLARE(int) ap_method_number_of(const char *method)
675 int len = strlen(method);
676 int which = lookup_builtin_method(method, len);
678 if (which != UNKNOWN_METHOD)
681 /* check if the method has been dynamically registered */
682 if (methods_registry != NULL) {
683 int *methnum = apr_hash_get(methods_registry, method, len);
685 if (methnum != NULL) {
694 * Turn a known method number into a name.
696 AP_DECLARE(const char *) ap_method_name_of(apr_pool_t *p, int methnum)
698 apr_hash_index_t *hi = apr_hash_first(p, methods_registry);
700 /* scan through the hash table, looking for a value that matches
701 the provided method number. */
702 for (; hi; hi = apr_hash_next(hi)) {
706 apr_hash_this(hi, &key, NULL, &val);
707 if (*(int *)val == methnum)
711 /* it wasn't found in the hash */
715 /* The index is found by its offset from the x00 code of each level.
716 * Although this is fast, it will need to be replaced if some nutcase
717 * decides to define a high-numbered code before the lower numbers.
718 * If that sad event occurs, replace the code below with a linear search
719 * from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1];
721 AP_DECLARE(int) ap_index_of_response(int status)
723 static int shortcut[6] = {0, LEVEL_200, LEVEL_300, LEVEL_400,
724 LEVEL_500, RESPONSE_CODES};
727 if (status < 100) { /* Below 100 is illegal for HTTP status */
731 for (i = 0; i < 5; i++) {
734 pos = (status + shortcut[i]);
735 if (pos < shortcut[i + 1]) {
739 return LEVEL_500; /* status unknown (falls in gap) */
743 return LEVEL_500; /* 600 or above is also illegal */
746 AP_DECLARE(const char *) ap_get_status_line(int status)
748 return status_lines[ap_index_of_response(status)];
751 /* Build the Allow field-value from the request handler method mask.
752 * Note that we always allow TRACE, since it is handled below.
754 static char *make_allow(request_rec *r)
758 apr_array_header_t *allow = apr_array_make(r->pool, 10, sizeof(char *));
759 apr_hash_index_t *hi = apr_hash_first(r->pool, methods_registry);
760 /* For TRACE below */
761 core_server_config *conf =
762 ap_get_module_config(r->server->module_config, &core_module);
764 mask = r->allowed_methods->method_mask;
766 for (; hi; hi = apr_hash_next(hi)) {
770 apr_hash_this(hi, &key, NULL, &val);
771 if ((mask & (AP_METHOD_BIT << *(int *)val)) != 0) {
772 *(const char **)apr_array_push(allow) = key;
774 /* the M_GET method actually refers to two methods */
775 if (*(int *)val == M_GET)
776 *(const char **)apr_array_push(allow) = "HEAD";
780 /* TRACE is tested on a per-server basis */
781 if (conf->trace_enable != AP_TRACE_DISABLE)
782 *(const char **)apr_array_push(allow) = "TRACE";
784 list = apr_array_pstrcat(r->pool, allow, ',');
786 /* ### this is rather annoying. we should enforce registration of
788 if ((mask & (AP_METHOD_BIT << M_INVALID))
789 && (r->allowed_methods->method_list != NULL)
790 && (r->allowed_methods->method_list->nelts != 0)) {
792 char **xmethod = (char **) r->allowed_methods->method_list->elts;
795 * Append all of the elements of r->allowed_methods->method_list
797 for (i = 0; i < r->allowed_methods->method_list->nelts; ++i) {
798 list = apr_pstrcat(r->pool, list, ",", xmethod[i], NULL);
805 AP_DECLARE(int) ap_send_http_options(request_rec *r)
807 if (r->assbackwards) {
811 apr_table_setn(r->headers_out, "Allow", make_allow(r));
813 /* the request finalization will send an EOS, which will flush all
814 * the headers out (including the Allow header)
820 AP_DECLARE(void) ap_set_content_type(request_rec *r, const char *ct)
823 r->content_type = NULL;
825 else if (!r->content_type || strcmp(r->content_type, ct)) {
826 r->content_type = ct;
828 /* Insert filters requested by the AddOutputFiltersByType
829 * configuration directive. Content-type filters must be
830 * inserted after the content handlers have run because
831 * only then, do we reliably know the content-type.
833 ap_add_output_filters_by_type(r);
837 static const char *add_optional_notes(request_rec *r,
842 const char *notes, *result;
844 if ((notes = apr_table_get(r->notes, key)) == NULL) {
845 result = apr_pstrcat(r->pool, prefix, suffix, NULL);
848 result = apr_pstrcat(r->pool, prefix, notes, suffix, NULL);
854 /* construct and return the default error message for a given
855 * HTTP defined error code
857 static const char *get_canned_error_string(int status,
859 const char *location)
861 apr_pool_t *p = r->pool;
862 const char *error_notes, *h1, *s1;
865 case HTTP_MOVED_PERMANENTLY:
866 case HTTP_MOVED_TEMPORARILY:
867 case HTTP_TEMPORARY_REDIRECT:
868 return(apr_pstrcat(p,
869 "<p>The document has moved <a href=\"",
870 ap_escape_html(r->pool, location),
871 "\">here</a>.</p>\n",
874 return(apr_pstrcat(p,
875 "<p>The answer to your request is located "
877 ap_escape_html(r->pool, location),
878 "\">here</a>.</p>\n",
881 return(apr_pstrcat(p,
882 "<p>This resource is only accessible "
883 "through the proxy\n",
884 ap_escape_html(r->pool, location),
885 "<br />\nYou will need to configure "
886 "your client to use that proxy.</p>\n",
888 case HTTP_PROXY_AUTHENTICATION_REQUIRED:
889 case HTTP_UNAUTHORIZED:
890 return("<p>This server could not verify that you\n"
891 "are authorized to access the document\n"
892 "requested. Either you supplied the wrong\n"
893 "credentials (e.g., bad password), or your\n"
894 "browser doesn't understand how to supply\n"
895 "the credentials required.</p>\n");
896 case HTTP_BAD_REQUEST:
897 return(add_optional_notes(r,
898 "<p>Your browser sent a request that "
899 "this server could not understand.<br />\n",
903 return(apr_pstrcat(p,
904 "<p>You don't have permission to access ",
905 ap_escape_html(r->pool, r->uri),
906 "\non this server.</p>\n",
909 return(apr_pstrcat(p,
910 "<p>The requested URL ",
911 ap_escape_html(r->pool, r->uri),
912 " was not found on this server.</p>\n",
914 case HTTP_METHOD_NOT_ALLOWED:
915 return(apr_pstrcat(p,
916 "<p>The requested method ", r->method,
917 " is not allowed for the URL ",
918 ap_escape_html(r->pool, r->uri),
921 case HTTP_NOT_ACCEPTABLE:
923 "<p>An appropriate representation of the "
924 "requested resource ",
925 ap_escape_html(r->pool, r->uri),
926 " could not be found on this server.</p>\n",
928 return(add_optional_notes(r, s1, "variant-list", ""));
929 case HTTP_MULTIPLE_CHOICES:
930 return(add_optional_notes(r, "", "variant-list", ""));
931 case HTTP_LENGTH_REQUIRED:
933 "<p>A request of the requested method ",
935 " requires a valid Content-length.<br />\n",
937 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
938 case HTTP_PRECONDITION_FAILED:
939 return(apr_pstrcat(p,
940 "<p>The precondition on the request "
942 ap_escape_html(r->pool, r->uri),
943 " evaluated to false.</p>\n",
945 case HTTP_NOT_IMPLEMENTED:
948 ap_escape_html(r->pool, r->method), " to ",
949 ap_escape_html(r->pool, r->uri),
950 " not supported.<br />\n",
952 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
953 case HTTP_BAD_GATEWAY:
954 s1 = "<p>The proxy server received an invalid" CRLF
955 "response from an upstream server.<br />" CRLF;
956 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
957 case HTTP_VARIANT_ALSO_VARIES:
958 return(apr_pstrcat(p,
959 "<p>A variant for the requested "
961 ap_escape_html(r->pool, r->uri),
962 "\n</pre>\nis itself a negotiable resource. "
963 "This indicates a configuration error.</p>\n",
965 case HTTP_REQUEST_TIME_OUT:
966 return("<p>Server timeout waiting for the HTTP request from the client.</p>\n");
968 return(apr_pstrcat(p,
969 "<p>The requested resource<br />",
970 ap_escape_html(r->pool, r->uri),
971 "<br />\nis no longer available on this server "
972 "and there is no forwarding address.\n"
973 "Please remove all references to this "
976 case HTTP_REQUEST_ENTITY_TOO_LARGE:
977 return(apr_pstrcat(p,
978 "The requested resource<br />",
979 ap_escape_html(r->pool, r->uri), "<br />\n",
980 "does not allow request data with ",
982 " requests, or the amount of data provided in\n"
983 "the request exceeds the capacity limit.\n",
985 case HTTP_REQUEST_URI_TOO_LARGE:
986 s1 = "<p>The requested URL's length exceeds the capacity\n"
987 "limit for this server.<br />\n";
988 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
989 case HTTP_UNSUPPORTED_MEDIA_TYPE:
990 return("<p>The supplied request data is not in a format\n"
991 "acceptable for processing by this resource.</p>\n");
992 case HTTP_RANGE_NOT_SATISFIABLE:
993 return("<p>None of the range-specifier values in the Range\n"
994 "request-header field overlap the current extent\n"
995 "of the selected resource.</p>\n");
996 case HTTP_EXPECTATION_FAILED:
997 return(apr_pstrcat(p,
998 "<p>The expectation given in the Expect "
1000 "\nfield could not be met by this server.</p>\n"
1001 "<p>The client sent<pre>\n Expect: ",
1002 ap_escape_html(r->pool, apr_table_get(r->headers_in, "Expect")),
1004 "but we only allow the 100-continue "
1005 "expectation.</p>\n",
1007 case HTTP_UNPROCESSABLE_ENTITY:
1008 return("<p>The server understands the media type of the\n"
1009 "request entity, but was unable to process the\n"
1010 "contained instructions.</p>\n");
1012 return("<p>The requested resource is currently locked.\n"
1013 "The lock must be released or proper identification\n"
1014 "given before the method can be applied.</p>\n");
1015 case HTTP_FAILED_DEPENDENCY:
1016 return("<p>The method could not be performed on the resource\n"
1017 "because the requested action depended on another\n"
1018 "action and that other action failed.</p>\n");
1019 case HTTP_UPGRADE_REQUIRED:
1020 return("<p>The requested resource can only be retrieved\n"
1021 "using SSL. The server is willing to upgrade the current\n"
1022 "connection to SSL, but your client doesn't support it.\n"
1023 "Either upgrade your client, or try requesting the page\n"
1024 "using https://\n");
1025 case HTTP_INSUFFICIENT_STORAGE:
1026 return("<p>The method could not be performed on the resource\n"
1027 "because the server is unable to store the\n"
1028 "representation needed to successfully complete the\n"
1029 "request. There is insufficient free space left in\n"
1030 "your storage allocation.</p>\n");
1031 case HTTP_SERVICE_UNAVAILABLE:
1032 return("<p>The server is temporarily unable to service your\n"
1033 "request due to maintenance downtime or capacity\n"
1034 "problems. Please try again later.</p>\n");
1035 case HTTP_GATEWAY_TIME_OUT:
1036 return("<p>The proxy server did not receive a timely response\n"
1037 "from the upstream server.</p>\n");
1038 case HTTP_NOT_EXTENDED:
1039 return("<p>A mandatory extension policy in the request is not\n"
1040 "accepted by the server for this resource.</p>\n");
1041 default: /* HTTP_INTERNAL_SERVER_ERROR */
1043 * This comparison to expose error-notes could be modified to
1044 * use a configuration directive and export based on that
1045 * directive. For now "*" is used to designate an error-notes
1046 * that is totally safe for any user to see (ie lacks paths,
1047 * database passwords, etc.)
1049 if (((error_notes = apr_table_get(r->notes,
1050 "error-notes")) != NULL)
1051 && (h1 = apr_table_get(r->notes, "verbose-error-to")) != NULL
1052 && (strcmp(h1, "*") == 0)) {
1053 return(apr_pstrcat(p, error_notes, "<p />\n", NULL));
1056 return(apr_pstrcat(p,
1057 "<p>The server encountered an internal "
1059 "misconfiguration and was unable to complete\n"
1060 "your request.</p>\n"
1061 "<p>Please contact the server "
1062 "administrator,\n ",
1063 ap_escape_html(r->pool,
1064 r->server->server_admin),
1065 " and inform them of the time the "
1067 "and anything you might have done that "
1069 "caused the error.</p>\n"
1070 "<p>More information about this error "
1071 "may be available\n"
1072 "in the server error log.</p>\n",
1076 * It would be nice to give the user the information they need to
1077 * fix the problem directly since many users don't have access to
1078 * the error_log (think University sites) even though they can easily
1079 * get this error by misconfiguring an htaccess file. However, the
1080 * e error notes tend to include the real file pathname in this case,
1081 * which some people consider to be a breach of privacy. Until we
1082 * can figure out a way to remove the pathname, leave this commented.
1084 * if ((error_notes = apr_table_get(r->notes,
1085 * "error-notes")) != NULL) {
1086 * return(apr_pstrcat(p, error_notes, "<p />\n", NULL);
1095 /* We should have named this send_canned_response, since it is used for any
1096 * response that can be generated by the server from the request record.
1097 * This includes all 204 (no content), 3xx (redirect), 4xx (client error),
1098 * and 5xx (server error) messages that have not been redirected to another
1099 * handler via the ErrorDocument feature.
1101 AP_DECLARE(void) ap_send_error_response(request_rec *r, int recursive_error)
1103 int status = r->status;
1104 int idx = ap_index_of_response(status);
1105 char *custom_response;
1106 const char *location = apr_table_get(r->headers_out, "Location");
1108 /* At this point, we are starting the response over, so we have to reset
1113 /* and we need to get rid of any RESOURCE filters that might be lurking
1114 * around, thinking they are in the middle of the original request
1117 r->output_filters = r->proto_output_filters;
1119 ap_run_insert_error_filter(r);
1122 * It's possible that the Location field might be in r->err_headers_out
1123 * instead of r->headers_out; use the latter if possible, else the
1126 if (location == NULL) {
1127 location = apr_table_get(r->err_headers_out, "Location");
1129 /* We need to special-case the handling of 204 and 304 responses,
1130 * since they have specific HTTP requirements and do not include a
1131 * message body. Note that being assbackwards here is not an option.
1133 if (status == HTTP_NOT_MODIFIED) {
1134 ap_finalize_request_protocol(r);
1138 if (status == HTTP_NO_CONTENT) {
1139 ap_finalize_request_protocol(r);
1143 if (!r->assbackwards) {
1144 apr_table_t *tmp = r->headers_out;
1146 /* For all HTTP/1.x responses for which we generate the message,
1147 * we need to avoid inheriting the "normal status" header fields
1148 * that may have been set by the request handler before the
1149 * error or redirect, except for Location on external redirects.
1151 r->headers_out = r->err_headers_out;
1152 r->err_headers_out = tmp;
1153 apr_table_clear(r->err_headers_out);
1155 if (ap_is_HTTP_REDIRECT(status) || (status == HTTP_CREATED)) {
1156 if ((location != NULL) && *location) {
1157 apr_table_setn(r->headers_out, "Location", location);
1160 location = ""; /* avoids coredump when printing, below */
1164 r->content_languages = NULL;
1165 r->content_encoding = NULL;
1168 if (apr_table_get(r->subprocess_env,
1169 "suppress-error-charset") != NULL) {
1170 core_request_config *request_conf =
1171 ap_get_module_config(r->request_config, &core_module);
1172 request_conf->suppress_charset = 1; /* avoid adding default
1175 ap_set_content_type(r, "text/html");
1178 ap_set_content_type(r, "text/html; charset=iso-8859-1");
1181 if ((status == HTTP_METHOD_NOT_ALLOWED)
1182 || (status == HTTP_NOT_IMPLEMENTED)) {
1183 apr_table_setn(r->headers_out, "Allow", make_allow(r));
1186 if (r->header_only) {
1187 ap_finalize_request_protocol(r);
1192 if ((custom_response = ap_response_code_string(r, idx))) {
1194 * We have a custom response output. This should only be
1195 * a text-string to write back. But if the ErrorDocument
1196 * was a local redirect and the requested resource failed
1197 * for any reason, the custom_response will still hold the
1198 * redirect URL. We don't really want to output this URL
1199 * as a text message, so first check the custom response
1200 * string to ensure that it is a text-string (using the
1201 * same test used in ap_die(), i.e. does it start with a ").
1203 * If it's not a text string, we've got a recursive error or
1204 * an external redirect. If it's a recursive error, ap_die passes
1205 * us the second error code so we can write both, and has already
1206 * backed up to the original error. If it's an external redirect,
1207 * it hasn't happened yet; we may never know if it fails.
1209 if (custom_response[0] == '\"') {
1210 ap_rputs(custom_response + 1, r);
1211 ap_finalize_request_protocol(r);
1216 const char *title = status_lines[idx];
1219 /* Accept a status_line set by a module, but only if it begins
1220 * with the 3 digit status code
1222 if (r->status_line != NULL
1223 && strlen(r->status_line) > 4 /* long enough */
1224 && apr_isdigit(r->status_line[0])
1225 && apr_isdigit(r->status_line[1])
1226 && apr_isdigit(r->status_line[2])
1227 && apr_isspace(r->status_line[3])
1228 && apr_isalnum(r->status_line[4])) {
1229 title = r->status_line;
1232 /* folks decided they didn't want the error code in the H1 text */
1235 /* can't count on a charset filter being in place here,
1236 * so do ebcdic->ascii translation explicitly (if needed)
1239 ap_rvputs_proto_in_ascii(r,
1241 "<html><head>\n<title>", title,
1242 "</title>\n</head><body>\n<h1>", h1, "</h1>\n",
1245 ap_rvputs_proto_in_ascii(r,
1246 get_canned_error_string(status, r, location),
1249 if (recursive_error) {
1250 ap_rvputs_proto_in_ascii(r, "<p>Additionally, a ",
1251 status_lines[ap_index_of_response(recursive_error)],
1252 "\nerror was encountered while trying to use an "
1253 "ErrorDocument to handle the request.</p>\n", NULL);
1255 ap_rvputs_proto_in_ascii(r, ap_psignature("<hr>\n", r), NULL);
1256 ap_rvputs_proto_in_ascii(r, "</body></html>\n", NULL);
1258 ap_finalize_request_protocol(r);
1262 * Create a new method list with the specified number of preallocated
1265 AP_DECLARE(ap_method_list_t *) ap_make_method_list(apr_pool_t *p, int nelts)
1267 ap_method_list_t *ml;
1269 ml = (ap_method_list_t *) apr_palloc(p, sizeof(ap_method_list_t));
1270 ml->method_mask = 0;
1271 ml->method_list = apr_array_make(p, nelts, sizeof(char *));
1276 * Make a copy of a method list (primarily for subrequests that may
1277 * subsequently change it; don't want them changing the parent's, too!).
1279 AP_DECLARE(void) ap_copy_method_list(ap_method_list_t *dest,
1280 ap_method_list_t *src)
1286 dest->method_mask = src->method_mask;
1287 imethods = (char **) src->method_list->elts;
1288 for (i = 0; i < src->method_list->nelts; ++i) {
1289 omethods = (char **) apr_array_push(dest->method_list);
1290 *omethods = apr_pstrdup(dest->method_list->pool, imethods[i]);
1295 * Return true if the specified HTTP method is in the provided
1298 AP_DECLARE(int) ap_method_in_list(ap_method_list_t *l, const char *method)
1305 * If it's one of our known methods, use the shortcut and check the
1308 methnum = ap_method_number_of(method);
1309 if (methnum != M_INVALID) {
1310 return !!(l->method_mask & (AP_METHOD_BIT << methnum));
1313 * Otherwise, see if the method name is in the array or string names
1315 if ((l->method_list == NULL) || (l->method_list->nelts == 0)) {
1318 methods = (char **)l->method_list->elts;
1319 for (i = 0; i < l->method_list->nelts; ++i) {
1320 if (strcmp(method, methods[i]) == 0) {
1328 * Add the specified method to a method list (if it isn't already there).
1330 AP_DECLARE(void) ap_method_list_add(ap_method_list_t *l, const char *method)
1334 const char **xmethod;
1338 * If it's one of our known methods, use the shortcut and use the
1341 methnum = ap_method_number_of(method);
1342 l->method_mask |= (AP_METHOD_BIT << methnum);
1343 if (methnum != M_INVALID) {
1347 * Otherwise, see if the method name is in the array of string names.
1349 if (l->method_list->nelts != 0) {
1350 methods = (char **)l->method_list->elts;
1351 for (i = 0; i < l->method_list->nelts; ++i) {
1352 if (strcmp(method, methods[i]) == 0) {
1357 xmethod = (const char **) apr_array_push(l->method_list);
1362 * Remove the specified method from a method list.
1364 AP_DECLARE(void) ap_method_list_remove(ap_method_list_t *l,
1371 * If it's a known methods, either builtin or registered
1372 * by a module, use the bitmask.
1374 methnum = ap_method_number_of(method);
1375 l->method_mask |= ~(AP_METHOD_BIT << methnum);
1376 if (methnum != M_INVALID) {
1380 * Otherwise, see if the method name is in the array of string names.
1382 if (l->method_list->nelts != 0) {
1383 register int i, j, k;
1384 methods = (char **)l->method_list->elts;
1385 for (i = 0; i < l->method_list->nelts; ) {
1386 if (strcmp(method, methods[i]) == 0) {
1387 for (j = i, k = i + 1; k < l->method_list->nelts; ++j, ++k) {
1388 methods[j] = methods[k];
1390 --l->method_list->nelts;
1400 * Reset a method list to be completely empty.
1402 AP_DECLARE(void) ap_clear_method_list(ap_method_list_t *l)
1405 l->method_list->nelts = 0;