http_request.c revision 64ff08a7a6515306d78e725cef4b220bf0675e8f
97a9a944b5887e91042b019776c41d5dd74557aferikabele/* Licensed to the Apache Software Foundation (ASF) under one or more
97a9a944b5887e91042b019776c41d5dd74557aferikabele * contributor license agreements. See the NOTICE file distributed with
97a9a944b5887e91042b019776c41d5dd74557aferikabele * this work for additional information regarding copyright ownership.
a945f35eff8b6a88009ce73de6d4c862ce58de3cslive * The ASF licenses this file to You under the Apache License, Version 2.0
a945f35eff8b6a88009ce73de6d4c862ce58de3cslive * (the "License"); you may not use this file except in compliance with
a945f35eff8b6a88009ce73de6d4c862ce58de3cslive * the License. You may obtain a copy of the License at
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * Unless required by applicable law or agreed to in writing, software
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * distributed under the License is distributed on an "AS IS" BASIS,
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * See the License for the specific language governing permissions and
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * limitations under the License.
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * http_request.c: functions to get and process requests
4b5981e276e93df97c34e4da05ca5cf8bbd937dand * Rob McCool 3/21/93
a63f0ab647ad2ab72efc9bea7a66e24e9ebc5cc2nd * Thoroughly revamped by rst for Apache. NB this file reads
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd * best from the bottom up.
117c1f888a14e73cdd821dc6c23eb0411144a41cnd/*****************************************************************
117c1f888a14e73cdd821dc6c23eb0411144a41cnd * Mainline request processing...
117c1f888a14e73cdd821dc6c23eb0411144a41cnd/* XXX A cleaner and faster way to do this might be to pass the request_rec
117c1f888a14e73cdd821dc6c23eb0411144a41cnd * down the filter chain as a parameter. It would need to change for
3cc4ff86e6cc4cfd7d4ccfc58dedff599091444bnoodl * subrequest vs. main request filters; perhaps the subrequest filter could
117c1f888a14e73cdd821dc6c23eb0411144a41cnd * make the switch.
117c1f888a14e73cdd821dc6c23eb0411144a41cnd while (f) {
6c45910d5394acbc3f20ab3f2615d9ed2b4e6533nd if (f->r == from) {
709e3a21ba73b8433462959cd56c773454b34441trawick char *custom_response = ap_response_code_string(r, error_index);
117c1f888a14e73cdd821dc6c23eb0411144a41cnd * Check if we still have the ap_http_header_filter in place. If
117c1f888a14e73cdd821dc6c23eb0411144a41cnd * this is the case we should not ignore AP_FILTER_ERROR here because
117c1f888a14e73cdd821dc6c23eb0411144a41cnd * it means that we have not sent any response at all and never
117c1f888a14e73cdd821dc6c23eb0411144a41cnd * will. This is bad. Sent an internal server error instead.
117c1f888a14e73cdd821dc6c23eb0411144a41cnd while (next && (next->frec != ap_http_header_filter_handle)) {
117c1f888a14e73cdd821dc6c23eb0411144a41cnd * If next != NULL then we left the while above because of
a38b5f73e7f0f3b8726fb47d27b145f37036ead0jim * next->frec == ap_http_header_filter
fe64b2ba25510d8c9dba5560a2d537763566cf40nd "Custom error page caused AP_FILTER_ERROR");
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna * The following takes care of Apache redirects to custom response URLs
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna * Note that if we are already dealing with the response to some other
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna * error condition, we just report on the original error, and give up on
5ae609a8a09239d20f48a4a95c4f21b713995babwrowe * any attempt to handle the other thing "intelligently"...
5ae609a8a09239d20f48a4a95c4f21b713995babwrowe while (r_1st_err->prev && (r_1st_err->prev->status != HTTP_OK))
5ae609a8a09239d20f48a4a95c4f21b713995babwrowe r_1st_err = r_1st_err->prev; /* Get back to original error */
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna /* The recursive error was caused by an ErrorDocument specifying
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna * an internal redirect to a bad URI. ap_internal_redirect has
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna * changed the filter chains to point to the ErrorDocument's
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna * request_rec. Back out those changes so we can safely use the
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna * original failing request_rec to send the canned error message.
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna * ap_send_error_response gets rid of existing resource filters
90efa9f1730742d874edb5a7803adce11c9f08eanoodl * on the output side, so we can skip those.
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna update_r_in_filters(r_1st_err->proto_output_filters, r, r_1st_err);
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna update_r_in_filters(r_1st_err->input_filters, r, r_1st_err);
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna custom_response = NULL; /* Do NOT retry the custom thing! */
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna * This test is done here so that none of the auth modules needs to know
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna * about proxy authentication. They treat it like normal auth, and then
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna * we tweak the status.
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna if (HTTP_UNAUTHORIZED == r->status && PROXYREQ_PROXY == r->proxyreq) {
5ae609a8a09239d20f48a4a95c4f21b713995babwrowe /* If we don't want to keep the connection, make sure we mark that the
5ae609a8a09239d20f48a4a95c4f21b713995babwrowe * connection is not eligible for keepalive. If we want to keep the
5ae609a8a09239d20f48a4a95c4f21b713995babwrowe * connection, be sure that the request body (if any) has been read.
5ae609a8a09239d20f48a4a95c4f21b713995babwrowe * Two types of custom redirects --- plain text, and URLs. Plain text has
5ae609a8a09239d20f48a4a95c4f21b713995babwrowe * a leading '"', so the URL code, here, is triggered on its absence
5ae609a8a09239d20f48a4a95c4f21b713995babwrowe * The URL isn't local, so lets drop through the rest of this
5ae609a8a09239d20f48a4a95c4f21b713995babwrowe * apache code, and continue with the usual REDIRECT handler.
5ae609a8a09239d20f48a4a95c4f21b713995babwrowe * But note that the client will ultimately see the wrong
5ae609a8a09239d20f48a4a95c4f21b713995babwrowe * status...
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna apr_table_setn(r->headers_out, "Location", custom_response);
fe64b2ba25510d8c9dba5560a2d537763566cf40nd const char *error_notes;
fe64b2ba25510d8c9dba5560a2d537763566cf40nd r->no_local_copy = 1; /* Do NOT send HTTP_NOT_MODIFIED for
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * error documents! */
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * This redirect needs to be a GET no matter what the original
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * method was.
fe64b2ba25510d8c9dba5560a2d537763566cf40nd apr_table_setn(r->subprocess_env, "REQUEST_METHOD", r->method);
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * Provide a special method for modules to communicate
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * more informative (than the plain canned) messages to us.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * Propagate them to ErrorDocuments via the ERROR_NOTES variable:
fb77c505254b6e9c925e23e734463e87574f8f40kess apr_table_setn(r->subprocess_env, "ERROR_NOTES", error_notes);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * Dumb user has given us a bad url to redirect to --- fake up
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * dying with a recursive server error...
06ba4a61654b3763ad65f52283832ebf058fdf1cslive "Invalid error redirection directive: %s",
06ba4a61654b3763ad65f52283832ebf058fdf1cslive apr_bucket_brigade *bb = apr_brigade_create(c->pool, c->bucket_alloc);
bc4b55ec8f31569d606d5680d50189a355bcd7a6rbowen rv = ap_get_brigade(c->input_filters, bb, AP_MODE_SPECULATIVE,
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * Error or empty brigade: There is no data present in the input
fe64b2ba25510d8c9dba5560a2d537763566cf40nd /* Send an EOR bucket through the output filter chain. When
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * this bucket is destroyed, the request will be logged and
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * its pool will be freed
fe64b2ba25510d8c9dba5560a2d537763566cf40nd bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
fe64b2ba25510d8c9dba5560a2d537763566cf40nd b = ap_bucket_eor_create(r->connection->bucket_alloc, r);
fe64b2ba25510d8c9dba5560a2d537763566cf40nd /* From here onward, it is no longer safe to reference r
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * or r->pool, because r->pool may have been destroyed
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess * already by the EOR bucket's cleanup function.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive AP_PROCESS_REQUEST_RETURN((uintptr_t)r, r->uri, r->status);
130d299c4b2b15be45532a176604c71fdc7bea5bnd /* Give quick handlers a shot at serving the request on the fast
130d299c4b2b15be45532a176604c71fdc7bea5bnd * path, bypassing all of the other Apache hooks.
130d299c4b2b15be45532a176604c71fdc7bea5bnd * This hook was added to enable serving files out of a URI keyed
130d299c4b2b15be45532a176604c71fdc7bea5bnd * content cache ( e.g., Mike Abbott's Quick Shortcut Cache,
130d299c4b2b15be45532a176604c71fdc7bea5bnd * described here: http://oss.sgi.com/projects/apache/mod_qsc.html )
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * It may have other uses as well, such as routing requests directly to
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * content handlers that have the ability to grok HTTP and do their
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * own access checking, etc (e.g. servlet engines).
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * Use this hook with extreme care and only if you know what you are
fe64b2ba25510d8c9dba5560a2d537763566cf40nd ap_time_process_request(r->connection->sbh, START_PREQUEST);
627c978514c54179736d152923478be7c8707f9bnd apr_thread_mutex_create(&r->invoke_mtx, APR_THREAD_MUTEX_DEFAULT, r->pool);
fe64b2ba25510d8c9dba5560a2d537763566cf40nd access_status = ap_run_quick_handler(r, 0); /* Not a look-up request */
888b616027180cc8aaa4d2bee5ecc6acec175bc5nd /* TODO: Should move these steps into a generic function, so modules
b95ae799514ad86a15610ad75808d7065e9847c9kess * working on a suspended request can also call _ENTRY again.
5224ff8eae5156a05f676f1dad8add2e2f2efe1dnd AP_PROCESS_REQUEST_RETURN((uintptr_t)r, r->uri, access_status);
fe64b2ba25510d8c9dba5560a2d537763566cf40nd /* e.g., something not in storage like TRACE */
6fe26506780e73be2a412d758af77fafdf03291and * Notice a timeout as an error message. This might be
6fe26506780e73be2a412d758af77fafdf03291and * valuable for detecting clients with broken network
58699879a562774640b95e9eedfd891f336e38c2nd * connections or possible DoS attacks.
fb77c505254b6e9c925e23e734463e87574f8f40kess * It is still save to use r / r->pool here as the eor bucket
fb77c505254b6e9c925e23e734463e87574f8f40kess * could not have been destroyed in the event of a timeout.
58699879a562774640b95e9eedfd891f336e38c2nd "Timeout while writing data for URI %s to the"
58699879a562774640b95e9eedfd891f336e38c2ndstatic apr_table_t *rename_original_env(apr_pool_t *p, apr_table_t *t)
fb77c505254b6e9c925e23e734463e87574f8f40kess const apr_table_entry_t *elts = (const apr_table_entry_t *) env_arr->elts;
58699879a562774640b95e9eedfd891f336e38c2nd apr_table_setn(new, apr_pstrcat(p, "REDIRECT_", elts[i].key, NULL),
9b5e2c5e769dc678a1aca06df75c32022b2f1492trawickstatic request_rec *internal_internal_redirect(const char *new_uri,
fe64b2ba25510d8c9dba5560a2d537763566cf40nd new = (request_rec *) apr_pcalloc(r->pool, sizeof(request_rec));
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * A whole lot of this really ought to be shared with http_protocol.c...
4335f1cbf345c91bb996eec540c11ba8ce5d4268nd * another missing cleanup. It's particularly inappropriate to be
4335f1cbf345c91bb996eec540c11ba8ce5d4268nd * setting header_only, etc., here.
4335f1cbf345c91bb996eec540c11ba8ce5d4268nd new->allowed_methods = ap_make_method_list(new->pool, 2);
4335f1cbf345c91bb996eec540c11ba8ce5d4268nd /* Must have prev and next pointers set before calling create_request
9b5e2c5e769dc678a1aca06df75c32022b2f1492trawick /* Inherit the rest of the protocol info... */
fe64b2ba25510d8c9dba5560a2d537763566cf40nd new->subprocess_env = rename_original_env(r->pool, r->subprocess_env);
fe64b2ba25510d8c9dba5560a2d537763566cf40nd new->allowed_methods = ap_make_method_list(new->pool, 2);
06ba4a61654b3763ad65f52283832ebf058fdf1cslive new->read_length = r->read_length; /* We can only read it once */
fb77c505254b6e9c925e23e734463e87574f8f40kess /* Add back the subrequest filter, which we lost when
fb77c505254b6e9c925e23e734463e87574f8f40kess * we set output_filters to include only the protocol
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * output filters from the original request.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive ap_add_output_filter_handle(ap_subreq_core_filter_handle,
06ba4a61654b3763ad65f52283832ebf058fdf1cslive apr_table_setn(new->subprocess_env, "REDIRECT_STATUS",
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz * XXX: hmm. This is because mod_setenvif and mod_unique_id really need
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz * to do their thing on internal redirects as well. Perhaps this is a
cb3a1082aec4b3b4f4ed238c93c3cc54933a7f0end * misnamed function.
9335f6d807d76d60e54af4ededdebebddb3e3d13noodl if ((access_status = ap_run_post_read_request(new))) {
604c89126c27104f659d7a51b0113e3bd435faf8fielding/* XXX: Is this function is so bogus and fragile that we deep-6 it? */
604c89126c27104f659d7a51b0113e3bd435faf8fieldingAP_DECLARE(void) ap_internal_fast_redirect(request_rec *rr, request_rec *r)
604c89126c27104f659d7a51b0113e3bd435faf8fielding /* We need to tell POOL_DEBUG that we're guaranteeing that rr->pool
604c89126c27104f659d7a51b0113e3bd435faf8fielding * will exist as long as r->pool. Otherwise we run into troubles because
604c89126c27104f659d7a51b0113e3bd435faf8fielding * some values in this request will be allocated in r->pool, and others in
909ce17e2bd0faef7b1c294f2307f009793fd493nd * rr->pool.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive r->no_local_copy = (r->no_local_copy && rr->no_local_copy);
cb3a1082aec4b3b4f4ed238c93c3cc54933a7f0end /* copy output headers from subrequest, but leave negotiation headers */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive r->notes = apr_table_overlay(r->pool, rr->notes, r->notes);
8e31885fc494b603e0650113dde9e29d1b1d2602maczniak r->headers_out = apr_table_overlay(r->pool, rr->headers_out,
06ba4a61654b3763ad65f52283832ebf058fdf1cslive r->err_headers_out = apr_table_overlay(r->pool, rr->err_headers_out,
97a9a944b5887e91042b019776c41d5dd74557aferikabele r->subprocess_env = apr_table_overlay(r->pool, rr->subprocess_env,
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* If any filters pointed at the now-defunct rr, we must point them
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * at our "new" instance of r. In particular, some of rr's structures
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd * will now be bogus (say rr->headers_out). If a filter tried to modify
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd * their f->r structure when it is pointing to rr, the real request_rec
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd * will not get updated. Fix that here.
da637bcae7b6e150470e701af29da5604a34a17erbowen ap_add_output_filter_handle(ap_subreq_core_filter_handle,
da637bcae7b6e150470e701af29da5604a34a17erbowen * We need to check if we now have the SUBREQ_CORE filter in our filter
da637bcae7b6e150470e701af29da5604a34a17erbowen * chain. If this is the case we need to remove it since we are NO
da637bcae7b6e150470e701af29da5604a34a17erbowen * subrequest. But we need to keep in mind that the SUBREQ_CORE filter
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * does not necessarily need to be the first filter in our chain. So we
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * need to go through the chain. But we only need to walk up the chain
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * until the proto_output_filters as the SUBREQ_CORE filter is below the
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * protocol filters.
fe64b2ba25510d8c9dba5560a2d537763566cf40nd while (next && (next->frec != ap_subreq_core_filter_handle)
fb77c505254b6e9c925e23e734463e87574f8f40kess if (next && (next->frec == ap_subreq_core_filter_handle)) {
fe64b2ba25510d8c9dba5560a2d537763566cf40ndAP_DECLARE(void) ap_internal_redirect(const char *new_uri, request_rec *r)
fb77c505254b6e9c925e23e734463e87574f8f40kess request_rec *new = internal_internal_redirect(new_uri, r);
fe64b2ba25510d8c9dba5560a2d537763566cf40nd /* ap_die was already called, if an error occured */
fe64b2ba25510d8c9dba5560a2d537763566cf40nd access_status = ap_run_quick_handler(new, 0); /* Not a look-up request */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive/* This function is designed for things like actions or CGI scripts, when
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * using AddHandler, and you want to preserve the content type across
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * an internal redirect.
06ba4a61654b3763ad65f52283832ebf058fdf1csliveAP_DECLARE(void) ap_internal_redirect_handler(const char *new_uri, request_rec *r)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd request_rec *new = internal_internal_redirect(new_uri, r);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd /* ap_die was already called, if an error occured */
604c89126c27104f659d7a51b0113e3bd435faf8fieldingAP_DECLARE(void) ap_allow_methods(request_rec *r, int reset, ...)
fe64b2ba25510d8c9dba5560a2d537763566cf40nd const char *method;
604c89126c27104f659d7a51b0113e3bd435faf8fielding * Get rid of any current settings if requested; not just the
fe64b2ba25510d8c9dba5560a2d537763566cf40nd * well-known methods but any extensions as well.
22265f1724519886e2a2b5e0ebd61477506b7379noodl while ((method = va_arg(methods, const char *)) != NULL) {
604c89126c27104f659d7a51b0113e3bd435faf8fieldingAP_DECLARE(void) ap_allow_standard_methods(request_rec *r, int reset, ...)
9597f440430d8c876dd64f5f78066804650a18ecnoodl * Get rid of any current settings if requested; not just the
9597f440430d8c876dd64f5f78066804650a18ecnoodl * well-known methods but any extensions as well.