You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2010/06/02 17:12:47 UTC

svn commit: r950587 - in /tomcat/trunk: java/org/apache/catalina/AccessLog.java java/org/apache/catalina/connector/CoyoteAdapter.java java/org/apache/catalina/valves/AccessLogValve.java webapps/docs/config/valve.xml

Author: markt
Date: Wed Jun  2 15:12:36 2010
New Revision: 950587

URL: http://svn.apache.org/viewvc?rev=950587&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=49099
Hooking the CoyoteAdaptor into the existing AccessLog wasn't as invasive as I feared so go that route to log requests rejected by the Adaptor before the request/response reaches the AcessLogValve

Added:
    tomcat/trunk/java/org/apache/catalina/AccessLog.java   (with props)
Modified:
    tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
    tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java
    tomcat/trunk/webapps/docs/config/valve.xml

Added: tomcat/trunk/java/org/apache/catalina/AccessLog.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/AccessLog.java?rev=950587&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/AccessLog.java (added)
+++ tomcat/trunk/java/org/apache/catalina/AccessLog.java Wed Jun  2 15:12:36 2010
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina;
+
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+
+
+/**
+ * Intended for use by a {@link Valve} to indicate that the {@link Valve}
+ * provides access logging. It is used by the Tomcat internals (the
+ * {@link org.apache.catalina.connector.CoyoteAdapter} at the time of writing)
+ * to identify a Valve that logs access requests so requests that are rejected
+ * earlier in the processing chain can still be added to the access log.
+ * Implementations of this interface should be robust against the provided
+ * {@link Request} and {@link Response} objects being null, having null
+ * attributes or any other 'oddness' that may result from attempting to log
+ * a request that was almost certainly rejected because it was mal-formed.
+ */
+public interface AccessLog {
+
+    /**
+     * Add the request/response to the access log using the specified processing
+     * time.
+     * 
+     * @param request   Request (associated with the response) to log
+     * @param response  Response (associated with the request) to log
+     * @param time      Time taken to process the request/response in
+     *                  milliseconds (use 0 if not known) 
+     */
+    public void log(Request request, Response response, long time);
+}

Propchange: tomcat/trunk/java/org/apache/catalina/AccessLog.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java?rev=950587&r1=950586&r2=950587&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java Wed Jun  2 15:12:36 2010
@@ -24,8 +24,13 @@ import java.util.EnumSet;
 
 import javax.servlet.SessionTrackingMode;
 
+import org.apache.catalina.AccessLog;
+import org.apache.catalina.Container;
 import org.apache.catalina.Context;
+import org.apache.catalina.Engine;
 import org.apache.catalina.Globals;
+import org.apache.catalina.Host;
+import org.apache.catalina.Valve;
 import org.apache.catalina.Wrapper;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.catalina.comet.CometEvent;
@@ -115,6 +120,11 @@ public class CoyoteAdapter implements Ad
     protected static URLEncoder urlEncoder;
 
 
+    /**
+     * Access log to use for rejected requests
+     */
+    private volatile AccessLog accessLog = null;
+    
     // ----------------------------------------------------- Static Initializer
 
 
@@ -512,12 +522,14 @@ public class CoyoteAdapter implements Ad
         } catch (IOException ioe) {
             res.setStatus(400);
             res.setMessage("Invalid URI: " + ioe.getMessage());
+            getAccessLog().log(request, response, 0);
             return false;
         }
         // Normalization
         if (!normalize(req.decodedURI())) {
             res.setStatus(400);
             res.setMessage("Invalid URI");
+            getAccessLog().log(request, response, 0);
             return false;
         }
         // Character decoding
@@ -526,6 +538,7 @@ public class CoyoteAdapter implements Ad
         if (!checkNormalize(req.decodedURI())) {
             res.setStatus(400);
             res.setMessage("Invalid URI character encoding");
+            getAccessLog().log(request, response, 0);
             return false;
         }
 
@@ -585,6 +598,7 @@ public class CoyoteAdapter implements Ad
             res.setStatus(405);
             res.addHeader("Allow", header);
             res.setMessage("TRACE method is not allowed");
+            getAccessLog().log(request, response, 0);
             return false;
         }
 
@@ -623,6 +637,7 @@ public class CoyoteAdapter implements Ad
                 redirectPath = redirectPath + "?" + query;
             }
             response.sendRedirect(redirectPath);
+            getAccessLog().log(request, response, 0);
             return false;
         }
 
@@ -1075,4 +1090,61 @@ public class CoyoteAdapter implements Ad
     }
 
 
+    /**
+     * Obtain a reference to the access log to use to log rejected requests.
+     * 
+     * @return
+     */
+    protected AccessLog getAccessLog() {
+        if (accessLog != null) {
+            return accessLog;
+        }
+        
+        // First look in Engine for associated service
+        Engine engine = (Engine) connector.getService().getContainer();
+        accessLog = findAccessLog(engine);
+        if (accessLog != null) {
+            return accessLog;
+        }
+        
+        // Then look in default host
+        Host defaultHost = (Host) engine.findChild(engine.getDefaultHost());
+        accessLog = findAccessLog(defaultHost);
+        if (accessLog != null) {
+            return accessLog;
+        }
+            
+        // Then look in ROOT context of default host
+        Context defaultContext = (Context) defaultHost.findChild("/");
+        accessLog = findAccessLog(defaultContext);
+        if (accessLog != null) {
+            return accessLog;
+        }
+
+        accessLog = new NoopAccessLog(); 
+        return accessLog;
+    }
+    
+    private AccessLog findAccessLog(Container container) {
+        if (container == null) {
+            return new NoopAccessLog();
+        }
+
+        Valve valves[] = container.getPipeline().getValves();
+        for (Valve valve : valves) {
+            if (valve instanceof AccessLog) {
+                return (AccessLog) valve;
+            }
+        }
+        return null;
+    }
+    
+    private static final class NoopAccessLog implements AccessLog {
+
+        @Override
+        public void log(Request request, Response response, long time) {
+            // NOOP
+        }
+        
+    }
 }

Modified: tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java?rev=950587&r1=950586&r2=950587&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java (original)
+++ tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java Wed Jun  2 15:12:36 2010
@@ -36,6 +36,7 @@ import javax.servlet.ServletException;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpSession;
 
+import org.apache.catalina.AccessLog;
 import org.apache.catalina.LifecycleException;
 import org.apache.catalina.LifecycleState;
 import org.apache.catalina.connector.Request;
@@ -118,7 +119,7 @@ import org.apache.juli.logging.LogFactor
  * @version $Id$
  */
 
-public class AccessLogValve extends ValveBase {
+public class AccessLogValve extends ValveBase implements AccessLog {
 
     private static final Log log = LogFactory.getLog(AccessLogValve.class);
 
@@ -563,25 +564,30 @@ public class AccessLogValve extends Valv
             
             long t2 = System.currentTimeMillis();
             long time = t2 - t1;
-    
-            if (logElements == null || condition != null
-                    && null != request.getRequest().getAttribute(condition)) {
-                return;
-            }
-    
-            Date date = getDate();
-            StringBuilder result = new StringBuilder(128);
-    
-            for (int i = 0; i < logElements.length; i++) {
-                logElements[i].addElement(result, date, request, response, time);
-            }
-    
-            log(result.toString());
+
+            log(request,response, time);
         } else
             getNext().invoke(request, response);       
     }
 
     
+    public void log(Request request, Response response, long time) {
+        if (logElements == null || condition != null
+                && null != request.getRequest().getAttribute(condition)) {
+            return;
+        }
+
+        Date date = getDate();
+        StringBuilder result = new StringBuilder(128);
+
+        for (int i = 0; i < logElements.length; i++) {
+            logElements[i].addElement(result, date, request, response, time);
+        }
+
+        log(result.toString());
+    }
+
+
     /**
      * Rename the existing log file to something else. Then open the
      * old log file name up once again. Intended to be called by a JMX

Modified: tomcat/trunk/webapps/docs/config/valve.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/valve.xml?rev=950587&r1=950586&r2=950587&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/valve.xml (original)
+++ tomcat/trunk/webapps/docs/config/valve.xml Wed Jun  2 15:12:36 2010
@@ -66,6 +66,15 @@
     <code>Host</code>, or <code>Engine</code>), and
     will record ALL requests processed by that container.</p>
 
+    <p>Some requests (e.g. those with mal-formed URLs) may be rejected by Tomcat
+    before they are passed to a container. In these cases Tomcat will look in
+    the <code>Engine</code>, then the default <code>Host</code> for the
+    <code>Engine</code> and finally the ROOT (or default) <code>Context</code>
+    for the default <code>Host</code> for an <code>AccessLogValve</code> or
+    other <code>AccessLog</code> implementation. Tomcat will use the first
+    <code>AccessLog</code> implementation found to log those requests that are
+    rejected before they are passed to a container.</p>
+
   </subsection>
 
   <subsection name="Attributes">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: svn commit: r950587 - in /tomcat/trunk: java/org/apache/catalina/AccessLog.java java/org/apache/catalina/connector/CoyoteAdapter.java java/org/apache/catalina/valves/AccessLogValve.java webapps/docs/config/valve.xml

Posted by Mark Thomas <ma...@apache.org>.
On 02/06/2010 16:40, Tim Funk wrote:
> Cool - One (very minor) nit ... A safer size might be 500.
> A typical User agent string by itself is 100+ characters which will
> easily take the log line over 128 characters.
> 
> StringBuilder result = new StringBuilder(128);

User agent isn't logged by default so I think 128 is probably OK.

Mark



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: svn commit: r950587 - in /tomcat/trunk: java/org/apache/catalina/AccessLog.java java/org/apache/catalina/connector/CoyoteAdapter.java java/org/apache/catalina/valves/AccessLogValve.java webapps/docs/config/valve.xml

Posted by Tim Funk <fu...@apache.org>.
Cool - One (very minor) nit ... A safer size might be 500.
A typical User agent string by itself is 100+ characters which will 
easily take the log line over 128 characters.

StringBuilder result = new StringBuilder(128);

-Tim


On 6/2/2010 11:12 AM, markt@apache.org wrote:
> Author: markt
> Date: Wed Jun  2 15:12:36 2010
> New Revision: 950587
>
> URL: http://svn.apache.org/viewvc?rev=950587&view=rev
> Log:
> Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=49099
> Hooking the CoyoteAdaptor into the existing AccessLog wasn't as invasive as I feared so go that route to log requests rejected by the Adaptor before the request/response reaches the AcessLogValve
>
> Added:
>      tomcat/trunk/java/org/apache/catalina/AccessLog.java   (with props)
> Modified:
>      tomcat/trunk/java/org/apache/catalina/connector/CoyoteAdapter.java
>      tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java
>      tomcat/trunk/webapps/docs/config/valve.xml
>
> Added: tomcat/trunk/java/org/apache/catalina/AccessLog.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/AccessLog.java?rev=950587&view=auto
> ==============================================================================
> --- tomcat/trunk/java/org/apache/catalina/AccessLog.java (added)
> +++ tomcat/trunk/java/org/apache/catalina/AccessLog.java Wed Jun  2 15:12:36 2010
> @@ -0,0 +1,47 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache License, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +package org.apache.catalina;
> +
> +import org.apache.catalina.connector.Request;
> +import org.apache.catalina.connector.Response;
> +
> +
> +/**
> + * Intended for use by a {@link Valve} to indicate that the {@link Valve}
> + * provides access logging. It is used by the Tomcat internals (the
> + * {@link org.apache.catalina.connector.CoyoteAdapter} at the time of writing)
> + * to identify a Valve that logs access requests so requests that are rejected
> + * earlier in the processing chain can still be added to the access log.
> + * Implementations of this interface should be robust against the provided
> + * {@link Request} and {@link Response} objects being null, having null
> + * attributes or any other 'oddness' that may result from attempting to log
> + * a request that was almost certainly rejected because it was mal-formed.
> + */
> +public interface AccessLog {
> +
> +    /**
> +     * Add the request/response to the access log using the specified processing
> +     * time.
> +     *
> +     * @param request   Request (associated with the response) to log
> +     * @param response  Response (associated with the request) to log
> +     * @param time      Time taken to process the request/response in
> +     *                  milliseconds (use 0 if not known)
> +     */
> +    public void log(Request request, Response response, long time);
> +}
>
> Propchange: tomcat/trunk/java/org/apache/catalina/AccessLog.java
> ------------------------------------------------------------------------------
>      svn:eol-style = native
>

> Modified: tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java?rev=950587&r1=950586&r2=950587&view=diff

> +    public void log(Request request, Response response, long time) {
> +        if (logElements == null || condition != null
> +&&  null != request.getRequest().getAttribute(condition)) {
> +            return;
> +        }
> +
> +        Date date = getDate();
> +        StringBuilder result = new StringBuilder(128);
> +
> +        for (int i = 0; i<  logElements.length; i++) {
> +            logElements[i].addElement(result, date, request, response, time);
> +        }
> +
> +        log(result.toString());
> +    }

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org