diff options
author | Justin Erenkrantz <jerenkrantz@apache.org> | 2001-09-02 10:43:23 +0200 |
---|---|---|
committer | Justin Erenkrantz <jerenkrantz@apache.org> | 2001-09-02 10:43:23 +0200 |
commit | 9b298bffc7e035aafb477d2d26a509a7a8a6d8dd (patch) | |
tree | f55f5bc1f5faec8fb01d436dc85d93118020b6bf | |
parent | We should be copying the filters as well when we perform the extension merge (diff) | |
download | apache2-9b298bffc7e035aafb477d2d26a509a7a8a6d8dd.tar.xz apache2-9b298bffc7e035aafb477d2d26a509a7a8a6d8dd.zip |
Make mod_include do lazy evaluation of potentially expensive to
compute variables.
Tested with httpd-test's printenv.shtml.
(Justin threw in one or two unrelated formatting nits)
Submitted by: Brian Pane <bpane@pacbell.net>
Reviewed by: Justin Erenkrantz
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@90872 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | modules/filters/mod_include.c | 134 |
2 files changed, 95 insertions, 42 deletions
@@ -1,5 +1,8 @@ Changes with Apache 2.0.26-dev + *) Make mod_include do lazy evaluation of potentially expensive to + compute variables. [Brian Pane <bpane@pacbell.net>] + *) Fix logging of bytes sent for HEAD requests. %b and %B should log either - or 0, before this patch, they were both logging the file size. [Taketo Kabe <kabe@sra-tohoku.co.jp>] diff --git a/modules/filters/mod_include.c b/modules/filters/mod_include.c index 9104362942..179799d838 100644 --- a/modules/filters/mod_include.c +++ b/modules/filters/mod_include.c @@ -96,32 +96,52 @@ module AP_MODULE_DECLARE_DATA include_module; static apr_hash_t *include_hash; static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *ssi_pfn_register; +/***************************************************************** + * + * XBITHACK. Sigh... NB it's configurable per-directory; the compile-time + * option only changes the default. + */ + +module include_module; +enum xbithack { + xbithack_off, xbithack_on, xbithack_full +}; + +typedef struct { + char *default_error_msg; + char *default_time_fmt; + enum xbithack *xbithack; +} include_dir_config; + +#ifdef XBITHACK +#define DEFAULT_XBITHACK xbithack_full +#else +#define DEFAULT_XBITHACK xbithack_off +#endif + #define BYTE_COUNT_THRESHOLD AP_MIN_BYTES_TO_WRITE /* ------------------------ Environment function -------------------------- */ +/* Sentinel value to store in subprocess_env for items that + * shouldn't be evaluated until/unless they're actually used + */ +static char lazy_eval_sentinel; + /* XXX: could use ap_table_overlap here */ static void add_include_vars(request_rec *r, char *timefmt) { - char *pwname; apr_table_t *e = r->subprocess_env; char *t; - apr_time_t date = r->request_time; - apr_table_setn(e, "DATE_LOCAL", ap_ht_time(r->pool, date, timefmt, 0)); - apr_table_setn(e, "DATE_GMT", ap_ht_time(r->pool, date, timefmt, 1)); - apr_table_setn(e, "LAST_MODIFIED", - ap_ht_time(r->pool, r->finfo.mtime, timefmt, 0)); + apr_table_setn(e, "DATE_LOCAL", &lazy_eval_sentinel); + apr_table_setn(e, "DATE_GMT", &lazy_eval_sentinel); + apr_table_setn(e, "LAST_MODIFIED", &lazy_eval_sentinel); apr_table_setn(e, "DOCUMENT_URI", r->uri); if (r->path_info && *r->path_info) { apr_table_setn(e, "DOCUMENT_PATH_INFO", r->path_info); } - if (apr_get_username(&pwname, r->finfo.user, r->pool) == APR_SUCCESS) { - apr_table_setn(e, "USER_NAME", pwname); - } - else { - apr_table_setn(e, "USER_NAME", "<unknown>"); - } + apr_table_setn(e, "USER_NAME", &lazy_eval_sentinel); if ((t = strrchr(r->filename, '/'))) { apr_table_setn(e, "DOCUMENT_NAME", ++t); } @@ -137,6 +157,42 @@ static void add_include_vars(request_rec *r, char *timefmt) } } +static const char *add_include_vars_lazy(request_rec *r, const char *var) +{ + char *val; + if (!strcasecmp(var, "DATE_LOCAL")) { + include_dir_config *conf = + (include_dir_config *)ap_get_module_config(r->per_dir_config, + &include_module); + val = ap_ht_time(r->pool, r->request_time, conf->default_time_fmt, 0); + } + else if (!strcasecmp(var, "DATE_GMT")) { + include_dir_config *conf = + (include_dir_config *)ap_get_module_config(r->per_dir_config, + &include_module); + val = ap_ht_time(r->pool, r->request_time, conf->default_time_fmt, 1); + } + else if (!strcasecmp(var, "LAST_MODIFIED")) { + include_dir_config *conf = + (include_dir_config *)ap_get_module_config(r->per_dir_config, + &include_module); + val = ap_ht_time(r->pool, r->finfo.mtime, conf->default_time_fmt, 0); + } + else if (!strcasecmp(var, "USER_NAME")) { + if (apr_get_username(&val, r->finfo.user, r->pool) != APR_SUCCESS) { + val = "<unknown>"; + } + } + else { + val = NULL; + } + + if (val) { + apr_table_setn(r->subprocess_env, var, val); + } + return val; +} + /* --------------------------- Parser functions --------------------------- */ /* This function returns either a pointer to the split bucket containing the @@ -177,7 +233,6 @@ static apr_bucket *find_start_sequence(apr_bucket *dptr, include_ctx_t *ctx, if (ctx->output_now) { apr_size_t start_index; apr_bucket *start_bucket; - apr_bucket_brigade *remainder; if (ctx->head_start_index > 0) { start_bucket = ctx->head_start_bucket; apr_bucket_split(start_bucket, start_index); @@ -716,6 +771,9 @@ static void ap_ssi_parse_string(request_rec *r, const char *in, char *out, tmp_store = *end_of_var_name; *end_of_var_name = '\0'; val = apr_table_get(r->subprocess_env, start_of_var_name); + if (val == &lazy_eval_sentinel) { + val = add_include_vars_lazy(r, start_of_var_name); + } *end_of_var_name = tmp_store; if (val) { @@ -962,12 +1020,21 @@ static int handle_echo(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec if (!strcmp(tag, "var")) { const char *val = apr_table_get(r->subprocess_env, tag_val); + if (val == &lazy_eval_sentinel) { + val = add_include_vars_lazy(r, tag_val); + } if (val) { switch(encode) { - case E_NONE: echo_text = val; break; - case E_URL: echo_text = ap_escape_uri(r->pool, val); break; - case E_ENTITY: echo_text = ap_escape_html(r->pool, val); break; - } + case E_NONE: + echo_text = val; + break; + case E_URL: + echo_text = ap_escape_uri(r->pool, val); + break; + case E_ENTITY: + echo_text = ap_escape_html(r->pool, val); + break; + } e_len = strlen(echo_text); tmp_buck = apr_bucket_heap_create(echo_text, e_len, 1, &e_wrt); @@ -2337,13 +2404,19 @@ static int handle_printenv(include_ctx_t *ctx, apr_bucket_brigade **bb, request_ apr_array_header_t *arr = apr_table_elts(r->subprocess_env); apr_table_entry_t *elts = (apr_table_entry_t *)arr->elts; int i; - char *key_text, *val_text; + const char *key_text, *val_text; apr_size_t k_len, v_len, t_wrt; *inserted_head = NULL; for (i = 0; i < arr->nelts; ++i) { key_text = ap_escape_html(r->pool, elts[i].key); - val_text = ap_escape_html(r->pool, elts[i].val); + if (elts[i].val == &lazy_eval_sentinel) { + val_text = + ap_escape_html(r->pool, + add_include_vars_lazy(r, elts[i].key)); + } else { + val_text = ap_escape_html(r->pool, elts[i].val); + } k_len = strlen(key_text); v_len = strlen(val_text); @@ -2688,29 +2761,6 @@ static apr_status_t send_parsed_content(apr_bucket_brigade **bb, return APR_SUCCESS; } -/***************************************************************** - * - * XBITHACK. Sigh... NB it's configurable per-directory; the compile-time - * option only changes the default. - */ - -module include_module; -enum xbithack { - xbithack_off, xbithack_on, xbithack_full -}; - -typedef struct { - char *default_error_msg; - char *default_time_fmt; - enum xbithack *xbithack; -} include_dir_config; - -#ifdef XBITHACK -#define DEFAULT_XBITHACK xbithack_full -#else -#define DEFAULT_XBITHACK xbithack_off -#endif - static void *create_includes_dir_config(apr_pool_t *p, char *dummy) { include_dir_config *result = |