http_protocol.c revision a771451a437726073089edb17a7c9ed32f85fb1a
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * contributor license agreements. See the NOTICE file distributed with
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * this work for additional information regarding copyright ownership.
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * The ASF licenses this file to You under the Apache License, Version 2.0
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * (the "License"); you may not use this file except in compliance with
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the License. You may obtain a copy of the License at
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Unless required by applicable law or agreed to in writing, software
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * distributed under the License is distributed on an "AS IS" BASIS,
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * See the License for the specific language governing permissions and
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * limitations under the License.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * http_protocol.c --- routines which directly communicate with the client.
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * Code originally by Rob McCool; much redone by Robert S. Thau
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * and the Apache Software Foundation.
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#include "http_log.h" /* For errors detected in basic auth common
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * support code... */
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding#include "apr_date.h" /* For apr_date_parse_http and APR_DATE_BAD */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* New Apache routine to map status codes into array indicies
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * e.g. 100 -> 0, 101 -> 1, 200 -> 2 ...
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * and must be listed in order.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char * const status_lines[RESPONSE_CODES] =
b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44crbb "100 Continue",
b6055b7832a0e4d0818416252fff5925aaebae4brbb "101 Switching Protocols",
b4c8a80f7dbfc9b56dbe03bdc28f0b5eb5f23697rbb "102 Processing",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "201 Created",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "202 Accepted",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "203 Non-Authoritative Information",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "204 No Content",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "205 Reset Content",
ee4a7424a2d75f6c2296459ce31bc4e02b923bcdrbb "206 Partial Content",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "207 Multi-Status",
d41217398f0e1031adbb6f5bd37f45737c805deftrawick "300 Multiple Choices",
d41217398f0e1031adbb6f5bd37f45737c805deftrawick "301 Moved Permanently",
d41217398f0e1031adbb6f5bd37f45737c805deftrawick "302 Found",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "303 See Other",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "304 Not Modified",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "305 Use Proxy",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "306 unused",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "307 Temporary Redirect",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "400 Bad Request",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "401 Authorization Required",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "402 Payment Required",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "403 Forbidden",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "404 Not Found",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "405 Method Not Allowed",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "406 Not Acceptable",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "407 Proxy Authentication Required",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "408 Request Time-out",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "409 Conflict",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "410 Gone",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "411 Length Required",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "412 Precondition Failed",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "413 Request Entity Too Large",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "414 Request-URI Too Large",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "415 Unsupported Media Type",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "416 Requested Range Not Satisfiable",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "417 Expectation Failed",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "418 unused",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "419 unused",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "420 unused",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "421 unused",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "422 Unprocessable Entity",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "423 Locked",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "424 Failed Dependency",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* This is a hack, but it is required for ap_index_of_response
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * to work with 426.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "425 No code",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "426 Upgrade Required",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "500 Internal Server Error",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "501 Method Not Implemented",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "502 Bad Gateway",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "503 Service Temporarily Unavailable",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "504 Gateway Time-out",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "505 HTTP Version Not Supported",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "506 Variant Also Negotiates",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "507 Insufficient Storage",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "508 unused",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "509 unused",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "510 Not Extended"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingAP_IMPLEMENT_HOOK_VOID(insert_error_filter, (request_rec *r), (r))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* The index of the first bit field that is used to index into a limit
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * bitmask. M_INVALID + 1 to METHOD_NUMBER_LAST.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* The max method number. Method numbers are used to shift bitmasks,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * so this cannot exceed 63, and all bits high is equal to -1, which is a
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * special flag, so the last bit used has index 62.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic int is_mpm_running(void)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int left = r->server->keep_alive_max - r->connection->keepalives;
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb const char *conn = apr_table_get(r->headers_in, "Connection");
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* The following convoluted conditional determines whether or not
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the current connection should remain persistent after this response
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * (a.k.a. HTTP Keep-Alive) and whether or not the output message
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * body should use the HTTP/1.1 chunked transfer-coding. In English,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * IF we have not marked this connection as errored;
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb * and the response body has a defined length due to the status code
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * being 304 or 204, the request method being HEAD, already
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * having defined Content-Length or Transfer-Encoding: chunked, or
a952e0c6ece342d88f2bc04e20dcfc563398eed3rbb * the request version being HTTP/1.1 and thus capable of being set
ec727afb817df0e5202135278c0d2902923cc980stoddard * as chunked [we know the (r->chunked = 1) side-effect is ugly];
ec727afb817df0e5202135278c0d2902923cc980stoddard * and the server configuration enables keep-alive;
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb * and the server configuration has a reasonable inter-request timeout;
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb * and there is no maximum # requests or the max hasn't been reached;
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb * and the response status does not require a close;
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb * and the response generator has not already indicated close;
fa4e5ac791dd1c84df616b28d4ee9751efe9c64frbb * and the client did not request non-persistence (Connection: close);
fa4e5ac791dd1c84df616b28d4ee9751efe9c64frbb * and we haven't been configured to ignore the buggy twit
fa4e5ac791dd1c84df616b28d4ee9751efe9c64frbb * or they're a buggy twit coming through a HTTP/1.1 proxy
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * and the client is requesting an HTTP/1.0-style keep-alive
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * and this MPM process is not already exiting
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * THEN we can be persistent, which requires more headers be output.
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb * Note that the condition evaluation order is extremely important.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm "Transfer-Encoding"),
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb && (r->chunked = 1))) /* THIS CODE IS CORRECT, see above. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding && (!apr_table_get(r->subprocess_env, "nokeepalive")
2b484455736f4c30447aa852764f53282cbeb5ddrbb && ((ka_sent = ap_find_token(r->pool, conn, "keep-alive"))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* If they sent a Keep-Alive token, send one back */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (int)apr_time_sec(r->server->keep_alive_timeout)));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_table_mergen(r->headers_out, "Connection", "Keep-Alive");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Otherwise, we need to indicate that we will be closing this
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * connection immediately after the current response.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * We only really need to send "close" to HTTP/1.1 clients, but we
061c3874622b67beff724876b9bd1b1f291f2eaafielding * always send it anyway, because a broken proxy may identify itself
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
95ed69df3d43a7d2758720bad8950f07587bdeb9bjh * to a HTTP/1.1 client. Better safe than sorry.
2b484455736f4c30447aa852764f53282cbeb5ddrbb apr_table_mergen(r->headers_out, "Connection", "close");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * If we had previously been a keepalive connection and this
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * is the last one, then bump up the number of keepalives
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * we've had
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm const char *etag;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm const char *if_match, *if_modified_since, *if_unmodified, *if_nonematch;
ec727afb817df0e5202135278c0d2902923cc980stoddard /* Check for conditional requests --- note that we only want to do
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * this if we are successful so far and we are not processing a
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * subrequest or an ErrorDocument.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * The order of the checks is important, since ETag checks are supposed
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * to be more accurate than checks relative to the modification time.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * However, not all documents are guaranteed to *have* ETags, and some
0942697a9b5de44865676345a3828741c827efe6rbb * might have Last-Modified values w/o ETags, so this gets a little
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * complicated.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (!ap_is_HTTP_SUCCESS(r->status) || r->no_local_copy) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* All of our comparisons must be in seconds, because that's the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * highest time resolution the HTTP specification allows.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* XXX: we should define a "time unset" constant */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding tmp_time = ((r->mtime != 0) ? r->mtime : apr_time_now());
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* If an If-Match request-header field was given
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * AND the field value is not "*" (meaning match anything)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * AND if our strong ETag does not match any entity tag in that field,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * respond with a status of 412 (Precondition Failed).
ab5581cc78e9d865b0a6ab1404c53347b3276968rbb if ((if_match = apr_table_get(r->headers_in, "If-Match")) != NULL) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* Else if a valid If-Unmodified-Since request-header field was given
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * AND the requested resource has been modified since the time
3597d6b10c88c252f156fe8061b659a38dea38c2rbb * specified in this field, then the server MUST
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * respond with a status of 412 (Precondition Failed).
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if_unmodified = apr_table_get(r->headers_in, "If-Unmodified-Since");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_time_t ius = apr_date_parse_http(if_unmodified);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((ius != APR_DATE_BAD) && (mtime > apr_time_sec(ius))) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* If an If-None-Match request-header field was given
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * AND the field value is "*" (meaning match anything)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * OR our ETag matches any of the entity tags in that field, fail.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * If the request method was GET or HEAD, failure means the server
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * SHOULD respond with a 304 (Not Modified) response.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * For all other request methods, failure means the server MUST
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * respond with a status of 412 (Precondition Failed).
2b484455736f4c30447aa852764f53282cbeb5ddrbb * GET or HEAD allow weak etag comparison, all other methods require
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * strong comparison. We can only use weak if it's not a range request.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if_nonematch = apr_table_get(r->headers_in, "If-None-Match");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding && ap_find_list_item(r->pool, if_nonematch, etag))) {
6db54801798f6021bb464de7b3fdcc9dc3150f7bdgaudet /* If a valid If-Modified-Since request-header field was given
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * AND it is a GET or HEAD request
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe * AND the requested resource has not been modified since the time
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe * specified in this field, then the server MUST
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe * respond with a status of 304 (Not Modified).
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * A date later than the server's current request time is invalid.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Singleton registry of additional methods. This maps new method names
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * such as "MYGET" to methnums, which are int offsets into bitmasks.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * This follows the same technique as standard M_GET, M_POST, etc. These
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * are dynamically assigned when modules are loaded and <Limit GET MYGET>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * directives are processed.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* internal function to register one method/number pair */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void register_one_method(apr_pool_t *p, const char *methname,
b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44crbb apr_hash_set(methods_registry, methname, APR_HASH_KEY_STRING, pnum);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm/* This internal function is used to clear the method registry
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * and reset the cur_method_number counter.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic apr_status_t ap_method_registry_destroy(void *notused)
a1de70bda57b72d8cc6b47ea744e0973ed424f56wroweAP_DECLARE(void) ap_method_registry_init(apr_pool_t *p)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* put all the standard methods into the registry hash to ease the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding mapping operations between name and number */
3597d6b10c88c252f156fe8061b659a38dea38c2rbb register_one_method(p, "VERSION-CONTROL", M_VERSION_CONTROL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding register_one_method(p, "MKWORKSPACE", M_MKWORKSPACE);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding register_one_method(p, "MKACTIVITY", M_MKACTIVITY);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding register_one_method(p, "BASELINE-CONTROL", M_BASELINE_CONTROL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingAP_DECLARE(int) ap_method_register(apr_pool_t *p, const char *methname)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Check if the method was previously registered. If it was
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * return the associated method number.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm methnum = (int *)apr_hash_get(methods_registry, methname,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* The method registry has run out of dynamically
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * assignable method numbers. Log this and return M_INVALID.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm "Maximum new request methods %d reached while "
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm "registering method %s.",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding register_one_method(p, methname, cur_method_number);
061c3874622b67beff724876b9bd1b1f291f2eaafieldingstatic int lookup_builtin_method(const char *method, apr_size_t len)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Note: the following code was generated by the "shilka" tool from
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding the "cocom" parsing/compilation toolkit. It is an optimized lookup
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding based on analysis of the input keywords. Postprocessing was done
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding on the shilka output, but the basic structure and analysis is
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding from there. Should new HTTP methods be added, then manual insertion
0942697a9b5de44865676345a3828741c827efe6rbb into this code is fine, or simply re-running the shilka tool on
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm the appropriate input. */
ab5581cc78e9d865b0a6ab1404c53347b3276968rbb /* Note: it is also quite reasonable to just use our method_registry,
ab5581cc78e9d865b0a6ab1404c53347b3276968rbb but I'm assuming (probably incorrectly) we want more speed here
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (based on the optimizations the previous code was doing). */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm switch (method[0])
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm switch (method[0])
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb switch (method[0])
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* NOTREACHED */
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbb/* Get the method number associated with the given string, assumed to
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * contain an HTTP method. Returns M_INVALID if not recognized.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * This is the first step toward placing method names in a configurable
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * list. Hopefully it (and other routines) can eventually be moved to
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * something like a mod_http_methods.c, complete with config stuff.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmAP_DECLARE(int) ap_method_number_of(const char *method)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* check if the method has been dynamically registered */
b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44crbb int *methnum = apr_hash_get(methods_registry, method, len);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Turn a known method number into a name.
2cfdca5be0c69f65b43a888d6d3da846489b8fa5rbbAP_DECLARE(const char *) ap_method_name_of(apr_pool_t *p, int methnum)
a952e0c6ece342d88f2bc04e20dcfc563398eed3rbb apr_hash_index_t *hi = apr_hash_first(p, methods_registry);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* scan through the hash table, looking for a value that matches
2b484455736f4c30447aa852764f53282cbeb5ddrbb the provided method number. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const void *key;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* it wasn't found in the hash */
b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44crbb/* The index is found by its offset from the x00 code of each level.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Although this is fast, it will need to be replaced if some nutcase
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * decides to define a high-numbered code before the lower numbers.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * If that sad event occurs, replace the code below with a linear search
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1];
int i, pos;
return LEVEL_500;
return pos;
char *list;
const void *key;
void *val;
return list;
if (r->assbackwards) {
return DECLINED;
return OK;
if (!ct) {
const char *prefix,
const char *key,
const char *suffix)
return result;
request_rec *r,
const char *location)
switch (status) {
case HTTP_MOVED_PERMANENTLY:
case HTTP_MOVED_TEMPORARILY:
case HTTP_TEMPORARY_REDIRECT:
return(apr_pstrcat(p,
NULL));
case HTTP_SEE_OTHER:
return(apr_pstrcat(p,
NULL));
case HTTP_USE_PROXY:
return(apr_pstrcat(p,
NULL));
case HTTP_UNAUTHORIZED:
case HTTP_BAD_REQUEST:
return(add_optional_notes(r,
case HTTP_FORBIDDEN:
return(apr_pstrcat(p,
NULL));
case HTTP_NOT_FOUND:
return(apr_pstrcat(p,
NULL));
case HTTP_METHOD_NOT_ALLOWED:
return(apr_pstrcat(p,
NULL));
case HTTP_NOT_ACCEPTABLE:
NULL);
case HTTP_MULTIPLE_CHOICES:
case HTTP_LENGTH_REQUIRED:
NULL);
case HTTP_PRECONDITION_FAILED:
return(apr_pstrcat(p,
NULL));
case HTTP_NOT_IMPLEMENTED:
NULL);
case HTTP_BAD_GATEWAY:
case HTTP_VARIANT_ALSO_VARIES:
return(apr_pstrcat(p,
NULL));
case HTTP_REQUEST_TIME_OUT:
case HTTP_GONE:
return(apr_pstrcat(p,
NULL));
return(apr_pstrcat(p,
NULL));
case HTTP_EXPECTATION_FAILED:
return(apr_pstrcat(p,
NULL));
case HTTP_LOCKED:
case HTTP_FAILED_DEPENDENCY:
case HTTP_UPGRADE_REQUIRED:
"using https://\n");
case HTTP_SERVICE_UNAVAILABLE:
case HTTP_GATEWAY_TIME_OUT:
case HTTP_NOT_EXTENDED:
return(apr_pstrcat(p,
NULL));
char *custom_response;
r->eos_sent = 0;
if (!r->assbackwards) {
r->clength = 0;
if (r->header_only) {
const char *h1;
if (r->status_line) {
char *end;
NULL);
NULL);
if (recursive_error) {
return ml;
char **imethods;
char **omethods;
int methnum;
char **methods;
int methnum;
const char **xmethod;
char **methods;
const char *method)
int methnum;
char **methods;
l->method_mask = 0;