You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by gl...@apache.org on 2002/04/22 00:57:11 UTC

cvs commit: jakarta-tomcat-connectors/jk/doc mod_jk-howto.html

glenn       02/04/21 15:57:11

  Modified:    jk/native/apache-1.3 mod_jk.c
               jk/native/common jk_logger.h jk_uri_worker_map.c jk_util.c
               jk/doc   mod_jk-howto.html
  Log:
  Apache mod_jk 1.2 new features.
  
  Added JkRequestLogFormat for Apache style request logging
  including Tocmat request latency in seconds and microseconds.
  
  Added JkAutoAlias, this can be used to automatically Alias
  web application context directories so that static files
  can be served by Apache instead of Tomcat.  When configured,
  requests for a WAR file in the Tomcat appBase (webapps) directory
  are forbidden.  Requests for the WEB-INF and META-INF directories
  within a web application context dir are also forbidden and will
  return an HTTP 403 error.
  
  Added ability to JkMount so that /*/servlet/ can be used to
  configure mod_jk to pass all servlet requests on to Tomcat
  for any web application context.
  
  Revision  Changes    Path
  1.26      +521 -12   jakarta-tomcat-connectors/jk/native/apache-1.3/mod_jk.c
  
  Index: mod_jk.c
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-connectors/jk/native/apache-1.3/mod_jk.c,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- mod_jk.c	3 Apr 2002 00:49:19 -0000	1.25
  +++ mod_jk.c	21 Apr 2002 22:57:11 -0000	1.26
  @@ -61,7 +61,7 @@
    * Author:      Gal Shachor <sh...@il.ibm.com>                           *
    *              Dan Milstein <da...@shore.net>                            *
    *              Henri Gomez <hg...@slib.fr>                               *
  - * Version:     $Revision: 1.25 $                                           *
  + * Version:     $Revision: 1.26 $                                           *
    ***************************************************************************/
   
   /*
  @@ -101,6 +101,7 @@
   
   #define JK_WORKER_ID        ("jakarta.worker")
   #define JK_HANDLER          ("jakarta-servlet")
  +#define JK_DURATION         ("jakarta.worker.duration")
   #define JK_MAGIC_TYPE       ("application/x-jakarta-servlet")
   #define NULL_FOR_EMPTY(x)   ((x && !strlen(x)) ? NULL : x) 
   
  @@ -139,6 +140,18 @@
       jk_uri_worker_map_t *uw_map;
   
       /*
  +     * Automatic context path apache alias
  +     */
  +    char *alias_dir;
  +
  +    /*
  +     * Request Logging
  +     */
  +
  +    char *format_string;
  +    array_header *format;
  +
  +    /*
        * SSL Support
        */
       int  ssl_enable;
  @@ -742,7 +755,7 @@
   /*
    * JkLogLevel Directive Handling
    *
  - * JkLogLevel debug/info/error/emerg
  + * JkLogLevel debug/info/request/error/emerg
    */
   
   static const char *jk_set_log_level(cmd_parms *cmd,
  @@ -773,6 +786,402 @@
   }
   
   /*
  + * JkAutoAlias Directive Handling
  + * 
  + * JkAutoAlias application directory
  + */
  +
  +static const char *jk_set_auto_alias(cmd_parms *cmd,
  +                                    void *dummy,
  +                                    char *directory)
  +{
  +    server_rec *s = cmd->server;
  +    jk_server_conf_t *conf =
  +        (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  +
  +    conf->alias_dir = directory;
  +
  +    if (conf->alias_dir == NULL)
  +        return "JkAutoAlias directory invalid";
  +
  +    return NULL;
  +}
  +
  +/*****************************************************************
  + *
  + * Actually logging.
  + */
  +
  +typedef const char *(*item_key_func) (request_rec *, char *);
  +                                                             
  +typedef struct {                                             
  +    item_key_func func;
  +    char *arg;         
  +} request_log_format_item;
  +
  +static const char *process_item(request_rec *r,
  +                          request_log_format_item *item)
  +{
  +    const char *cp;
  +
  +    cp = (*item->func) (r,item->arg);
  +    return cp ? cp : "-";
  +}
  +
  +static int request_log_transaction(request_rec *r,
  +                                  jk_server_conf_t *conf)
  +{
  +    request_log_format_item *items;
  +    char *str, *s;
  +    int i;
  +    int len = 0;
  +    const char **strs;
  +    int *strl;
  +    array_header *format = conf->format;
  +
  +    strs = ap_palloc(r->pool, sizeof(char *) * (format->nelts));
  +    strl = ap_palloc(r->pool, sizeof(int) * (format->nelts));
  +    items = (request_log_format_item *) format->elts;
  +    for (i = 0; i < format->nelts; ++i) {
  +        strs[i] = process_item(r, &items[i]);
  +    }
  +    for (i = 0; i < format->nelts; ++i) {
  +        len += strl[i] = strlen(strs[i]);
  +    }
  +    str = ap_palloc(r->pool, len + 1);
  +    for (i = 0, s = str; i < format->nelts; ++i) {
  +        memcpy(s, strs[i], strl[i]);
  +        s += strl[i];
  +    }
  +    *s = 0;
  +    jk_log(conf->log ? conf->log : main_log,JK_LOG_REQUEST,str);
  +}
  +
  +/*****************************************************************
  + *
  + * Parsing the log format string
  + */
  +
  +static char *format_integer(pool *p, int i)
  +{
  +    return ap_psprintf(p, "%d", i);
  +}
  + 
  +static char *pfmt(pool *p, int i)
  +{
  +    if (i <= 0) {
  +        return "-";
  +    }
  +    else {
  +        return format_integer(p, i);
  +    }
  +}
  +
  +static const char *constant_item(request_rec *dummy, char *stuff)
  +{
  +    return stuff;
  +}
  +
  +static const char *log_worker_name(request_rec *r, char *a)
  +{
  +    return ap_table_get(r->notes, JK_WORKER_ID);
  +}
  +
  +
  +static const char *log_request_duration(request_rec *r, char *a)
  +{
  +    return ap_table_get(r->notes, JK_DURATION);
  +}
  + 
  +static const char *log_request_line(request_rec *r, char *a)
  +{
  +            /* NOTE: If the original request contained a password, we
  +             * re-write the request line here to contain XXXXXX instead:
  +             * (note the truncation before the protocol string for HTTP/0.9 requests)
  +             * (note also that r->the_request contains the unmodified request)
  +             */
  +    return (r->parsed_uri.password) ? ap_pstrcat(r->pool, r->method, " ",
  +                                         ap_unparse_uri_components(r->pool, &r->parsed_uri, 0),
  +                                         r->assbackwards ? NULL : " ", r->protocol, NULL)
  +                                        : r->the_request;
  +}
  +
  +/* These next two routines use the canonical name:port so that log
  + * parsers don't need to duplicate all the vhost parsing crud.
  + */
  +static const char *log_virtual_host(request_rec *r, char *a)
  +{
  +    return r->server->server_hostname;
  +}
  + 
  +static const char *log_server_port(request_rec *r, char *a)
  +{
  +    return ap_psprintf(r->pool, "%u",
  +        r->server->port ? r->server->port : ap_default_port(r));
  +}
  + 
  +/* This respects the setting of UseCanonicalName so that
  + * the dynamic mass virtual hosting trick works better.
  + */
  +static const char *log_server_name(request_rec *r, char *a)
  +{
  +    return ap_get_server_name(r);
  +}
  +
  +static const char *log_request_uri(request_rec *r, char *a)
  +{
  +    return r->uri;
  +}
  +static const char *log_request_method(request_rec *r, char *a)
  +{
  +    return r->method;
  +}
  +
  +static const char *log_request_protocol(request_rec *r, char *a)
  +{
  +    return r->protocol;
  +}
  +static const char *log_request_query(request_rec *r, char *a)
  +{
  +    return (r->args != NULL) ? ap_pstrcat(r->pool, "?", r->args, NULL)
  +                             : "";
  +}                  
  +static const char *log_status(request_rec *r, char *a)
  +{                  
  +    return pfmt(r->pool,r->status);
  +}                  
  +                   
  +static const char *clf_log_bytes_sent(request_rec *r, char *a)
  +{                  
  +    if (!r->sent_bodyct) {
  +        return "-";
  +    }              
  +    else {        
  +        long int bs;
  +        ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
  +        return ap_psprintf(r->pool, "%ld", bs);
  +    }              
  +}                  
  +    
  +static const char *log_bytes_sent(request_rec *r, char *a)
  +{                  
  +    if (!r->sent_bodyct) {
  +        return "0";
  +    }              
  +    else {        
  +        long int bs;
  +        ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
  +        return ap_psprintf(r->pool, "%ld", bs);
  +    }              
  +}
  +
  +static struct log_item_list {
  +    char ch;
  +    item_key_func func;
  +} log_item_keys[] = {
  +
  +    {
  +        'T', log_request_duration
  +    },
  +    {
  +        'r', log_request_line
  +    },
  +    {
  +        'U', log_request_uri
  +    },
  +    {
  +        's', log_status
  +    },
  +    {
  +        'b', clf_log_bytes_sent
  +    },
  +    {
  +        'B', log_bytes_sent
  +    },
  +    {
  +        'V', log_server_name
  +    },
  +    {
  +        'v', log_virtual_host
  +    },
  +    {
  +        'p', log_server_port
  +    },
  +    {
  +        'H', log_request_protocol
  +    },
  +    {
  +        'm', log_request_method
  +    },
  +    {
  +        'q', log_request_query
  +    },
  +    {
  +        'w', log_worker_name
  +    },
  +    {
  +        '\0'
  +    }
  +};
  +
  +static struct log_item_list *find_log_func(char k)
  +{
  +    int i;
  +
  +    for (i = 0; log_item_keys[i].ch; ++i)
  +        if (k == log_item_keys[i].ch) {
  +            return &log_item_keys[i];
  +        }
  +
  +    return NULL;
  +}
  +
  +static char *parse_request_log_misc_string(pool *p,
  +                                           request_log_format_item *it,
  +                                           const char **sa)
  +{
  +    const char *s;
  +    char *d;
  +
  +    it->func = constant_item;
  +
  +    s = *sa;
  +    while (*s && *s != '%') {
  +        s++;
  +    }
  +    /*
  +     * This might allocate a few chars extra if there's a backslash
  +     * escape in the format string.
  +     */
  +    it->arg = ap_palloc(p, s - *sa + 1);
  +
  +    d = it->arg;
  +    s = *sa;
  +    while (*s && *s != '%') {
  +        if (*s != '\\') {
  +            *d++ = *s++;
  +        }
  +        else {
  +            s++;
  +            switch (*s) {
  +            case '\\':
  +                *d++ = '\\';
  +                s++;
  +                break;
  +            case 'n':
  +                *d++ = '\n';
  +                s++;
  +                break;
  +            case 't':
  +                *d++ = '\t';
  +                s++;
  +                break;
  +            default:
  +                /* copy verbatim */
  +                *d++ = '\\';
  +                /*
  +                 * Allow the loop to deal with this *s in the normal
  +                 * fashion so that it handles end of string etc.
  +                 * properly.
  +                 */
  +                break;
  +            }
  +        }
  +    }
  +    *d = '\0';
  +
  +    *sa = s;
  +    return NULL;
  +}
  +
  +static char *parse_request_log_item(pool *p,
  +                                    request_log_format_item *it,
  +                                    const char **sa)
  +{
  +    const char *s = *sa;
  +    int i;
  +    struct log_item_list *l;
  +
  +    if (*s != '%') {
  +        return parse_request_log_misc_string(p, it, sa);
  +    }
  +    
  +    ++s;
  +    it->arg = "";               /* For safety's sake... */
  +    
  +    l = find_log_func(*s++);
  +    if (!l) {
  +        char dummy[2];
  +
  +        dummy[0] = s[-1];
  +        dummy[1] = '\0';
  +        return ap_pstrcat(p, "Unrecognized JkRequestLogFormat directive %",
  +                          dummy, NULL);
  +    }
  +    it->func = l->func;
  +    *sa = s;
  +    return NULL;
  +}
  +
  +static array_header *parse_request_log_string(pool *p, const char *s,
  +                                              const char **err)
  +{
  +    array_header *a = ap_make_array(p, 15, sizeof(request_log_format_item));
  +    char *res;
  +
  +    while (*s) {
  +        if ((res = parse_request_log_item(p, (request_log_format_item *) ap_push_array(a), &s))) {
  +            *err = res;
  +            return NULL;
  +        }
  +    }    
  +     
  +    s = "\n";
  +    parse_request_log_item(p, (request_log_format_item *) ap_push_array(a), &s);
  +    return a;
  +}
  +
  +/*
  + * JkRequestLogFormat Directive Handling
  + *
  + * JkRequestLogFormat format string
  + *
  + * %b - Bytes sent, excluding HTTP headers. In CLF format
  + * %B - Bytes sent, excluding HTTP headers.             
  + * %H - The request protocol              
  + * %m - The request method
  + * %p - The canonical Port of the server serving the request
  + * %q - The query string (prepended with a ? if a query string exists,
  + *      otherwise an empty string)
  + * %r - First line of request
  + * %s - request HTTP status code
  + * %T - Requset duration, elapsed time to handle request in seconds '.' micro seconds
  + * %U - The URL path requested, not including any query string.
  + * %v - The canonical ServerName of the server serving the request.
  + * %V - The server name according to the UseCanonicalName setting.
  + * %w - Tomcat worker name
  + */
  +
  +static const char *jk_set_request_log_format(cmd_parms *cmd,
  +                                             void *dummy,    
  +                                             char *format)
  +{
  +    const char *err_string = NULL;
  +    server_rec *s = cmd->server;
  +    jk_server_conf_t *conf =
  +        (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  +
  +    conf->format_string = ap_pstrdup(cmd->pool,format);
  +    if( format != NULL ) {
  +        conf->format = parse_request_log_string(cmd->pool, format, &err_string);
  +    }
  +    if( conf->format == NULL )
  +        return "JkRequestLogFormat format array NULL";
  +
  +    return err_string;
  +}
  +
  +/*
    * JkExtractSSL Directive Handling
    *
    * JkExtractSSL On/Off
  @@ -1006,14 +1415,23 @@
       /*
        * JkLogFile & JkLogLevel specifies to where should the plugin log
        * its information and how much.
  -	 * JkLogStampFormat specify the time-stamp to be used on log
  +     * JkLogStampFormat specify the time-stamp to be used on log
        */
       {"JkLogFile", jk_set_log_file, NULL, RSRC_CONF, TAKE1,
        "Full path to the Jakarta mod_jk module log file"},
       {"JkLogLevel", jk_set_log_level, NULL, RSRC_CONF, TAKE1,
  -     "The Jakarta mod_jk module log level, can be debug, info, error or emerg"},
  +     "The Jakarta mod_jk module log level, can be debug, info, request, error, or emerg"},
       {"JkLogStampFormat", jk_set_log_fmt, NULL, RSRC_CONF, TAKE1,
        "The Jakarta mod_jk module log format, follow strftime synthax"},
  +    {"JkRequestLogFormat", jk_set_request_log_format, NULL, RSRC_CONF, TAKE1,
  +     "The Jakarta mod_jk module request log format string"},
  +
  +    /*
  +     * Automatically Alias webapp context directories into the Apache
  +     * document space.
  +     */
  +    {"JkAutoAlias", jk_set_auto_alias, NULL, RSRC_CONF, TAKE1,
  +     "The Jakarta mod_jk module automatic context apache alias directory"},
   
       /*
        * Apache has multiple SSL modules (for example apache_ssl, stronghold
  @@ -1093,6 +1511,7 @@
           jk_worker_t *worker = wc_get_worker_for_name(worker_name, l);
   
           if(worker) {
  +            struct timeval tv_begin,tv_end;
               int rc = JK_FALSE;
               apache_private_data_t private_data;
               jk_ws_service_t s;
  @@ -1107,7 +1526,10 @@
   
               s.ws_private = &private_data;
               s.pool = &private_data.p;            
  -            
  +            if(conf->format != NULL) {
  +                gettimeofday(&tv_begin, NULL);
  +            }
  +
               if(init_ws_service(&private_data, &s, conf)) {
                   jk_endpoint_t *end = NULL;
                   if(worker->get_endpoint(worker, &end, l)) {
  @@ -1131,6 +1553,21 @@
                       }
                       end->done(&end, l);
                   }
  +                if(conf->format != NULL) {
  +                    char *duration = NULL;
  +                    char *status = NULL;
  +                    long micro,seconds;
  +                    gettimeofday(&tv_end, NULL);
  +                    if( tv_end.tv_usec < tv_begin.tv_usec ) {
  +                        tv_end.tv_usec += 1000000;
  +                        tv_end.tv_sec--;
  +                    }
  +                    micro = tv_end.tv_usec - tv_begin.tv_usec;
  +                    seconds = tv_end.tv_sec - tv_begin.tv_sec;
  +                    duration = ap_psprintf(r->pool,"%.1d.%.6d",seconds,micro);
  +                    ap_table_setn(r->notes, JK_DURATION, duration);
  +                    request_log_transaction(r,conf);
  +                }
               }
   
               jk_close_pool(&private_data.p);
  @@ -1152,12 +1589,15 @@
       jk_server_conf_t *c =
           (jk_server_conf_t *) ap_pcalloc(p, sizeof(jk_server_conf_t));
   
  -    c->worker_file = NULL;
  -    c->log_file    = NULL;
  -    c->log_level   = -1;
  -    c->log         = NULL;
  -    c->mountcopy   = JK_FALSE;
  -    c->options     = JK_OPT_FWDURIDEFAULT;
  +    c->worker_file   = NULL;
  +    c->log_file      = NULL;
  +    c->log_level     = -1;
  +    c->log           = NULL;
  +    c->alias_dir     = NULL;
  +    c->format_string = NULL;
  +    c->format        = NULL;
  +    c->mountcopy     = JK_FALSE;
  +    c->options       = JK_OPT_FWDURIDEFAULT;
   
       /*
        * By default we will try to gather SSL info. 
  @@ -1332,11 +1772,80 @@
               (jk_server_conf_t *)ap_get_module_config(r->server->module_config, &jk_module);
   
           if(conf) {
  -            char *worker = map_uri_to_worker(conf->uw_map, r->uri, conf->log ? conf->log : main_log);
  +            jk_logger_t *l = conf->log ? conf->log : main_log;
  +            char *worker = map_uri_to_worker(conf->uw_map, r->uri, l);
   
               if(worker) {
                   r->handler = ap_pstrdup(r->pool, JK_HANDLER);
                   ap_table_setn(r->notes, JK_WORKER_ID, worker);
  +            } else if(conf->alias_dir != NULL) {
  +                /* Automatically map uri to a context static file */
  +                jk_log(l, JK_LOG_DEBUG,
  +                    "mod_jk::jk_translate, check alias_dir: %s\n",conf->alias_dir);
  +                if (strlen(r->uri) > 1) {
  +                    /* Get the context directory name */
  +                    char *context_dir = NULL;
  +                    char *context_path = NULL;
  +                    char *child_dir = NULL;
  +                    char *index = r->uri;
  +                    char *suffix = strchr(index+1,'/');
  +                    if( suffix != NULL ) {
  +                        int size = suffix - index;
  +                        context_dir = ap_pstrndup(r->pool,index,size);
  +                        /* Get the context child directory name */
  +                        index = index + size + 1;
  +                        suffix = strchr(index,'/');
  +                        if( suffix != NULL ) {
  +                            size = suffix - index;
  +                            child_dir = ap_pstrndup(r->pool,index,size);
  +                        } else {
  +                            child_dir = index;
  +                        }
  +                        /* Deny access to WEB-INF and META-INF directories */
  +                        if( child_dir != NULL ) {
  +                            jk_log(l, JK_LOG_DEBUG,             
  +                                "mod_jk::jk_translate, AutoAlias child_dir: %s\n",
  +                                 child_dir);
  +                            if( !strcasecmp(child_dir,"WEB-INF") ||
  +                                !strcasecmp(child_dir,"META-INF") ) {
  +                                jk_log(l, JK_LOG_DEBUG,
  +                                    "mod_jk::jk_translate, AutoAlias FORBIDDEN for URI: %s\n",
  +                                    r->uri);
  +                                return FORBIDDEN;
  +                            }
  +                        }
  +                    } else {
  +                        context_dir = ap_pstrdup(r->pool,index);
  +                    }
  +
  +                    context_path = ap_pstrcat(r->pool,conf->alias_dir,
  +                                              ap_os_escape_path(r->pool,context_dir,1),
  +                                              NULL);
  +                    if( context_path != NULL ) {
  +                        DIR *dir = ap_popendir(r->pool,context_path);
  +                        if( dir != NULL ) {
  +                            char *escurl = ap_os_escape_path(r->pool, r->uri, 1);
  +                            char *ret = ap_pstrcat(r->pool,conf->alias_dir,escurl,NULL);
  +                            ap_pclosedir(r->pool,dir);
  +                            /* Add code to verify real path ap_os_canonical_name */
  +                            if( ret != NULL ) {
  +                                jk_log(l, JK_LOG_DEBUG,
  +                                    "mod_jk::jk_translate, AutoAlias OK for file: %s\n",ret);
  +                                r->filename = ret;
  +                                return OK;
  +                            }
  +                        } else {
  +                            /* Deny access to war files in web app directory */
  +                            int size = strlen(context_dir);
  +                            if( size > 4 && !strcasecmp(context_dir+(size-4),".war") ) {
  +                                jk_log(l, JK_LOG_DEBUG,
  +                                    "mod_jk::jk_translate, AutoAlias FORBIDDEN for URI: %s\n",
  +                                    r->uri);
  +                                return FORBIDDEN;
  +                            }
  +                        }
  +                    }
  +                }
               }
           }
       }
  
  
  
  1.3       +11 -9     jakarta-tomcat-connectors/jk/native/common/jk_logger.h
  
  Index: jk_logger.h
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-connectors/jk/native/common/jk_logger.h,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- jk_logger.h	18 Jun 2001 14:15:49 -0000	1.2
  +++ jk_logger.h	21 Apr 2002 22:57:11 -0000	1.3
  @@ -58,7 +58,7 @@
   /***************************************************************************
    * Description: Logger object definitions                                  *
    * Author:      Gal Shachor <sh...@il.ibm.com>                           *
  - * Version:     $Revision: 1.2 $                                           *
  + * Version:     $Revision: 1.3 $                                           *
    ***************************************************************************/
   
   #ifndef JK_LOGGER_H
  @@ -81,20 +81,22 @@
   
   };
   
  -#define JK_LOG_DEBUG_LEVEL 0
  -#define JK_LOG_INFO_LEVEL  1
  -#define JK_LOG_ERROR_LEVEL 2
  -#define JK_LOG_EMERG_LEVEL 3
  +#define JK_LOG_DEBUG_LEVEL   0
  +#define JK_LOG_INFO_LEVEL    1
  +#define JK_LOG_ERROR_LEVEL   2
  +#define JK_LOG_EMERG_LEVEL   3
  +#define JK_LOG_REQUEST_LEVEL 4
   
   #define JK_LOG_DEBUG_VERB   "debug"
   #define JK_LOG_INFO_VERB    "info"
   #define JK_LOG_ERROR_VERB   "error"
   #define JK_LOG_EMERG_VERB   "emerg"
   
  -#define JK_LOG_DEBUG __FILE__,__LINE__,JK_LOG_DEBUG_LEVEL
  -#define JK_LOG_INFO  __FILE__,__LINE__,JK_LOG_INFO_LEVEL
  -#define JK_LOG_ERROR __FILE__,__LINE__,JK_LOG_ERROR_LEVEL
  -#define JK_LOG_EMERG __FILE__,__LINE__,JK_LOG_EMERG_LEVEL
  +#define JK_LOG_DEBUG   __FILE__,__LINE__,JK_LOG_DEBUG_LEVEL
  +#define JK_LOG_INFO    __FILE__,__LINE__,JK_LOG_INFO_LEVEL
  +#define JK_LOG_ERROR   __FILE__,__LINE__,JK_LOG_ERROR_LEVEL
  +#define JK_LOG_EMERG   __FILE__,__LINE__,JK_LOG_EMERG_LEVEL
  +#define JK_LOG_REQUEST __FILE__,NULL,JK_LOG_REQUEST_LEVEL
   
   #ifdef __cplusplus
   }
  
  
  
  1.14      +31 -2     jakarta-tomcat-connectors/jk/native/common/jk_uri_worker_map.c
  
  Index: jk_uri_worker_map.c
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-connectors/jk/native/common/jk_uri_worker_map.c,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- jk_uri_worker_map.c	7 Dec 2001 00:57:16 -0000	1.13
  +++ jk_uri_worker_map.c	21 Apr 2002 22:57:11 -0000	1.14
  @@ -67,7 +67,7 @@
    * servlet container.                                                      *
    *                                                                         *
    * Author:      Gal Shachor <sh...@il.ibm.com>                           *
  - * Version:     $Revision: 1.13 $                                           *
  + * Version:     $Revision: 1.14 $                                           *
    ***************************************************************************/
   
   #include "jk_pool.h"
  @@ -78,6 +78,8 @@
   #define MATCH_TYPE_CONTEXT  (1)
   #define MATCH_TYPE_SUFFIX   (2)
   #define MATCH_TYPE_GENERAL_SUFFIX (3) /* match all URIs of the form *ext */
  +/* match all context path URIs with a path component suffix */
  +#define MATCH_TYPE_CONTEXT_PATH (4)
   
   struct uri_worker_record {
       /* Original uri for logging */
  @@ -275,7 +277,18 @@
                */
                asterisk--;
                if ('/' == asterisk[0]) {
  -                if ('.' == asterisk[2]) {
  +                if ( 0 == strncmp("/*/",uri,3) ) {
  +                    /* general context path */
  +                    asterisk[1] = '\0';
  +                    uwr->worker_name = worker;
  +                    uwr->context = uri;
  +                    uwr->suffix  = asterisk + 2;
  +                    uwr->match_type = MATCH_TYPE_CONTEXT_PATH;
  +                    jk_log(l, JK_LOG_DEBUG,
  +                           "Into jk_uri_worker_map_t::uri_worker_map_open, "
  +                           "general context path rule %s*%s=%s was added\n",
  +                           uri, asterisk + 2, worker);
  +                } else if ('.' == asterisk[2]) {
                       /* suffix rule */
                       asterisk[1]      = 
                       asterisk[2]      = '\0';
  @@ -507,6 +520,22 @@
   			    longest_match = uwr->ctxt_len;
   			    best_match = i;
   			}
  +                    }
  +                } else if(MATCH_TYPE_CONTEXT_PATH == uwr->match_type) {
  +                    char *suffix_path = NULL;
  +                    if (strlen(uri) > 1 && (suffix_path = strchr(uri+1,'/')) != NULL) {
  +                        if (0 == strncmp(suffix_path,uwr->suffix,strlen(uwr->suffix))) {
  +                            if(uwr->ctxt_len >= longest_match) {
  +                                jk_log(l,
  +                                       JK_LOG_DEBUG,
  +                                       "jk_uri_worker_map_t::map_uri_to_worker, "
  +                                       "Found a general context path match %s -> *%s\n",
  +                                       uwr->worker_name,
  +                                       uwr->suffix );   
  +                                longest_match = uwr->ctxt_len;
  +                                best_match = i;
  +                            }
  +                        }
                       }
                   } else /* suffix match */ {
                       int suffix_start;
  
  
  
  1.13      +11 -6     jakarta-tomcat-connectors/jk/native/common/jk_util.c
  
  Index: jk_util.c
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-connectors/jk/native/common/jk_util.c,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- jk_util.c	6 Feb 2002 19:11:23 -0000	1.12
  +++ jk_util.c	21 Apr 2002 22:57:11 -0000	1.13
  @@ -59,7 +59,7 @@
    * Description: Utility functions (mainly configuration)                   *
    * Author:      Gal Shachor <sh...@il.ibm.com>                           *
    * Author:      Henri Gomez <hg...@slib.fr>                               *
  - * Version:     $Revision: 1.12 $                                           *
  + * Version:     $Revision: 1.13 $                                           *
    ***************************************************************************/
   
   
  @@ -127,7 +127,9 @@
                                    int level,
                                    const char *what)
   {
  -    if(l && l->level <= level && l->logger_private && what) {       
  +    if( l &&
  +        (l->level <= level || level == JK_LOG_REQUEST_LEVEL) &&
  +        l->logger_private && what) {
           unsigned sz = strlen(what);
           if(sz) {
               file_logger_t *p = l->logger_private;
  @@ -214,7 +216,7 @@
           return -1;
       }
   
  -    if(l->level <= level) {
  +    if((l->level <= level) || (level == JK_LOG_REQUEST_LEVEL)) {
   #ifdef NETWARE
   /* On NetWare, this can get called on a thread that has a limited stack so */
   /* we will allocate and free the temporary buffer in this function         */
  @@ -236,7 +238,8 @@
   #ifdef WIN32
   	set_time_str(buf, HUGE_BUFFER_SIZE);
   	used = strlen(buf);
  -        used += _snprintf(&buf[used], HUGE_BUFFER_SIZE, " [%s (%d)]: ", f, line);        
  +        if(line)
  +            used += _snprintf(&buf[used], HUGE_BUFFER_SIZE, " [%s (%d)]: ", f, line);        
   #elif defined(NETWARE) /* until we get a snprintf function */
           buf = (char *) malloc(HUGE_BUFFER_SIZE);
           if (NULL == buf)
  @@ -244,11 +247,13 @@
   
   	set_time_str(buf, HUGE_BUFFER_SIZE);
   	used = strlen(buf);
  -        used += sprintf(&buf[used], " [%s (%d)]: ", f, line);
  +        if(line)
  +            used += sprintf(&buf[used], " [%s (%d)]: ", f, line);
   #else 
   	set_time_str(buf, HUGE_BUFFER_SIZE);
   	used = strlen(buf);
  -        used += snprintf(&buf[used], HUGE_BUFFER_SIZE, " [%s (%d)]: ", f, line);        
  +        if(line)
  +            used += snprintf(&buf[used], HUGE_BUFFER_SIZE, " [%s (%d)]: ", f, line);        
   #endif
           if(used < 0) {
               return 0; /* [V] not sure what to return... */
  
  
  
  1.4       +76 -9     jakarta-tomcat-connectors/jk/doc/mod_jk-howto.html
  
  Index: mod_jk-howto.html
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-connectors/jk/doc/mod_jk-howto.html,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- mod_jk-howto.html	22 Jun 2001 14:44:52 -0000	1.3
  +++ mod_jk-howto.html	21 Apr 2002 22:57:11 -0000	1.4
  @@ -71,6 +71,7 @@
   <li><a href="#s71">Removing mod_jserv directives</a></li>
   <li><a href="#s72">Configuring Apache to use mod_jk</a></li>
   <li><a href="#s73">Assigning URLs to be redirected to Tomcat</a></li>
  +<li><a href="#s74">Configuring Apache to serve static web application files</a></li>
   </ul></li>
   <li><a href="#s8">Configuring Tomcat</a>
     <ul>
  @@ -507,11 +508,35 @@
    <li>You should specify a location where mod_jk is going to place its log file
        and a log level to be used. Use the <tt>JkLogFile</tt> and <tt>JkLogLevel</tt>
        configuration directives. Possible log levels are <i>debug</i>, <i>info</i>,
  -     <i>error</i> and <i>emerg</i>, but <i>info</i> should be your default
  -     selection.</li>
  +     <i>error</i>, and <i>emerg</i>, but <i>info</i> should be your
  +     default selection.</li>
    <li>The directive <tt>JkLogStampFormat</tt> will configure the date/time format
        found on mod_jk logfile. Using <tt>strftime()</tt> format string it's set by
        default to "[%a %b %d %H:%M:%S %Y] "</li> 
  + <li>The directive <tt>JkRequestLogFormat</tt> will configure the format of mod_jk
  +     individual request logging. Request logging is configured and enabled on a per
  +     virtual host basis.  To enable request logging for a virtual host just add
  +     a JkRequestLogFormat config.
  +     The syntax of the format string is similiar to the Apache LogFormat command,
  +     here is a list of the avaialbe request log format options:
  +     <ul>
  +       <li>%b - Bytes sent, excluding HTTP headers. In CLF format</li>
  +       <li>%B - Bytes sent, excluding HTTP headers.</li>
  +       <li>%H - The request protocol</li>
  +       <li>%m - The request method</li>
  +       <li>%p - The canonical Port of the server serving the request</li>
  +       <li>%q - The query string (prepended with a ? if a query string exists,
  +                otherwise an empty string)</li>
  +       <li>%r - First line of request</li>
  +       <li>%s - request HTTP status code</li>
  +       <li>%T - Requset duration, elapsed time to handle request in seconds '.'
  +                micro seconds</li>
  +       <li>%U - The URL path requested, not including any query string.</li>
  +       <li>%v - The canonical ServerName of the server serving the request.</li>
  +       <li>%V - The server name according to the UseCanonicalName setting.</li>
  +       <li>%w - Tomcat worker name</li>
  +     </ul>
  + </li>
   </ul>
   A simple example would be to include the following lines in your <tt>httpd.conf</tt> file:
   <blockquote><pre>
  @@ -537,18 +562,59 @@
   </pre>
   
   <p>For example the following directives will send all requests ending in
  -<tt>.jsp</tt> or beginning with <tt>/servlet</tt> to the &quot;<tt>ajp13</tt>&quot; worker,
  -but jsp requests to files located in /otherworker will go to &quot;<tt>remoteworker</tt>&quot;.
  +<tt>.jsp</tt> or with <tt>/servlet</tt> as the second path componenet to
  +the &quot;<tt>ajp13</tt>&quot; worker, but jsp requests to files located
  +in /otherworker will go to &quot;<tt>remoteworker</tt>&quot;.
   
   <blockquote><pre>
   JkMount /*.jsp ajp13
  -JkMount /servlet/* ajp13
  +JkMount /*/servlet/ ajp13
   JkMount /otherworker/*.jsp remoteworker
   </pre></blockquote>
   You  can use the <tt>JkMount</tt> directive at the top level or inside <tt>&lt;VirtualHost&gt;</tt>
   sections of your httpd.conf file.
   </div>
   
  +<h3><a name="s74">Configuring Apache to serve static web application files</a></h3>
  +<div class=subsection>
  +<p>If the Tomcat Host appBase (webapps) directory is accessible by the Apache
  +web server, Apache can be configured to serve web application context directory
  +static files instead of passing the request to Tomcat.</p>
  +
  +<p><b>Caution:</b> If Apache is configured to serve static pages for a web
  +application it bypasses any security contraints you may have configured in
  +your web application web.xml config file.</p>
  +
  +<p>Use Apache's Alias directive to map a single web application context directory
  +into Apache's document space for a VirtualHost:
  +
  +<pre>
  +# Static files in the examples webapp are served by apache
  +Alias /examples /export/home/web/host1/webapps/examples
  +
  +JkMount /*.jsp ajp13
  +JkMount /*/servlet/ ajp13
  +</pre>
  +</p>
  +
  +<p>Use the mod_jk JkAutoAlias directive to map all web application context
  +directories into Apache's document space. Attempts to access the <code>WEB-INF</code>
  +or <code>META-INF</code> directories within a web application context or a
  +Web Archive <code>*.war</code> within the Tomcat Host appBase (webapps) directory
  +will fail with an HTTP 403, Access Forbidden.</p>
  +<p>
  +Example configuration for an Apache VirtualHost:
  +
  +<pre>
  +# Static files in all Tomcat webapp context directories are served by apache
  +JkAutoAlias /export/home/web/host2/webapps
  +
  +JkMount /*.jsp ajp13
  +JkMount /*/servlet/ ajp13
  +</pre>
  +</p>
  +</div>
  +
   <hr>
   <h2><a name="s8">Configuring Tomcat</a></h2>
   
  @@ -741,13 +807,14 @@
   JkLogFile     /usr/local/apache/logs/mod_jk.log
   JkLogLevel    info
   
  -# First Virtual Host.
  +# First Virtual Host. Request logging is enabled.
   #
   &lt;VirtualHost 10.0.0.1:80&gt;
     DocumentRoot /web/host1
     ServerName host1.apache.org
  +  JkRequestLogFormat "%w \"%r\" %s %T"
     JkMount /*.jsp ajp13
  -  JkMount /servlet/* ajp13
  +  JkMount /*/servlet/ ajp13
   &lt;/VirtualHost&gt;
   
   # Second Virtual Host. Also accessible via HTTPS
  @@ -756,7 +823,7 @@
     DocumentRoot /web/host2
     ServerName host2.apache.org
     JkMount /*.jsp ajp13
  -  JkMount /servlet/* ajp13
  +  JkMount /*/servlet/ ajp13
   &lt;/VirtualHost&gt;
   
   &lt;VirtualHost 10.0.0.2:443&gt;
  @@ -764,7 +831,7 @@
     ServerName host2.apache.org
     SSLEngine On
     JkMount /*.jsp ajp13
  -  JkMount /servlet/* ajp13
  +  JkMount /*/servlet/ ajp13
   &lt;/VirtualHost&gt;
   
   </pre></blockquote>
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: cvs commit: jakarta-tomcat-connectors/jk/doc mod_jk-howto.html

Posted by co...@covalent.net.
On Mon, 22 Apr 2002, Glenn Nielsen wrote:

> Hmmm, this gives me an incentive to play around with Apache 2.0.

It's a nice server :-)

What would help the most is a 'common' implementation - i.e. have as much 
as possible independent of the server. 


> > Also, any chance to update this on native2 ? I'll do it later if you don't
> > have the time.
> > 
> 
> I need to look at jk2 anyway.
> 
> I'll see what I can do, I may not have the time to get to it until
> the weekend.

No hurry. But one more hand would really help... 

Costin


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: cvs commit: jakarta-tomcat-connectors/jk/doc mod_jk-howto.html

Posted by Glenn Nielsen <gl...@voyager.apg.more.net>.
costinm@covalent.net wrote:
> 
> Hi Glenn,
> 
> Could you update at least the apache2 connector ? This features makes
> sense on all servers actually ( i.e. IIS, etc ) - but we should have it
> at least in 1.3 and 2.0.
> 

Thanks.  You may have noticed I added several of your suggestions. :-)

Hmmm, this gives me an incentive to play around with Apache 2.0.

> Also, any chance to update this on native2 ? I'll do it later if you don't
> have the time.
> 

I need to look at jk2 anyway.

I'll see what I can do, I may not have the time to get to it until
the weekend.

Regards,

Glenn

> Costin
> 
> On 21 Apr 2002 glenn@apache.org wrote:
> 
> > glenn       02/04/21 15:57:11
> >
> >   Modified:    jk/native/apache-1.3 mod_jk.c
> >                jk/native/common jk_logger.h jk_uri_worker_map.c jk_util.c
> >                jk/doc   mod_jk-howto.html
> >   Log:
> >   Apache mod_jk 1.2 new features.
> >
> >   Added JkRequestLogFormat for Apache style request logging
> >   including Tocmat request latency in seconds and microseconds.
> >
> >   Added JkAutoAlias, this can be used to automatically Alias
> >   web application context directories so that static files
> >   can be served by Apache instead of Tomcat.  When configured,
> >   requests for a WAR file in the Tomcat appBase (webapps) directory
> >   are forbidden.  Requests for the WEB-INF and META-INF directories
> >   within a web application context dir are also forbidden and will
> >   return an HTTP 403 error.
> >
> >   Added ability to JkMount so that /*/servlet/ can be used to
> >   configure mod_jk to pass all servlet requests on to Tomcat
> >   for any web application context.
> >

----------------------------------------------------------------------
Glenn Nielsen             glenn@more.net | /* Spelin donut madder    |
MOREnet System Programming               |  * if iz ina coment.      |
Missouri Research and Education Network  |  */                       |
----------------------------------------------------------------------

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: cvs commit: jakarta-tomcat-connectors/jk/doc mod_jk-howto.html

Posted by co...@covalent.net.
Hi Glenn,

Could you update at least the apache2 connector ? This features makes 
sense on all servers actually ( i.e. IIS, etc ) - but we should have it 
at least in 1.3 and 2.0.

Also, any chance to update this on native2 ? I'll do it later if you don't
have the time.


Costin




On 21 Apr 2002 glenn@apache.org wrote:

> glenn       02/04/21 15:57:11
> 
>   Modified:    jk/native/apache-1.3 mod_jk.c
>                jk/native/common jk_logger.h jk_uri_worker_map.c jk_util.c
>                jk/doc   mod_jk-howto.html
>   Log:
>   Apache mod_jk 1.2 new features.
>   
>   Added JkRequestLogFormat for Apache style request logging
>   including Tocmat request latency in seconds and microseconds.
>   
>   Added JkAutoAlias, this can be used to automatically Alias
>   web application context directories so that static files
>   can be served by Apache instead of Tomcat.  When configured,
>   requests for a WAR file in the Tomcat appBase (webapps) directory
>   are forbidden.  Requests for the WEB-INF and META-INF directories
>   within a web application context dir are also forbidden and will
>   return an HTTP 403 error.
>   
>   Added ability to JkMount so that /*/servlet/ can be used to
>   configure mod_jk to pass all servlet requests on to Tomcat
>   for any web application context.
>   
>   Revision  Changes    Path
>   1.26      +521 -12   jakarta-tomcat-connectors/jk/native/apache-1.3/mod_jk.c
>   
>   Index: mod_jk.c
>   ===================================================================
>   RCS file: /home/cvs/jakarta-tomcat-connectors/jk/native/apache-1.3/mod_jk.c,v
>   retrieving revision 1.25
>   retrieving revision 1.26
>   diff -u -r1.25 -r1.26
>   --- mod_jk.c	3 Apr 2002 00:49:19 -0000	1.25
>   +++ mod_jk.c	21 Apr 2002 22:57:11 -0000	1.26
>   @@ -61,7 +61,7 @@
>     * Author:      Gal Shachor <sh...@il.ibm.com>                           *
>     *              Dan Milstein <da...@shore.net>                            *
>     *              Henri Gomez <hg...@slib.fr>                               *
>   - * Version:     $Revision: 1.25 $                                           *
>   + * Version:     $Revision: 1.26 $                                           *
>     ***************************************************************************/
>    
>    /*
>   @@ -101,6 +101,7 @@
>    
>    #define JK_WORKER_ID        ("jakarta.worker")
>    #define JK_HANDLER          ("jakarta-servlet")
>   +#define JK_DURATION         ("jakarta.worker.duration")
>    #define JK_MAGIC_TYPE       ("application/x-jakarta-servlet")
>    #define NULL_FOR_EMPTY(x)   ((x && !strlen(x)) ? NULL : x) 
>    
>   @@ -139,6 +140,18 @@
>        jk_uri_worker_map_t *uw_map;
>    
>        /*
>   +     * Automatic context path apache alias
>   +     */
>   +    char *alias_dir;
>   +
>   +    /*
>   +     * Request Logging
>   +     */
>   +
>   +    char *format_string;
>   +    array_header *format;
>   +
>   +    /*
>         * SSL Support
>         */
>        int  ssl_enable;
>   @@ -742,7 +755,7 @@
>    /*
>     * JkLogLevel Directive Handling
>     *
>   - * JkLogLevel debug/info/error/emerg
>   + * JkLogLevel debug/info/request/error/emerg
>     */
>    
>    static const char *jk_set_log_level(cmd_parms *cmd,
>   @@ -773,6 +786,402 @@
>    }
>    
>    /*
>   + * JkAutoAlias Directive Handling
>   + * 
>   + * JkAutoAlias application directory
>   + */
>   +
>   +static const char *jk_set_auto_alias(cmd_parms *cmd,
>   +                                    void *dummy,
>   +                                    char *directory)
>   +{
>   +    server_rec *s = cmd->server;
>   +    jk_server_conf_t *conf =
>   +        (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
>   +
>   +    conf->alias_dir = directory;
>   +
>   +    if (conf->alias_dir == NULL)
>   +        return "JkAutoAlias directory invalid";
>   +
>   +    return NULL;
>   +}
>   +
>   +/*****************************************************************
>   + *
>   + * Actually logging.
>   + */
>   +
>   +typedef const char *(*item_key_func) (request_rec *, char *);
>   +                                                             
>   +typedef struct {                                             
>   +    item_key_func func;
>   +    char *arg;         
>   +} request_log_format_item;
>   +
>   +static const char *process_item(request_rec *r,
>   +                          request_log_format_item *item)
>   +{
>   +    const char *cp;
>   +
>   +    cp = (*item->func) (r,item->arg);
>   +    return cp ? cp : "-";
>   +}
>   +
>   +static int request_log_transaction(request_rec *r,
>   +                                  jk_server_conf_t *conf)
>   +{
>   +    request_log_format_item *items;
>   +    char *str, *s;
>   +    int i;
>   +    int len = 0;
>   +    const char **strs;
>   +    int *strl;
>   +    array_header *format = conf->format;
>   +
>   +    strs = ap_palloc(r->pool, sizeof(char *) * (format->nelts));
>   +    strl = ap_palloc(r->pool, sizeof(int) * (format->nelts));
>   +    items = (request_log_format_item *) format->elts;
>   +    for (i = 0; i < format->nelts; ++i) {
>   +        strs[i] = process_item(r, &items[i]);
>   +    }
>   +    for (i = 0; i < format->nelts; ++i) {
>   +        len += strl[i] = strlen(strs[i]);
>   +    }
>   +    str = ap_palloc(r->pool, len + 1);
>   +    for (i = 0, s = str; i < format->nelts; ++i) {
>   +        memcpy(s, strs[i], strl[i]);
>   +        s += strl[i];
>   +    }
>   +    *s = 0;
>   +    jk_log(conf->log ? conf->log : main_log,JK_LOG_REQUEST,str);
>   +}
>   +
>   +/*****************************************************************
>   + *
>   + * Parsing the log format string
>   + */
>   +
>   +static char *format_integer(pool *p, int i)
>   +{
>   +    return ap_psprintf(p, "%d", i);
>   +}
>   + 
>   +static char *pfmt(pool *p, int i)
>   +{
>   +    if (i <= 0) {
>   +        return "-";
>   +    }
>   +    else {
>   +        return format_integer(p, i);
>   +    }
>   +}
>   +
>   +static const char *constant_item(request_rec *dummy, char *stuff)
>   +{
>   +    return stuff;
>   +}
>   +
>   +static const char *log_worker_name(request_rec *r, char *a)
>   +{
>   +    return ap_table_get(r->notes, JK_WORKER_ID);
>   +}
>   +
>   +
>   +static const char *log_request_duration(request_rec *r, char *a)
>   +{
>   +    return ap_table_get(r->notes, JK_DURATION);
>   +}
>   + 
>   +static const char *log_request_line(request_rec *r, char *a)
>   +{
>   +            /* NOTE: If the original request contained a password, we
>   +             * re-write the request line here to contain XXXXXX instead:
>   +             * (note the truncation before the protocol string for HTTP/0.9 requests)
>   +             * (note also that r->the_request contains the unmodified request)
>   +             */
>   +    return (r->parsed_uri.password) ? ap_pstrcat(r->pool, r->method, " ",
>   +                                         ap_unparse_uri_components(r->pool, &r->parsed_uri, 0),
>   +                                         r->assbackwards ? NULL : " ", r->protocol, NULL)
>   +                                        : r->the_request;
>   +}
>   +
>   +/* These next two routines use the canonical name:port so that log
>   + * parsers don't need to duplicate all the vhost parsing crud.
>   + */
>   +static const char *log_virtual_host(request_rec *r, char *a)
>   +{
>   +    return r->server->server_hostname;
>   +}
>   + 
>   +static const char *log_server_port(request_rec *r, char *a)
>   +{
>   +    return ap_psprintf(r->pool, "%u",
>   +        r->server->port ? r->server->port : ap_default_port(r));
>   +}
>   + 
>   +/* This respects the setting of UseCanonicalName so that
>   + * the dynamic mass virtual hosting trick works better.
>   + */
>   +static const char *log_server_name(request_rec *r, char *a)
>   +{
>   +    return ap_get_server_name(r);
>   +}
>   +
>   +static const char *log_request_uri(request_rec *r, char *a)
>   +{
>   +    return r->uri;
>   +}
>   +static const char *log_request_method(request_rec *r, char *a)
>   +{
>   +    return r->method;
>   +}
>   +
>   +static const char *log_request_protocol(request_rec *r, char *a)
>   +{
>   +    return r->protocol;
>   +}
>   +static const char *log_request_query(request_rec *r, char *a)
>   +{
>   +    return (r->args != NULL) ? ap_pstrcat(r->pool, "?", r->args, NULL)
>   +                             : "";
>   +}                  
>   +static const char *log_status(request_rec *r, char *a)
>   +{                  
>   +    return pfmt(r->pool,r->status);
>   +}                  
>   +                   
>   +static const char *clf_log_bytes_sent(request_rec *r, char *a)
>   +{                  
>   +    if (!r->sent_bodyct) {
>   +        return "-";
>   +    }              
>   +    else {        
>   +        long int bs;
>   +        ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
>   +        return ap_psprintf(r->pool, "%ld", bs);
>   +    }              
>   +}                  
>   +    
>   +static const char *log_bytes_sent(request_rec *r, char *a)
>   +{                  
>   +    if (!r->sent_bodyct) {
>   +        return "0";
>   +    }              
>   +    else {        
>   +        long int bs;
>   +        ap_bgetopt(r->connection->client, BO_BYTECT, &bs);
>   +        return ap_psprintf(r->pool, "%ld", bs);
>   +    }              
>   +}
>   +
>   +static struct log_item_list {
>   +    char ch;
>   +    item_key_func func;
>   +} log_item_keys[] = {
>   +
>   +    {
>   +        'T', log_request_duration
>   +    },
>   +    {
>   +        'r', log_request_line
>   +    },
>   +    {
>   +        'U', log_request_uri
>   +    },
>   +    {
>   +        's', log_status
>   +    },
>   +    {
>   +        'b', clf_log_bytes_sent
>   +    },
>   +    {
>   +        'B', log_bytes_sent
>   +    },
>   +    {
>   +        'V', log_server_name
>   +    },
>   +    {
>   +        'v', log_virtual_host
>   +    },
>   +    {
>   +        'p', log_server_port
>   +    },
>   +    {
>   +        'H', log_request_protocol
>   +    },
>   +    {
>   +        'm', log_request_method
>   +    },
>   +    {
>   +        'q', log_request_query
>   +    },
>   +    {
>   +        'w', log_worker_name
>   +    },
>   +    {
>   +        '\0'
>   +    }
>   +};
>   +
>   +static struct log_item_list *find_log_func(char k)
>   +{
>   +    int i;
>   +
>   +    for (i = 0; log_item_keys[i].ch; ++i)
>   +        if (k == log_item_keys[i].ch) {
>   +            return &log_item_keys[i];
>   +        }
>   +
>   +    return NULL;
>   +}
>   +
>   +static char *parse_request_log_misc_string(pool *p,
>   +                                           request_log_format_item *it,
>   +                                           const char **sa)
>   +{
>   +    const char *s;
>   +    char *d;
>   +
>   +    it->func = constant_item;
>   +
>   +    s = *sa;
>   +    while (*s && *s != '%') {
>   +        s++;
>   +    }
>   +    /*
>   +     * This might allocate a few chars extra if there's a backslash
>   +     * escape in the format string.
>   +     */
>   +    it->arg = ap_palloc(p, s - *sa + 1);
>   +
>   +    d = it->arg;
>   +    s = *sa;
>   +    while (*s && *s != '%') {
>   +        if (*s != '\\') {
>   +            *d++ = *s++;
>   +        }
>   +        else {
>   +            s++;
>   +            switch (*s) {
>   +            case '\\':
>   +                *d++ = '\\';
>   +                s++;
>   +                break;
>   +            case 'n':
>   +                *d++ = '\n';
>   +                s++;
>   +                break;
>   +            case 't':
>   +                *d++ = '\t';
>   +                s++;
>   +                break;
>   +            default:
>   +                /* copy verbatim */
>   +                *d++ = '\\';
>   +                /*
>   +                 * Allow the loop to deal with this *s in the normal
>   +                 * fashion so that it handles end of string etc.
>   +                 * properly.
>   +                 */
>   +                break;
>   +            }
>   +        }
>   +    }
>   +    *d = '\0';
>   +
>   +    *sa = s;
>   +    return NULL;
>   +}
>   +
>   +static char *parse_request_log_item(pool *p,
>   +                                    request_log_format_item *it,
>   +                                    const char **sa)
>   +{
>   +    const char *s = *sa;
>   +    int i;
>   +    struct log_item_list *l;
>   +
>   +    if (*s != '%') {
>   +        return parse_request_log_misc_string(p, it, sa);
>   +    }
>   +    
>   +    ++s;
>   +    it->arg = "";               /* For safety's sake... */
>   +    
>   +    l = find_log_func(*s++);
>   +    if (!l) {
>   +        char dummy[2];
>   +
>   +        dummy[0] = s[-1];
>   +        dummy[1] = '\0';
>   +        return ap_pstrcat(p, "Unrecognized JkRequestLogFormat directive %",
>   +                          dummy, NULL);
>   +    }
>   +    it->func = l->func;
>   +    *sa = s;
>   +    return NULL;
>   +}
>   +
>   +static array_header *parse_request_log_string(pool *p, const char *s,
>   +                                              const char **err)
>   +{
>   +    array_header *a = ap_make_array(p, 15, sizeof(request_log_format_item));
>   +    char *res;
>   +
>   +    while (*s) {
>   +        if ((res = parse_request_log_item(p, (request_log_format_item *) ap_push_array(a), &s))) {
>   +            *err = res;
>   +            return NULL;
>   +        }
>   +    }    
>   +     
>   +    s = "\n";
>   +    parse_request_log_item(p, (request_log_format_item *) ap_push_array(a), &s);
>   +    return a;
>   +}
>   +
>   +/*
>   + * JkRequestLogFormat Directive Handling
>   + *
>   + * JkRequestLogFormat format string
>   + *
>   + * %b - Bytes sent, excluding HTTP headers. In CLF format
>   + * %B - Bytes sent, excluding HTTP headers.             
>   + * %H - The request protocol              
>   + * %m - The request method
>   + * %p - The canonical Port of the server serving the request
>   + * %q - The query string (prepended with a ? if a query string exists,
>   + *      otherwise an empty string)
>   + * %r - First line of request
>   + * %s - request HTTP status code
>   + * %T - Requset duration, elapsed time to handle request in seconds '.' micro seconds
>   + * %U - The URL path requested, not including any query string.
>   + * %v - The canonical ServerName of the server serving the request.
>   + * %V - The server name according to the UseCanonicalName setting.
>   + * %w - Tomcat worker name
>   + */
>   +
>   +static const char *jk_set_request_log_format(cmd_parms *cmd,
>   +                                             void *dummy,    
>   +                                             char *format)
>   +{
>   +    const char *err_string = NULL;
>   +    server_rec *s = cmd->server;
>   +    jk_server_conf_t *conf =
>   +        (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
>   +
>   +    conf->format_string = ap_pstrdup(cmd->pool,format);
>   +    if( format != NULL ) {
>   +        conf->format = parse_request_log_string(cmd->pool, format, &err_string);
>   +    }
>   +    if( conf->format == NULL )
>   +        return "JkRequestLogFormat format array NULL";
>   +
>   +    return err_string;
>   +}
>   +
>   +/*
>     * JkExtractSSL Directive Handling
>     *
>     * JkExtractSSL On/Off
>   @@ -1006,14 +1415,23 @@
>        /*
>         * JkLogFile & JkLogLevel specifies to where should the plugin log
>         * its information and how much.
>   -	 * JkLogStampFormat specify the time-stamp to be used on log
>   +     * JkLogStampFormat specify the time-stamp to be used on log
>         */
>        {"JkLogFile", jk_set_log_file, NULL, RSRC_CONF, TAKE1,
>         "Full path to the Jakarta mod_jk module log file"},
>        {"JkLogLevel", jk_set_log_level, NULL, RSRC_CONF, TAKE1,
>   -     "The Jakarta mod_jk module log level, can be debug, info, error or emerg"},
>   +     "The Jakarta mod_jk module log level, can be debug, info, request, error, or emerg"},
>        {"JkLogStampFormat", jk_set_log_fmt, NULL, RSRC_CONF, TAKE1,
>         "The Jakarta mod_jk module log format, follow strftime synthax"},
>   +    {"JkRequestLogFormat", jk_set_request_log_format, NULL, RSRC_CONF, TAKE1,
>   +     "The Jakarta mod_jk module request log format string"},
>   +
>   +    /*
>   +     * Automatically Alias webapp context directories into the Apache
>   +     * document space.
>   +     */
>   +    {"JkAutoAlias", jk_set_auto_alias, NULL, RSRC_CONF, TAKE1,
>   +     "The Jakarta mod_jk module automatic context apache alias directory"},
>    
>        /*
>         * Apache has multiple SSL modules (for example apache_ssl, stronghold
>   @@ -1093,6 +1511,7 @@
>            jk_worker_t *worker = wc_get_worker_for_name(worker_name, l);
>    
>            if(worker) {
>   +            struct timeval tv_begin,tv_end;
>                int rc = JK_FALSE;
>                apache_private_data_t private_data;
>                jk_ws_service_t s;
>   @@ -1107,7 +1526,10 @@
>    
>                s.ws_private = &private_data;
>                s.pool = &private_data.p;            
>   -            
>   +            if(conf->format != NULL) {
>   +                gettimeofday(&tv_begin, NULL);
>   +            }
>   +
>                if(init_ws_service(&private_data, &s, conf)) {
>                    jk_endpoint_t *end = NULL;
>                    if(worker->get_endpoint(worker, &end, l)) {
>   @@ -1131,6 +1553,21 @@
>                        }
>                        end->done(&end, l);
>                    }
>   +                if(conf->format != NULL) {
>   +                    char *duration = NULL;
>   +                    char *status = NULL;
>   +                    long micro,seconds;
>   +                    gettimeofday(&tv_end, NULL);
>   +                    if( tv_end.tv_usec < tv_begin.tv_usec ) {
>   +                        tv_end.tv_usec += 1000000;
>   +                        tv_end.tv_sec--;
>   +                    }
>   +                    micro = tv_end.tv_usec - tv_begin.tv_usec;
>   +                    seconds = tv_end.tv_sec - tv_begin.tv_sec;
>   +                    duration = ap_psprintf(r->pool,"%.1d.%.6d",seconds,micro);
>   +                    ap_table_setn(r->notes, JK_DURATION, duration);
>   +                    request_log_transaction(r,conf);
>   +                }
>                }
>    
>                jk_close_pool(&private_data.p);
>   @@ -1152,12 +1589,15 @@
>        jk_server_conf_t *c =
>            (jk_server_conf_t *) ap_pcalloc(p, sizeof(jk_server_conf_t));
>    
>   -    c->worker_file = NULL;
>   -    c->log_file    = NULL;
>   -    c->log_level   = -1;
>   -    c->log         = NULL;
>   -    c->mountcopy   = JK_FALSE;
>   -    c->options     = JK_OPT_FWDURIDEFAULT;
>   +    c->worker_file   = NULL;
>   +    c->log_file      = NULL;
>   +    c->log_level     = -1;
>   +    c->log           = NULL;
>   +    c->alias_dir     = NULL;
>   +    c->format_string = NULL;
>   +    c->format        = NULL;
>   +    c->mountcopy     = JK_FALSE;
>   +    c->options       = JK_OPT_FWDURIDEFAULT;
>    
>        /*
>         * By default we will try to gather SSL info. 
>   @@ -1332,11 +1772,80 @@
>                (jk_server_conf_t *)ap_get_module_config(r->server->module_config, &jk_module);
>    
>            if(conf) {
>   -            char *worker = map_uri_to_worker(conf->uw_map, r->uri, conf->log ? conf->log : main_log);
>   +            jk_logger_t *l = conf->log ? conf->log : main_log;
>   +            char *worker = map_uri_to_worker(conf->uw_map, r->uri, l);
>    
>                if(worker) {
>                    r->handler = ap_pstrdup(r->pool, JK_HANDLER);
>                    ap_table_setn(r->notes, JK_WORKER_ID, worker);
>   +            } else if(conf->alias_dir != NULL) {
>   +                /* Automatically map uri to a context static file */
>   +                jk_log(l, JK_LOG_DEBUG,
>   +                    "mod_jk::jk_translate, check alias_dir: %s\n",conf->alias_dir);
>   +                if (strlen(r->uri) > 1) {
>   +                    /* Get the context directory name */
>   +                    char *context_dir = NULL;
>   +                    char *context_path = NULL;
>   +                    char *child_dir = NULL;
>   +                    char *index = r->uri;
>   +                    char *suffix = strchr(index+1,'/');
>   +                    if( suffix != NULL ) {
>   +                        int size = suffix - index;
>   +                        context_dir = ap_pstrndup(r->pool,index,size);
>   +                        /* Get the context child directory name */
>   +                        index = index + size + 1;
>   +                        suffix = strchr(index,'/');
>   +                        if( suffix != NULL ) {
>   +                            size = suffix - index;
>   +                            child_dir = ap_pstrndup(r->pool,index,size);
>   +                        } else {
>   +                            child_dir = index;
>   +                        }
>   +                        /* Deny access to WEB-INF and META-INF directories */
>   +                        if( child_dir != NULL ) {
>   +                            jk_log(l, JK_LOG_DEBUG,             
>   +                                "mod_jk::jk_translate, AutoAlias child_dir: %s\n",
>   +                                 child_dir);
>   +                            if( !strcasecmp(child_dir,"WEB-INF") ||
>   +                                !strcasecmp(child_dir,"META-INF") ) {
>   +                                jk_log(l, JK_LOG_DEBUG,
>   +                                    "mod_jk::jk_translate, AutoAlias FORBIDDEN for URI: %s\n",
>   +                                    r->uri);
>   +                                return FORBIDDEN;
>   +                            }
>   +                        }
>   +                    } else {
>   +                        context_dir = ap_pstrdup(r->pool,index);
>   +                    }
>   +
>   +                    context_path = ap_pstrcat(r->pool,conf->alias_dir,
>   +                                              ap_os_escape_path(r->pool,context_dir,1),
>   +                                              NULL);
>   +                    if( context_path != NULL ) {
>   +                        DIR *dir = ap_popendir(r->pool,context_path);
>   +                        if( dir != NULL ) {
>   +                            char *escurl = ap_os_escape_path(r->pool, r->uri, 1);
>   +                            char *ret = ap_pstrcat(r->pool,conf->alias_dir,escurl,NULL);
>   +                            ap_pclosedir(r->pool,dir);
>   +                            /* Add code to verify real path ap_os_canonical_name */
>   +                            if( ret != NULL ) {
>   +                                jk_log(l, JK_LOG_DEBUG,
>   +                                    "mod_jk::jk_translate, AutoAlias OK for file: %s\n",ret);
>   +                                r->filename = ret;
>   +                                return OK;
>   +                            }
>   +                        } else {
>   +                            /* Deny access to war files in web app directory */
>   +                            int size = strlen(context_dir);
>   +                            if( size > 4 && !strcasecmp(context_dir+(size-4),".war") ) {
>   +                                jk_log(l, JK_LOG_DEBUG,
>   +                                    "mod_jk::jk_translate, AutoAlias FORBIDDEN for URI: %s\n",
>   +                                    r->uri);
>   +                                return FORBIDDEN;
>   +                            }
>   +                        }
>   +                    }
>   +                }
>                }
>            }
>        }
>   
>   
>   
>   1.3       +11 -9     jakarta-tomcat-connectors/jk/native/common/jk_logger.h
>   
>   Index: jk_logger.h
>   ===================================================================
>   RCS file: /home/cvs/jakarta-tomcat-connectors/jk/native/common/jk_logger.h,v
>   retrieving revision 1.2
>   retrieving revision 1.3
>   diff -u -r1.2 -r1.3
>   --- jk_logger.h	18 Jun 2001 14:15:49 -0000	1.2
>   +++ jk_logger.h	21 Apr 2002 22:57:11 -0000	1.3
>   @@ -58,7 +58,7 @@
>    /***************************************************************************
>     * Description: Logger object definitions                                  *
>     * Author:      Gal Shachor <sh...@il.ibm.com>                           *
>   - * Version:     $Revision: 1.2 $                                           *
>   + * Version:     $Revision: 1.3 $                                           *
>     ***************************************************************************/
>    
>    #ifndef JK_LOGGER_H
>   @@ -81,20 +81,22 @@
>    
>    };
>    
>   -#define JK_LOG_DEBUG_LEVEL 0
>   -#define JK_LOG_INFO_LEVEL  1
>   -#define JK_LOG_ERROR_LEVEL 2
>   -#define JK_LOG_EMERG_LEVEL 3
>   +#define JK_LOG_DEBUG_LEVEL   0
>   +#define JK_LOG_INFO_LEVEL    1
>   +#define JK_LOG_ERROR_LEVEL   2
>   +#define JK_LOG_EMERG_LEVEL   3
>   +#define JK_LOG_REQUEST_LEVEL 4
>    
>    #define JK_LOG_DEBUG_VERB   "debug"
>    #define JK_LOG_INFO_VERB    "info"
>    #define JK_LOG_ERROR_VERB   "error"
>    #define JK_LOG_EMERG_VERB   "emerg"
>    
>   -#define JK_LOG_DEBUG __FILE__,__LINE__,JK_LOG_DEBUG_LEVEL
>   -#define JK_LOG_INFO  __FILE__,__LINE__,JK_LOG_INFO_LEVEL
>   -#define JK_LOG_ERROR __FILE__,__LINE__,JK_LOG_ERROR_LEVEL
>   -#define JK_LOG_EMERG __FILE__,__LINE__,JK_LOG_EMERG_LEVEL
>   +#define JK_LOG_DEBUG   __FILE__,__LINE__,JK_LOG_DEBUG_LEVEL
>   +#define JK_LOG_INFO    __FILE__,__LINE__,JK_LOG_INFO_LEVEL
>   +#define JK_LOG_ERROR   __FILE__,__LINE__,JK_LOG_ERROR_LEVEL
>   +#define JK_LOG_EMERG   __FILE__,__LINE__,JK_LOG_EMERG_LEVEL
>   +#define JK_LOG_REQUEST __FILE__,NULL,JK_LOG_REQUEST_LEVEL
>    
>    #ifdef __cplusplus
>    }
>   
>   
>   
>   1.14      +31 -2     jakarta-tomcat-connectors/jk/native/common/jk_uri_worker_map.c
>   
>   Index: jk_uri_worker_map.c
>   ===================================================================
>   RCS file: /home/cvs/jakarta-tomcat-connectors/jk/native/common/jk_uri_worker_map.c,v
>   retrieving revision 1.13
>   retrieving revision 1.14
>   diff -u -r1.13 -r1.14
>   --- jk_uri_worker_map.c	7 Dec 2001 00:57:16 -0000	1.13
>   +++ jk_uri_worker_map.c	21 Apr 2002 22:57:11 -0000	1.14
>   @@ -67,7 +67,7 @@
>     * servlet container.                                                      *
>     *                                                                         *
>     * Author:      Gal Shachor <sh...@il.ibm.com>                           *
>   - * Version:     $Revision: 1.13 $                                           *
>   + * Version:     $Revision: 1.14 $                                           *
>     ***************************************************************************/
>    
>    #include "jk_pool.h"
>   @@ -78,6 +78,8 @@
>    #define MATCH_TYPE_CONTEXT  (1)
>    #define MATCH_TYPE_SUFFIX   (2)
>    #define MATCH_TYPE_GENERAL_SUFFIX (3) /* match all URIs of the form *ext */
>   +/* match all context path URIs with a path component suffix */
>   +#define MATCH_TYPE_CONTEXT_PATH (4)
>    
>    struct uri_worker_record {
>        /* Original uri for logging */
>   @@ -275,7 +277,18 @@
>                 */
>                 asterisk--;
>                 if ('/' == asterisk[0]) {
>   -                if ('.' == asterisk[2]) {
>   +                if ( 0 == strncmp("/*/",uri,3) ) {
>   +                    /* general context path */
>   +                    asterisk[1] = '\0';
>   +                    uwr->worker_name = worker;
>   +                    uwr->context = uri;
>   +                    uwr->suffix  = asterisk + 2;
>   +                    uwr->match_type = MATCH_TYPE_CONTEXT_PATH;
>   +                    jk_log(l, JK_LOG_DEBUG,
>   +                           "Into jk_uri_worker_map_t::uri_worker_map_open, "
>   +                           "general context path rule %s*%s=%s was added\n",
>   +                           uri, asterisk + 2, worker);
>   +                } else if ('.' == asterisk[2]) {
>                        /* suffix rule */
>                        asterisk[1]      = 
>                        asterisk[2]      = '\0';
>   @@ -507,6 +520,22 @@
>    			    longest_match = uwr->ctxt_len;
>    			    best_match = i;
>    			}
>   +                    }
>   +                } else if(MATCH_TYPE_CONTEXT_PATH == uwr->match_type) {
>   +                    char *suffix_path = NULL;
>   +                    if (strlen(uri) > 1 && (suffix_path = strchr(uri+1,'/')) != NULL) {
>   +                        if (0 == strncmp(suffix_path,uwr->suffix,strlen(uwr->suffix))) {
>   +                            if(uwr->ctxt_len >= longest_match) {
>   +                                jk_log(l,
>   +                                       JK_LOG_DEBUG,
>   +                                       "jk_uri_worker_map_t::map_uri_to_worker, "
>   +                                       "Found a general context path match %s -> *%s\n",
>   +                                       uwr->worker_name,
>   +                                       uwr->suffix );   
>   +                                longest_match = uwr->ctxt_len;
>   +                                best_match = i;
>   +                            }
>   +                        }
>                        }
>                    } else /* suffix match */ {
>                        int suffix_start;
>   
>   
>   
>   1.13      +11 -6     jakarta-tomcat-connectors/jk/native/common/jk_util.c
>   
>   Index: jk_util.c
>   ===================================================================
>   RCS file: /home/cvs/jakarta-tomcat-connectors/jk/native/common/jk_util.c,v
>   retrieving revision 1.12
>   retrieving revision 1.13
>   diff -u -r1.12 -r1.13
>   --- jk_util.c	6 Feb 2002 19:11:23 -0000	1.12
>   +++ jk_util.c	21 Apr 2002 22:57:11 -0000	1.13
>   @@ -59,7 +59,7 @@
>     * Description: Utility functions (mainly configuration)                   *
>     * Author:      Gal Shachor <sh...@il.ibm.com>                           *
>     * Author:      Henri Gomez <hg...@slib.fr>                               *
>   - * Version:     $Revision: 1.12 $                                           *
>   + * Version:     $Revision: 1.13 $                                           *
>     ***************************************************************************/
>    
>    
>   @@ -127,7 +127,9 @@
>                                     int level,
>                                     const char *what)
>    {
>   -    if(l && l->level <= level && l->logger_private && what) {       
>   +    if( l &&
>   +        (l->level <= level || level == JK_LOG_REQUEST_LEVEL) &&
>   +        l->logger_private && what) {
>            unsigned sz = strlen(what);
>            if(sz) {
>                file_logger_t *p = l->logger_private;
>   @@ -214,7 +216,7 @@
>            return -1;
>        }
>    
>   -    if(l->level <= level) {
>   +    if((l->level <= level) || (level == JK_LOG_REQUEST_LEVEL)) {
>    #ifdef NETWARE
>    /* On NetWare, this can get called on a thread that has a limited stack so */
>    /* we will allocate and free the temporary buffer in this function         */
>   @@ -236,7 +238,8 @@
>    #ifdef WIN32
>    	set_time_str(buf, HUGE_BUFFER_SIZE);
>    	used = strlen(buf);
>   -        used += _snprintf(&buf[used], HUGE_BUFFER_SIZE, " [%s (%d)]: ", f, line);        
>   +        if(line)
>   +            used += _snprintf(&buf[used], HUGE_BUFFER_SIZE, " [%s (%d)]: ", f, line);        
>    #elif defined(NETWARE) /* until we get a snprintf function */
>            buf = (char *) malloc(HUGE_BUFFER_SIZE);
>            if (NULL == buf)
>   @@ -244,11 +247,13 @@
>    
>    	set_time_str(buf, HUGE_BUFFER_SIZE);
>    	used = strlen(buf);
>   -        used += sprintf(&buf[used], " [%s (%d)]: ", f, line);
>   +        if(line)
>   +            used += sprintf(&buf[used], " [%s (%d)]: ", f, line);
>    #else 
>    	set_time_str(buf, HUGE_BUFFER_SIZE);
>    	used = strlen(buf);
>   -        used += snprintf(&buf[used], HUGE_BUFFER_SIZE, " [%s (%d)]: ", f, line);        
>   +        if(line)
>   +            used += snprintf(&buf[used], HUGE_BUFFER_SIZE, " [%s (%d)]: ", f, line);        
>    #endif
>            if(used < 0) {
>                return 0; /* [V] not sure what to return... */
>   
>   
>   
>   1.4       +76 -9     jakarta-tomcat-connectors/jk/doc/mod_jk-howto.html
>   
>   Index: mod_jk-howto.html
>   ===================================================================
>   RCS file: /home/cvs/jakarta-tomcat-connectors/jk/doc/mod_jk-howto.html,v
>   retrieving revision 1.3
>   retrieving revision 1.4
>   diff -u -r1.3 -r1.4
>   --- mod_jk-howto.html	22 Jun 2001 14:44:52 -0000	1.3
>   +++ mod_jk-howto.html	21 Apr 2002 22:57:11 -0000	1.4
>   @@ -71,6 +71,7 @@
>    <li><a href="#s71">Removing mod_jserv directives</a></li>
>    <li><a href="#s72">Configuring Apache to use mod_jk</a></li>
>    <li><a href="#s73">Assigning URLs to be redirected to Tomcat</a></li>
>   +<li><a href="#s74">Configuring Apache to serve static web application files</a></li>
>    </ul></li>
>    <li><a href="#s8">Configuring Tomcat</a>
>      <ul>
>   @@ -507,11 +508,35 @@
>     <li>You should specify a location where mod_jk is going to place its log file
>         and a log level to be used. Use the <tt>JkLogFile</tt> and <tt>JkLogLevel</tt>
>         configuration directives. Possible log levels are <i>debug</i>, <i>info</i>,
>   -     <i>error</i> and <i>emerg</i>, but <i>info</i> should be your default
>   -     selection.</li>
>   +     <i>error</i>, and <i>emerg</i>, but <i>info</i> should be your
>   +     default selection.</li>
>     <li>The directive <tt>JkLogStampFormat</tt> will configure the date/time format
>         found on mod_jk logfile. Using <tt>strftime()</tt> format string it's set by
>         default to "[%a %b %d %H:%M:%S %Y] "</li> 
>   + <li>The directive <tt>JkRequestLogFormat</tt> will configure the format of mod_jk
>   +     individual request logging. Request logging is configured and enabled on a per
>   +     virtual host basis.  To enable request logging for a virtual host just add
>   +     a JkRequestLogFormat config.
>   +     The syntax of the format string is similiar to the Apache LogFormat command,
>   +     here is a list of the avaialbe request log format options:
>   +     <ul>
>   +       <li>%b - Bytes sent, excluding HTTP headers. In CLF format</li>
>   +       <li>%B - Bytes sent, excluding HTTP headers.</li>
>   +       <li>%H - The request protocol</li>
>   +       <li>%m - The request method</li>
>   +       <li>%p - The canonical Port of the server serving the request</li>
>   +       <li>%q - The query string (prepended with a ? if a query string exists,
>   +                otherwise an empty string)</li>
>   +       <li>%r - First line of request</li>
>   +       <li>%s - request HTTP status code</li>
>   +       <li>%T - Requset duration, elapsed time to handle request in seconds '.'
>   +                micro seconds</li>
>   +       <li>%U - The URL path requested, not including any query string.</li>
>   +       <li>%v - The canonical ServerName of the server serving the request.</li>
>   +       <li>%V - The server name according to the UseCanonicalName setting.</li>
>   +       <li>%w - Tomcat worker name</li>
>   +     </ul>
>   + </li>
>    </ul>
>    A simple example would be to include the following lines in your <tt>httpd.conf</tt> file:
>    <blockquote><pre>
>   @@ -537,18 +562,59 @@
>    </pre>
>    
>    <p>For example the following directives will send all requests ending in
>   -<tt>.jsp</tt> or beginning with <tt>/servlet</tt> to the &quot;<tt>ajp13</tt>&quot; worker,
>   -but jsp requests to files located in /otherworker will go to &quot;<tt>remoteworker</tt>&quot;.
>   +<tt>.jsp</tt> or with <tt>/servlet</tt> as the second path componenet to
>   +the &quot;<tt>ajp13</tt>&quot; worker, but jsp requests to files located
>   +in /otherworker will go to &quot;<tt>remoteworker</tt>&quot;.
>    
>    <blockquote><pre>
>    JkMount /*.jsp ajp13
>   -JkMount /servlet/* ajp13
>   +JkMount /*/servlet/ ajp13
>    JkMount /otherworker/*.jsp remoteworker
>    </pre></blockquote>
>    You  can use the <tt>JkMount</tt> directive at the top level or inside <tt>&lt;VirtualHost&gt;</tt>
>    sections of your httpd.conf file.
>    </div>
>    
>   +<h3><a name="s74">Configuring Apache to serve static web application files</a></h3>
>   +<div class=subsection>
>   +<p>If the Tomcat Host appBase (webapps) directory is accessible by the Apache
>   +web server, Apache can be configured to serve web application context directory
>   +static files instead of passing the request to Tomcat.</p>
>   +
>   +<p><b>Caution:</b> If Apache is configured to serve static pages for a web
>   +application it bypasses any security contraints you may have configured in
>   +your web application web.xml config file.</p>
>   +
>   +<p>Use Apache's Alias directive to map a single web application context directory
>   +into Apache's document space for a VirtualHost:
>   +
>   +<pre>
>   +# Static files in the examples webapp are served by apache
>   +Alias /examples /export/home/web/host1/webapps/examples
>   +
>   +JkMount /*.jsp ajp13
>   +JkMount /*/servlet/ ajp13
>   +</pre>
>   +</p>
>   +
>   +<p>Use the mod_jk JkAutoAlias directive to map all web application context
>   +directories into Apache's document space. Attempts to access the <code>WEB-INF</code>
>   +or <code>META-INF</code> directories within a web application context or a
>   +Web Archive <code>*.war</code> within the Tomcat Host appBase (webapps) directory
>   +will fail with an HTTP 403, Access Forbidden.</p>
>   +<p>
>   +Example configuration for an Apache VirtualHost:
>   +
>   +<pre>
>   +# Static files in all Tomcat webapp context directories are served by apache
>   +JkAutoAlias /export/home/web/host2/webapps
>   +
>   +JkMount /*.jsp ajp13
>   +JkMount /*/servlet/ ajp13
>   +</pre>
>   +</p>
>   +</div>
>   +
>    <hr>
>    <h2><a name="s8">Configuring Tomcat</a></h2>
>    
>   @@ -741,13 +807,14 @@
>    JkLogFile     /usr/local/apache/logs/mod_jk.log
>    JkLogLevel    info
>    
>   -# First Virtual Host.
>   +# First Virtual Host. Request logging is enabled.
>    #
>    &lt;VirtualHost 10.0.0.1:80&gt;
>      DocumentRoot /web/host1
>      ServerName host1.apache.org
>   +  JkRequestLogFormat "%w \"%r\" %s %T"
>      JkMount /*.jsp ajp13
>   -  JkMount /servlet/* ajp13
>   +  JkMount /*/servlet/ ajp13
>    &lt;/VirtualHost&gt;
>    
>    # Second Virtual Host. Also accessible via HTTPS
>   @@ -756,7 +823,7 @@
>      DocumentRoot /web/host2
>      ServerName host2.apache.org
>      JkMount /*.jsp ajp13
>   -  JkMount /servlet/* ajp13
>   +  JkMount /*/servlet/ ajp13
>    &lt;/VirtualHost&gt;
>    
>    &lt;VirtualHost 10.0.0.2:443&gt;
>   @@ -764,7 +831,7 @@
>      ServerName host2.apache.org
>      SSLEngine On
>      JkMount /*.jsp ajp13
>   -  JkMount /servlet/* ajp13
>   +  JkMount /*/servlet/ ajp13
>    &lt;/VirtualHost&gt;
>    
>    </pre></blockquote>
>   
>   
>   
> 
> --
> To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@jakarta.apache.org>
> 
> 


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>