1 /* Copyright 1999-2005 The Apache Software Foundation or its licensors, as
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * 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"
61 /* New Apache routine to map status codes into array indicies
62 * e.g. 100 -> 0, 101 -> 1, 200 -> 2 ...
63 * The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
64 * and must be listed in order.
68 /* The second const triggers an assembler bug on UTS 2.1.
69 * Another workaround is to move some code out of this file into another,
70 * but this is easier. Dave Dykstra, 3/31/99
72 static const char * status_lines[RESPONSE_CODES] =
74 static const char * const status_lines[RESPONSE_CODES] =
78 "101 Switching Protocols",
84 "203 Non-Authoritative Information",
87 "206 Partial Content",
90 "300 Multiple Choices",
91 "301 Moved Permanently",
97 "307 Temporary Redirect",
100 "401 Authorization Required",
101 "402 Payment Required",
104 "405 Method Not Allowed",
105 "406 Not Acceptable",
106 "407 Proxy Authentication Required",
107 "408 Request Time-out",
110 "411 Length Required",
111 "412 Precondition Failed",
112 "413 Request Entity Too Large",
113 "414 Request-URI Too Large",
114 "415 Unsupported Media Type",
115 "416 Requested Range Not Satisfiable",
116 "417 Expectation Failed",
121 "422 Unprocessable Entity",
123 "424 Failed Dependency",
124 /* This is a hack, but it is required for ap_index_of_response
128 "426 Upgrade Required",
130 "500 Internal Server Error",
131 "501 Method Not Implemented",
133 "503 Service Temporarily Unavailable",
134 "504 Gateway Time-out",
135 "505 HTTP Version Not Supported",
136 "506 Variant Also Negotiates",
137 "507 Insufficient Storage",
144 APR_HOOK_LINK(insert_error_filter)
147 AP_IMPLEMENT_HOOK_VOID(insert_error_filter, (request_rec *r), (r))
149 /* The index of the first bit field that is used to index into a limit
150 * bitmask. M_INVALID + 1 to METHOD_NUMBER_LAST.
152 #define METHOD_NUMBER_FIRST (M_INVALID + 1)
154 /* The max method number. Method numbers are used to shift bitmasks,
155 * so this cannot exceed 63, and all bits high is equal to -1, which is a
156 * special flag, so the last bit used has index 62.
158 #define METHOD_NUMBER_LAST 62
161 AP_DECLARE(int) ap_set_keepalive(request_rec *r)
164 int wimpy = ap_find_token(r->pool,
165 apr_table_get(r->headers_out, "Connection"),
167 const char *conn = apr_table_get(r->headers_in, "Connection");
169 /* The following convoluted conditional determines whether or not
170 * the current connection should remain persistent after this response
171 * (a.k.a. HTTP Keep-Alive) and whether or not the output message
172 * body should use the HTTP/1.1 chunked transfer-coding. In English,
174 * IF we have not marked this connection as errored;
175 * and the response body has a defined length due to the status code
176 * being 304 or 204, the request method being HEAD, already
177 * having defined Content-Length or Transfer-Encoding: chunked, or
178 * the request version being HTTP/1.1 and thus capable of being set
179 * as chunked [we know the (r->chunked = 1) side-effect is ugly];
180 * and the server configuration enables keep-alive;
181 * and the server configuration has a reasonable inter-request timeout;
182 * and there is no maximum # requests or the max hasn't been reached;
183 * and the response status does not require a close;
184 * and the response generator has not already indicated close;
185 * and the client did not request non-persistence (Connection: close);
186 * and we haven't been configured to ignore the buggy twit
187 * or they're a buggy twit coming through a HTTP/1.1 proxy
188 * and the client is requesting an HTTP/1.0-style keep-alive
189 * or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
190 * THEN we can be persistent, which requires more headers be output.
192 * Note that the condition evaluation order is extremely important.
194 if ((r->connection->keepalive != AP_CONN_CLOSE)
195 && ((r->status == HTTP_NOT_MODIFIED)
196 || (r->status == HTTP_NO_CONTENT)
198 || apr_table_get(r->headers_out, "Content-Length")
199 || ap_find_last_token(r->pool,
200 apr_table_get(r->headers_out,
201 "Transfer-Encoding"),
203 || ((r->proto_num >= HTTP_VERSION(1,1))
204 && (r->chunked = 1))) /* THIS CODE IS CORRECT, see above. */
205 && r->server->keep_alive
206 && (r->server->keep_alive_timeout > 0)
207 && ((r->server->keep_alive_max == 0)
208 || (r->server->keep_alive_max > r->connection->keepalives))
209 && !ap_status_drops_connection(r->status)
211 && !ap_find_token(r->pool, conn, "close")
212 && (!apr_table_get(r->subprocess_env, "nokeepalive")
213 || apr_table_get(r->headers_in, "Via"))
214 && ((ka_sent = ap_find_token(r->pool, conn, "keep-alive"))
215 || (r->proto_num >= HTTP_VERSION(1,1)))) {
216 int left = r->server->keep_alive_max - r->connection->keepalives;
218 r->connection->keepalive = AP_CONN_KEEPALIVE;
219 r->connection->keepalives++;
221 /* If they sent a Keep-Alive token, send one back */
223 if (r->server->keep_alive_max) {
224 apr_table_setn(r->headers_out, "Keep-Alive",
225 apr_psprintf(r->pool, "timeout=%d, max=%d",
226 (int)apr_time_sec(r->server->keep_alive_timeout),
230 apr_table_setn(r->headers_out, "Keep-Alive",
231 apr_psprintf(r->pool, "timeout=%d",
232 (int)apr_time_sec(r->server->keep_alive_timeout)));
234 apr_table_mergen(r->headers_out, "Connection", "Keep-Alive");
240 /* Otherwise, we need to indicate that we will be closing this
241 * connection immediately after the current response.
243 * We only really need to send "close" to HTTP/1.1 clients, but we
244 * always send it anyway, because a broken proxy may identify itself
245 * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
246 * to a HTTP/1.1 client. Better safe than sorry.
249 apr_table_mergen(r->headers_out, "Connection", "close");
252 r->connection->keepalive = AP_CONN_CLOSE;
257 AP_DECLARE(int) ap_meets_conditions(request_rec *r)
260 const char *if_match, *if_modified_since, *if_unmodified, *if_nonematch;
264 /* Check for conditional requests --- note that we only want to do
265 * this if we are successful so far and we are not processing a
266 * subrequest or an ErrorDocument.
268 * The order of the checks is important, since ETag checks are supposed
269 * to be more accurate than checks relative to the modification time.
270 * However, not all documents are guaranteed to *have* ETags, and some
271 * might have Last-Modified values w/o ETags, so this gets a little
275 if (!ap_is_HTTP_SUCCESS(r->status) || r->no_local_copy) {
279 etag = apr_table_get(r->headers_out, "ETag");
281 /* All of our comparisons must be in seconds, because that's the
282 * highest time resolution the HTTP specification allows.
284 /* XXX: we should define a "time unset" constant */
285 tmp_time = ((r->mtime != 0) ? r->mtime : apr_time_now());
286 mtime = apr_time_sec(tmp_time);
288 /* If an If-Match request-header field was given
289 * AND the field value is not "*" (meaning match anything)
290 * AND if our strong ETag does not match any entity tag in that field,
291 * respond with a status of 412 (Precondition Failed).
293 if ((if_match = apr_table_get(r->headers_in, "If-Match")) != NULL) {
294 if (if_match[0] != '*'
295 && (etag == NULL || etag[0] == 'W'
296 || !ap_find_list_item(r->pool, if_match, etag))) {
297 return HTTP_PRECONDITION_FAILED;
301 /* Else if a valid If-Unmodified-Since request-header field was given
302 * AND the requested resource has been modified since the time
303 * specified in this field, then the server MUST
304 * respond with a status of 412 (Precondition Failed).
306 if_unmodified = apr_table_get(r->headers_in, "If-Unmodified-Since");
307 if (if_unmodified != NULL) {
308 apr_time_t ius = apr_date_parse_http(if_unmodified);
310 if ((ius != APR_DATE_BAD) && (mtime > apr_time_sec(ius))) {
311 return HTTP_PRECONDITION_FAILED;
316 /* If an If-None-Match request-header field was given
317 * AND the field value is "*" (meaning match anything)
318 * OR our ETag matches any of the entity tags in that field, fail.
320 * If the request method was GET or HEAD, failure means the server
321 * SHOULD respond with a 304 (Not Modified) response.
322 * For all other request methods, failure means the server MUST
323 * respond with a status of 412 (Precondition Failed).
325 * GET or HEAD allow weak etag comparison, all other methods require
326 * strong comparison. We can only use weak if it's not a range request.
328 if_nonematch = apr_table_get(r->headers_in, "If-None-Match");
329 if (if_nonematch != NULL) {
330 if (r->method_number == M_GET) {
331 if (if_nonematch[0] == '*') {
332 return HTTP_NOT_MODIFIED;
335 if (apr_table_get(r->headers_in, "Range")) {
337 && ap_find_list_item(r->pool, if_nonematch, etag)) {
338 return HTTP_NOT_MODIFIED;
341 else if (ap_strstr_c(if_nonematch, etag)) {
342 return HTTP_NOT_MODIFIED;
346 else if (if_nonematch[0] == '*'
348 && ap_find_list_item(r->pool, if_nonematch, etag))) {
349 return HTTP_PRECONDITION_FAILED;
352 /* Else if a valid If-Modified-Since request-header field was given
353 * AND it is a GET or HEAD request
354 * AND the requested resource has not been modified since the time
355 * specified in this field, then the server MUST
356 * respond with a status of 304 (Not Modified).
357 * A date later than the server's current request time is invalid.
359 else if ((r->method_number == M_GET)
360 && ((if_modified_since =
361 apr_table_get(r->headers_in,
362 "If-Modified-Since")) != NULL)) {
364 apr_int64_t ims, reqtime;
366 ims_time = apr_date_parse_http(if_modified_since);
367 ims = apr_time_sec(ims_time);
368 reqtime = apr_time_sec(r->request_time);
370 if ((ims >= mtime) && (ims <= reqtime)) {
371 return HTTP_NOT_MODIFIED;
378 * Singleton registry of additional methods. This maps new method names
379 * such as "MYGET" to methnums, which are int offsets into bitmasks.
381 * This follows the same technique as standard M_GET, M_POST, etc. These
382 * are dynamically assigned when modules are loaded and <Limit GET MYGET>
383 * directives are processed.
385 static apr_hash_t *methods_registry = NULL;
386 static int cur_method_number = METHOD_NUMBER_FIRST;
388 /* internal function to register one method/number pair */
389 static void register_one_method(apr_pool_t *p, const char *methname,
392 int *pnum = apr_palloc(p, sizeof(*pnum));
395 apr_hash_set(methods_registry, methname, APR_HASH_KEY_STRING, pnum);
398 /* This internal function is used to clear the method registry
399 * and reset the cur_method_number counter.
401 static apr_status_t ap_method_registry_destroy(void *notused)
403 methods_registry = NULL;
404 cur_method_number = METHOD_NUMBER_FIRST;
408 AP_DECLARE(void) ap_method_registry_init(apr_pool_t *p)
410 methods_registry = apr_hash_make(p);
411 apr_pool_cleanup_register(p, NULL,
412 ap_method_registry_destroy,
413 apr_pool_cleanup_null);
415 /* put all the standard methods into the registry hash to ease the
416 mapping operations between name and number */
417 register_one_method(p, "GET", M_GET);
418 register_one_method(p, "PUT", M_PUT);
419 register_one_method(p, "POST", M_POST);
420 register_one_method(p, "DELETE", M_DELETE);
421 register_one_method(p, "CONNECT", M_CONNECT);
422 register_one_method(p, "OPTIONS", M_OPTIONS);
423 register_one_method(p, "TRACE", M_TRACE);
424 register_one_method(p, "PATCH", M_PATCH);
425 register_one_method(p, "PROPFIND", M_PROPFIND);
426 register_one_method(p, "PROPPATCH", M_PROPPATCH);
427 register_one_method(p, "MKCOL", M_MKCOL);
428 register_one_method(p, "COPY", M_COPY);
429 register_one_method(p, "MOVE", M_MOVE);
430 register_one_method(p, "LOCK", M_LOCK);
431 register_one_method(p, "UNLOCK", M_UNLOCK);
432 register_one_method(p, "VERSION-CONTROL", M_VERSION_CONTROL);
433 register_one_method(p, "CHECKOUT", M_CHECKOUT);
434 register_one_method(p, "UNCHECKOUT", M_UNCHECKOUT);
435 register_one_method(p, "CHECKIN", M_CHECKIN);
436 register_one_method(p, "UPDATE", M_UPDATE);
437 register_one_method(p, "LABEL", M_LABEL);
438 register_one_method(p, "REPORT", M_REPORT);
439 register_one_method(p, "MKWORKSPACE", M_MKWORKSPACE);
440 register_one_method(p, "MKACTIVITY", M_MKACTIVITY);
441 register_one_method(p, "BASELINE-CONTROL", M_BASELINE_CONTROL);
442 register_one_method(p, "MERGE", M_MERGE);
445 AP_DECLARE(int) ap_method_register(apr_pool_t *p, const char *methname)
449 if (methods_registry == NULL) {
450 ap_method_registry_init(p);
453 if (methname == NULL) {
457 /* Check if the method was previously registered. If it was
458 * return the associated method number.
460 methnum = (int *)apr_hash_get(methods_registry, methname,
461 APR_HASH_KEY_STRING);
465 if (cur_method_number > METHOD_NUMBER_LAST) {
466 /* The method registry has run out of dynamically
467 * assignable method numbers. Log this and return M_INVALID.
469 ap_log_perror(APLOG_MARK, APLOG_ERR, 0, p,
470 "Maximum new request methods %d reached while "
471 "registering method %s.",
472 METHOD_NUMBER_LAST, methname);
476 register_one_method(p, methname, cur_method_number);
477 return cur_method_number++;
480 #define UNKNOWN_METHOD (-1)
482 static int lookup_builtin_method(const char *method, apr_size_t len)
484 /* Note: the following code was generated by the "shilka" tool from
485 the "cocom" parsing/compilation toolkit. It is an optimized lookup
486 based on analysis of the input keywords. Postprocessing was done
487 on the shilka output, but the basic structure and analysis is
488 from there. Should new HTTP methods be added, then manual insertion
489 into this code is fine, or simply re-running the shilka tool on
490 the appropriate input. */
492 /* Note: it is also quite reasonable to just use our method_registry,
493 but I'm assuming (probably incorrectly) we want more speed here
494 (based on the optimizations the previous code was doing). */
502 return (method[1] == 'U'
504 ? M_PUT : UNKNOWN_METHOD);
506 return (method[1] == 'E'
508 ? M_GET : UNKNOWN_METHOD);
510 return UNKNOWN_METHOD;
517 return (method[1] == 'E'
520 ? M_GET : UNKNOWN_METHOD);
522 return (method[1] == 'O'
525 ? M_POST : UNKNOWN_METHOD);
527 return (method[1] == 'O'
530 ? M_MOVE : UNKNOWN_METHOD);
532 return (method[1] == 'O'
535 ? M_LOCK : UNKNOWN_METHOD);
537 return (method[1] == 'O'
540 ? M_COPY : UNKNOWN_METHOD);
542 return UNKNOWN_METHOD;
549 return (memcmp(method, "PATCH", 5) == 0
550 ? M_PATCH : UNKNOWN_METHOD);
552 return (memcmp(method, "MERGE", 5) == 0
553 ? M_MERGE : UNKNOWN_METHOD);
555 return (memcmp(method, "MKCOL", 5) == 0
556 ? M_MKCOL : UNKNOWN_METHOD);
558 return (memcmp(method, "LABEL", 5) == 0
559 ? M_LABEL : UNKNOWN_METHOD);
561 return (memcmp(method, "TRACE", 5) == 0
562 ? M_TRACE : UNKNOWN_METHOD);
564 return UNKNOWN_METHOD;
574 return (memcmp(method, "UNLOCK", 6) == 0
575 ? M_UNLOCK : UNKNOWN_METHOD);
577 return (memcmp(method, "UPDATE", 6) == 0
578 ? M_UPDATE : UNKNOWN_METHOD);
580 return UNKNOWN_METHOD;
583 return (memcmp(method, "REPORT", 6) == 0
584 ? M_REPORT : UNKNOWN_METHOD);
586 return (memcmp(method, "DELETE", 6) == 0
587 ? M_DELETE : UNKNOWN_METHOD);
589 return UNKNOWN_METHOD;
596 return (memcmp(method, "OPTIONS", 7) == 0
597 ? M_OPTIONS : UNKNOWN_METHOD);
599 return (memcmp(method, "CONNECT", 7) == 0
600 ? M_CONNECT : UNKNOWN_METHOD);
602 return (memcmp(method, "CHECKIN", 7) == 0
603 ? M_CHECKIN : UNKNOWN_METHOD);
605 return UNKNOWN_METHOD;
612 return (memcmp(method, "PROPFIND", 8) == 0
613 ? M_PROPFIND : UNKNOWN_METHOD);
615 return (memcmp(method, "CHECKOUT", 8) == 0
616 ? M_CHECKOUT : UNKNOWN_METHOD);
618 return UNKNOWN_METHOD;
622 return (memcmp(method, "PROPPATCH", 9) == 0
623 ? M_PROPPATCH : UNKNOWN_METHOD);
629 return (memcmp(method, "UNCHECKOUT", 10) == 0
630 ? M_UNCHECKOUT : UNKNOWN_METHOD);
632 return (memcmp(method, "MKACTIVITY", 10) == 0
633 ? M_MKACTIVITY : UNKNOWN_METHOD);
635 return UNKNOWN_METHOD;
639 return (memcmp(method, "MKWORKSPACE", 11) == 0
640 ? M_MKWORKSPACE : UNKNOWN_METHOD);
643 return (memcmp(method, "VERSION-CONTROL", 15) == 0
644 ? M_VERSION_CONTROL : UNKNOWN_METHOD);
647 return (memcmp(method, "BASELINE-CONTROL", 16) == 0
648 ? M_BASELINE_CONTROL : UNKNOWN_METHOD);
651 return UNKNOWN_METHOD;
657 /* Get the method number associated with the given string, assumed to
658 * contain an HTTP method. Returns M_INVALID if not recognized.
660 * This is the first step toward placing method names in a configurable
661 * list. Hopefully it (and other routines) can eventually be moved to
662 * something like a mod_http_methods.c, complete with config stuff.
664 AP_DECLARE(int) ap_method_number_of(const char *method)
666 int len = strlen(method);
667 int which = lookup_builtin_method(method, len);
669 if (which != UNKNOWN_METHOD)
672 /* check if the method has been dynamically registered */
673 if (methods_registry != NULL) {
674 int *methnum = apr_hash_get(methods_registry, method, len);
676 if (methnum != NULL) {
685 * Turn a known method number into a name.
687 AP_DECLARE(const char *) ap_method_name_of(apr_pool_t *p, int methnum)
689 apr_hash_index_t *hi = apr_hash_first(p, methods_registry);
691 /* scan through the hash table, looking for a value that matches
692 the provided method number. */
693 for (; hi; hi = apr_hash_next(hi)) {
697 apr_hash_this(hi, &key, NULL, &val);
698 if (*(int *)val == methnum)
702 /* it wasn't found in the hash */
706 /* The index is found by its offset from the x00 code of each level.
707 * Although this is fast, it will need to be replaced if some nutcase
708 * decides to define a high-numbered code before the lower numbers.
709 * If that sad event occurs, replace the code below with a linear search
710 * from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1];
712 AP_DECLARE(int) ap_index_of_response(int status)
714 static int shortcut[6] = {0, LEVEL_200, LEVEL_300, LEVEL_400,
715 LEVEL_500, RESPONSE_CODES};
718 if (status < 100) { /* Below 100 is illegal for HTTP status */
722 for (i = 0; i < 5; i++) {
725 pos = (status + shortcut[i]);
726 if (pos < shortcut[i + 1]) {
730 return LEVEL_500; /* status unknown (falls in gap) */
734 return LEVEL_500; /* 600 or above is also illegal */
737 AP_DECLARE(const char *) ap_get_status_line(int status)
739 return status_lines[ap_index_of_response(status)];
742 /* Build the Allow field-value from the request handler method mask.
743 * Note that we always allow TRACE, since it is handled below.
745 static char *make_allow(request_rec *r)
749 apr_array_header_t *allow = apr_array_make(r->pool, 10, sizeof(char *));
750 apr_hash_index_t *hi = apr_hash_first(r->pool, methods_registry);
752 mask = r->allowed_methods->method_mask;
754 for (; hi; hi = apr_hash_next(hi)) {
758 apr_hash_this(hi, &key, NULL, &val);
759 if ((mask & (AP_METHOD_BIT << *(int *)val)) != 0) {
760 *(const char **)apr_array_push(allow) = key;
762 /* the M_GET method actually refers to two methods */
763 if (*(int *)val == M_GET)
764 *(const char **)apr_array_push(allow) = "HEAD";
768 /* TRACE is always allowed */
769 *(const char **)apr_array_push(allow) = "TRACE";
771 list = apr_array_pstrcat(r->pool, allow, ',');
773 /* ### this is rather annoying. we should enforce registration of
775 if ((mask & (AP_METHOD_BIT << M_INVALID))
776 && (r->allowed_methods->method_list != NULL)
777 && (r->allowed_methods->method_list->nelts != 0)) {
779 char **xmethod = (char **) r->allowed_methods->method_list->elts;
782 * Append all of the elements of r->allowed_methods->method_list
784 for (i = 0; i < r->allowed_methods->method_list->nelts; ++i) {
785 list = apr_pstrcat(r->pool, list, ",", xmethod[i], NULL);
792 AP_DECLARE(int) ap_send_http_options(request_rec *r)
794 if (r->assbackwards) {
798 apr_table_setn(r->headers_out, "Allow", make_allow(r));
800 /* the request finalization will send an EOS, which will flush all
801 * the headers out (including the Allow header)
807 AP_DECLARE(void) ap_set_content_type(request_rec *r, const char *ct)
810 r->content_type = NULL;
812 else if (!r->content_type || strcmp(r->content_type, ct)) {
813 r->content_type = ct;
815 /* Insert filters requested by the AddOutputFiltersByType
816 * configuration directive. Content-type filters must be
817 * inserted after the content handlers have run because
818 * only then, do we reliably know the content-type.
820 ap_add_output_filters_by_type(r);
824 static const char *add_optional_notes(request_rec *r,
829 const char *notes, *result;
831 if ((notes = apr_table_get(r->notes, key)) == NULL) {
832 result = apr_pstrcat(r->pool, prefix, suffix, NULL);
835 result = apr_pstrcat(r->pool, prefix, notes, suffix, NULL);
841 /* construct and return the default error message for a given
842 * HTTP defined error code
844 static const char *get_canned_error_string(int status,
846 const char *location)
848 apr_pool_t *p = r->pool;
849 const char *error_notes, *h1, *s1;
852 case HTTP_MOVED_PERMANENTLY:
853 case HTTP_MOVED_TEMPORARILY:
854 case HTTP_TEMPORARY_REDIRECT:
855 return(apr_pstrcat(p,
856 "<p>The document has moved <a href=\"",
857 ap_escape_html(r->pool, location),
858 "\">here</a>.</p>\n",
861 return(apr_pstrcat(p,
862 "<p>The answer to your request is located "
864 ap_escape_html(r->pool, location),
865 "\">here</a>.</p>\n",
868 return(apr_pstrcat(p,
869 "<p>This resource is only accessible "
870 "through the proxy\n",
871 ap_escape_html(r->pool, location),
872 "<br />\nYou will need to configure "
873 "your client to use that proxy.</p>\n",
875 case HTTP_PROXY_AUTHENTICATION_REQUIRED:
876 case HTTP_UNAUTHORIZED:
877 return("<p>This server could not verify that you\n"
878 "are authorized to access the document\n"
879 "requested. Either you supplied the wrong\n"
880 "credentials (e.g., bad password), or your\n"
881 "browser doesn't understand how to supply\n"
882 "the credentials required.</p>\n");
883 case HTTP_BAD_REQUEST:
884 return(add_optional_notes(r,
885 "<p>Your browser sent a request that "
886 "this server could not understand.<br />\n",
890 return(apr_pstrcat(p,
891 "<p>You don't have permission to access ",
892 ap_escape_html(r->pool, r->uri),
893 "\non this server.</p>\n",
896 return(apr_pstrcat(p,
897 "<p>The requested URL ",
898 ap_escape_html(r->pool, r->uri),
899 " was not found on this server.</p>\n",
901 case HTTP_METHOD_NOT_ALLOWED:
902 return(apr_pstrcat(p,
903 "<p>The requested method ", r->method,
904 " is not allowed for the URL ",
905 ap_escape_html(r->pool, r->uri),
908 case HTTP_NOT_ACCEPTABLE:
910 "<p>An appropriate representation of the "
911 "requested resource ",
912 ap_escape_html(r->pool, r->uri),
913 " could not be found on this server.</p>\n",
915 return(add_optional_notes(r, s1, "variant-list", ""));
916 case HTTP_MULTIPLE_CHOICES:
917 return(add_optional_notes(r, "", "variant-list", ""));
918 case HTTP_LENGTH_REQUIRED:
920 "<p>A request of the requested method ",
922 " requires a valid Content-length.<br />\n",
924 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
925 case HTTP_PRECONDITION_FAILED:
926 return(apr_pstrcat(p,
927 "<p>The precondition on the request "
929 ap_escape_html(r->pool, r->uri),
930 " evaluated to false.</p>\n",
932 case HTTP_NOT_IMPLEMENTED:
935 ap_escape_html(r->pool, r->method), " to ",
936 ap_escape_html(r->pool, r->uri),
937 " not supported.<br />\n",
939 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
940 case HTTP_BAD_GATEWAY:
941 s1 = "<p>The proxy server received an invalid" CRLF
942 "response from an upstream server.<br />" CRLF;
943 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
944 case HTTP_VARIANT_ALSO_VARIES:
945 return(apr_pstrcat(p,
946 "<p>A variant for the requested "
948 ap_escape_html(r->pool, r->uri),
949 "\n</pre>\nis itself a negotiable resource. "
950 "This indicates a configuration error.</p>\n",
952 case HTTP_REQUEST_TIME_OUT:
953 return("<p>Server timeout waiting for the HTTP request from the client.</p>\n");
955 return(apr_pstrcat(p,
956 "<p>The requested resource<br />",
957 ap_escape_html(r->pool, r->uri),
958 "<br />\nis no longer available on this server "
959 "and there is no forwarding address.\n"
960 "Please remove all references to this "
963 case HTTP_REQUEST_ENTITY_TOO_LARGE:
964 return(apr_pstrcat(p,
965 "The requested resource<br />",
966 ap_escape_html(r->pool, r->uri), "<br />\n",
967 "does not allow request data with ",
969 " requests, or the amount of data provided in\n"
970 "the request exceeds the capacity limit.\n",
972 case HTTP_REQUEST_URI_TOO_LARGE:
973 s1 = "<p>The requested URL's length exceeds the capacity\n"
974 "limit for this server.<br />\n";
975 return(add_optional_notes(r, s1, "error-notes", "</p>\n"));
976 case HTTP_UNSUPPORTED_MEDIA_TYPE:
977 return("<p>The supplied request data is not in a format\n"
978 "acceptable for processing by this resource.</p>\n");
979 case HTTP_RANGE_NOT_SATISFIABLE:
980 return("<p>None of the range-specifier values in the Range\n"
981 "request-header field overlap the current extent\n"
982 "of the selected resource.</p>\n");
983 case HTTP_EXPECTATION_FAILED:
984 return(apr_pstrcat(p,
985 "<p>The expectation given in the Expect "
987 "\nfield could not be met by this server.</p>\n"
988 "<p>The client sent<pre>\n Expect: ",
989 apr_table_get(r->headers_in, "Expect"),
991 "but we only allow the 100-continue "
992 "expectation.</p>\n",
994 case HTTP_UNPROCESSABLE_ENTITY:
995 return("<p>The server understands the media type of the\n"
996 "request entity, but was unable to process the\n"
997 "contained instructions.</p>\n");
999 return("<p>The requested resource is currently locked.\n"
1000 "The lock must be released or proper identification\n"
1001 "given before the method can be applied.</p>\n");
1002 case HTTP_FAILED_DEPENDENCY:
1003 return("<p>The method could not be performed on the resource\n"
1004 "because the requested action depended on another\n"
1005 "action and that other action failed.</p>\n");
1006 case HTTP_UPGRADE_REQUIRED:
1007 return("<p>The requested resource can only be retrieved\n"
1008 "using SSL. The server is willing to upgrade the current\n"
1009 "connection to SSL, but your client doesn't support it.\n"
1010 "Either upgrade your client, or try requesting the page\n"
1011 "using https://\n");
1012 case HTTP_INSUFFICIENT_STORAGE:
1013 return("<p>The method could not be performed on the resource\n"
1014 "because the server is unable to store the\n"
1015 "representation needed to successfully complete the\n"
1016 "request. There is insufficient free space left in\n"
1017 "your storage allocation.</p>\n");
1018 case HTTP_SERVICE_UNAVAILABLE:
1019 return("<p>The server is temporarily unable to service your\n"
1020 "request due to maintenance downtime or capacity\n"
1021 "problems. Please try again later.</p>\n");
1022 case HTTP_GATEWAY_TIME_OUT:
1023 return("<p>The proxy server did not receive a timely response\n"
1024 "from the upstream server.</p>\n");
1025 case HTTP_NOT_EXTENDED:
1026 return("<p>A mandatory extension policy in the request is not\n"
1027 "accepted by the server for this resource.</p>\n");
1028 default: /* HTTP_INTERNAL_SERVER_ERROR */
1030 * This comparison to expose error-notes could be modified to
1031 * use a configuration directive and export based on that
1032 * directive. For now "*" is used to designate an error-notes
1033 * that is totally safe for any user to see (ie lacks paths,
1034 * database passwords, etc.)
1036 if (((error_notes = apr_table_get(r->notes,
1037 "error-notes")) != NULL)
1038 && (h1 = apr_table_get(r->notes, "verbose-error-to")) != NULL
1039 && (strcmp(h1, "*") == 0)) {
1040 return(apr_pstrcat(p, error_notes, "<p />\n", NULL));
1043 return(apr_pstrcat(p,
1044 "<p>The server encountered an internal "
1046 "misconfiguration and was unable to complete\n"
1047 "your request.</p>\n"
1048 "<p>Please contact the server "
1049 "administrator,\n ",
1050 ap_escape_html(r->pool,
1051 r->server->server_admin),
1052 " and inform them of the time the "
1054 "and anything you might have done that "
1056 "caused the error.</p>\n"
1057 "<p>More information about this error "
1058 "may be available\n"
1059 "in the server error log.</p>\n",
1063 * It would be nice to give the user the information they need to
1064 * fix the problem directly since many users don't have access to
1065 * the error_log (think University sites) even though they can easily
1066 * get this error by misconfiguring an htaccess file. However, the
1067 * e error notes tend to include the real file pathname in this case,
1068 * which some people consider to be a breach of privacy. Until we
1069 * can figure out a way to remove the pathname, leave this commented.
1071 * if ((error_notes = apr_table_get(r->notes,
1072 * "error-notes")) != NULL) {
1073 * return(apr_pstrcat(p, error_notes, "<p />\n", NULL);
1082 /* We should have named this send_canned_response, since it is used for any
1083 * response that can be generated by the server from the request record.
1084 * This includes all 204 (no content), 3xx (redirect), 4xx (client error),
1085 * and 5xx (server error) messages that have not been redirected to another
1086 * handler via the ErrorDocument feature.
1088 AP_DECLARE(void) ap_send_error_response(request_rec *r, int recursive_error)
1090 int status = r->status;
1091 int idx = ap_index_of_response(status);
1092 char *custom_response;
1093 const char *location = apr_table_get(r->headers_out, "Location");
1095 /* At this point, we are starting the response over, so we have to reset
1100 /* and we need to get rid of any RESOURCE filters that might be lurking
1101 * around, thinking they are in the middle of the original request
1104 r->output_filters = r->proto_output_filters;
1106 ap_run_insert_error_filter(r);
1109 * It's possible that the Location field might be in r->err_headers_out
1110 * instead of r->headers_out; use the latter if possible, else the
1113 if (location == NULL) {
1114 location = apr_table_get(r->err_headers_out, "Location");
1116 /* We need to special-case the handling of 204 and 304 responses,
1117 * since they have specific HTTP requirements and do not include a
1118 * message body. Note that being assbackwards here is not an option.
1120 if (status == HTTP_NOT_MODIFIED) {
1121 ap_finalize_request_protocol(r);
1125 if (status == HTTP_NO_CONTENT) {
1126 ap_finalize_request_protocol(r);
1130 if (!r->assbackwards) {
1131 apr_table_t *tmp = r->headers_out;
1133 /* For all HTTP/1.x responses for which we generate the message,
1134 * we need to avoid inheriting the "normal status" header fields
1135 * that may have been set by the request handler before the
1136 * error or redirect, except for Location on external redirects.
1138 r->headers_out = r->err_headers_out;
1139 r->err_headers_out = tmp;
1140 apr_table_clear(r->err_headers_out);
1142 if (ap_is_HTTP_REDIRECT(status) || (status == HTTP_CREATED)) {
1143 if ((location != NULL) && *location) {
1144 apr_table_setn(r->headers_out, "Location", location);
1147 location = ""; /* avoids coredump when printing, below */
1151 r->content_languages = NULL;
1152 r->content_encoding = NULL;
1154 ap_set_content_type(r, "text/html; charset=iso-8859-1");
1156 if ((status == HTTP_METHOD_NOT_ALLOWED)
1157 || (status == HTTP_NOT_IMPLEMENTED)) {
1158 apr_table_setn(r->headers_out, "Allow", make_allow(r));
1161 if (r->header_only) {
1162 ap_finalize_request_protocol(r);
1167 if ((custom_response = ap_response_code_string(r, idx))) {
1169 * We have a custom response output. This should only be
1170 * a text-string to write back. But if the ErrorDocument
1171 * was a local redirect and the requested resource failed
1172 * for any reason, the custom_response will still hold the
1173 * redirect URL. We don't really want to output this URL
1174 * as a text message, so first check the custom response
1175 * string to ensure that it is a text-string (using the
1176 * same test used in ap_die(), i.e. does it start with a ").
1178 * If it's not a text string, we've got a recursive error or
1179 * an external redirect. If it's a recursive error, ap_die passes
1180 * us the second error code so we can write both, and has already
1181 * backed up to the original error. If it's an external redirect,
1182 * it hasn't happened yet; we may never know if it fails.
1184 if (custom_response[0] == '\"') {
1185 ap_rputs(custom_response + 1, r);
1186 ap_finalize_request_protocol(r);
1191 const char *title = status_lines[idx];
1194 /* Accept a status_line set by a module, but only if it begins
1195 * with the 3 digit status code
1197 if (r->status_line != NULL
1198 && strlen(r->status_line) > 4 /* long enough */
1199 && apr_isdigit(r->status_line[0])
1200 && apr_isdigit(r->status_line[1])
1201 && apr_isdigit(r->status_line[2])
1202 && apr_isspace(r->status_line[3])
1203 && apr_isalnum(r->status_line[4])) {
1204 title = r->status_line;
1207 /* folks decided they didn't want the error code in the H1 text */
1210 /* can't count on a charset filter being in place here,
1211 * so do ebcdic->ascii translation explicitly (if needed)
1214 ap_rvputs_proto_in_ascii(r,
1216 "<html><head>\n<title>", title,
1217 "</title>\n</head><body>\n<h1>", h1, "</h1>\n",
1220 ap_rvputs_proto_in_ascii(r,
1221 get_canned_error_string(status, r, location),
1224 if (recursive_error) {
1225 ap_rvputs_proto_in_ascii(r, "<p>Additionally, a ",
1226 status_lines[ap_index_of_response(recursive_error)],
1227 "\nerror was encountered while trying to use an "
1228 "ErrorDocument to handle the request.</p>\n", NULL);
1230 ap_rvputs_proto_in_ascii(r, ap_psignature("<hr>\n", r), NULL);
1231 ap_rvputs_proto_in_ascii(r, "</body></html>\n", NULL);
1233 ap_finalize_request_protocol(r);
1237 * Create a new method list with the specified number of preallocated
1240 AP_DECLARE(ap_method_list_t *) ap_make_method_list(apr_pool_t *p, int nelts)
1242 ap_method_list_t *ml;
1244 ml = (ap_method_list_t *) apr_palloc(p, sizeof(ap_method_list_t));
1245 ml->method_mask = 0;
1246 ml->method_list = apr_array_make(p, nelts, sizeof(char *));
1251 * Make a copy of a method list (primarily for subrequests that may
1252 * subsequently change it; don't want them changing the parent's, too!).
1254 AP_DECLARE(void) ap_copy_method_list(ap_method_list_t *dest,
1255 ap_method_list_t *src)
1261 dest->method_mask = src->method_mask;
1262 imethods = (char **) src->method_list->elts;
1263 for (i = 0; i < src->method_list->nelts; ++i) {
1264 omethods = (char **) apr_array_push(dest->method_list);
1265 *omethods = apr_pstrdup(dest->method_list->pool, imethods[i]);
1270 * Invoke a callback routine for each method in the specified list.
1272 AP_DECLARE_NONSTD(void) ap_method_list_do(int (*comp) (void *urec,
1276 const ap_method_list_t *ml, ...)
1280 ap_method_list_vdo(comp, rec, ml, vp);
1284 AP_DECLARE(void) ap_method_list_vdo(int (*comp) (void *mrec,
1287 void *rec, const ap_method_list_t *ml,
1294 * Return true if the specified HTTP method is in the provided
1297 AP_DECLARE(int) ap_method_in_list(ap_method_list_t *l, const char *method)
1304 * If it's one of our known methods, use the shortcut and check the
1307 methnum = ap_method_number_of(method);
1308 if (methnum != M_INVALID) {
1309 return !!(l->method_mask & (AP_METHOD_BIT << methnum));
1312 * Otherwise, see if the method name is in the array or string names
1314 if ((l->method_list == NULL) || (l->method_list->nelts == 0)) {
1317 methods = (char **)l->method_list->elts;
1318 for (i = 0; i < l->method_list->nelts; ++i) {
1319 if (strcmp(method, methods[i]) == 0) {
1327 * Add the specified method to a method list (if it isn't already there).
1329 AP_DECLARE(void) ap_method_list_add(ap_method_list_t *l, const char *method)
1333 const char **xmethod;
1337 * If it's one of our known methods, use the shortcut and use the
1340 methnum = ap_method_number_of(method);
1341 l->method_mask |= (AP_METHOD_BIT << methnum);
1342 if (methnum != M_INVALID) {
1346 * Otherwise, see if the method name is in the array of string names.
1348 if (l->method_list->nelts != 0) {
1349 methods = (char **)l->method_list->elts;
1350 for (i = 0; i < l->method_list->nelts; ++i) {
1351 if (strcmp(method, methods[i]) == 0) {
1356 xmethod = (const char **) apr_array_push(l->method_list);
1361 * Remove the specified method from a method list.
1363 AP_DECLARE(void) ap_method_list_remove(ap_method_list_t *l,
1370 * If it's a known methods, either builtin or registered
1371 * by a module, use the bitmask.
1373 methnum = ap_method_number_of(method);
1374 l->method_mask |= ~(AP_METHOD_BIT << methnum);
1375 if (methnum != M_INVALID) {
1379 * Otherwise, see if the method name is in the array of string names.
1381 if (l->method_list->nelts != 0) {
1382 register int i, j, k;
1383 methods = (char **)l->method_list->elts;
1384 for (i = 0; i < l->method_list->nelts; ) {
1385 if (strcmp(method, methods[i]) == 0) {
1386 for (j = i, k = i + 1; k < l->method_list->nelts; ++j, ++k) {
1387 methods[j] = methods[k];
1389 --l->method_list->nelts;
1399 * Reset a method list to be completely empty.
1401 AP_DECLARE(void) ap_clear_method_list(ap_method_list_t *l)
1404 l->method_list->nelts = 0;