Add additional configuration options to the RemoteIpValve to control ports.
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Mon, 9 May 2011 10:09:44 +0000 (10:09 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Mon, 9 May 2011 10:09:44 +0000 (10:09 +0000)
These are required by my TCK test environment since I have multiple connectors (with different ports) configured all using the one Valve.
If this has the desired effect, I'll port the changes to the RemoteIpFilter.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1100940 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/valves/LocalStrings.properties
java/org/apache/catalina/valves/RemoteIpValve.java
webapps/docs/changelog.xml
webapps/docs/config/valve.xml

index bb2398b..24bfee4 100644 (file)
@@ -40,6 +40,7 @@ errorReportValve.rootCauseInLogs=The full stack trace of the root cause is avail
 
 # Remote IP valve
 remoteIpValve.syntax=Invalid regular expressions [{0}] provided.
+remoteIpValve.invalidPortHeader=Invalid value [{0}] found for port in HTP header [{1}]
 
 sslValve.certError=Failed to process certificate string [{0}] to create a java.security.cert.X509Certificate object
 sslValve.invalidProvider=The SSL provider specified on the connector associated with this request of [{0}] is invalid. The certificate data could not be processed.
index 7b8a825..bbb6195 100644 (file)
@@ -403,6 +403,8 @@ public class RemoteIpValve extends ValveBase {
      */
     private int httpsServerPort = 443;
     
+    private boolean changeLocalPort = false;
+
     /**
      * @see #setInternalProxies(String)
      */
@@ -422,6 +424,8 @@ public class RemoteIpValve extends ValveBase {
      */
     private String protocolHeaderHttpsValue = "https";
     
+    private String portHeader = null;
+
     /**
      * @see #setProxiesHeader(String)
      */
@@ -461,6 +465,36 @@ public class RemoteIpValve extends ValveBase {
         return httpServerPort;
     }
     
+    public boolean isChangeLocalPort() {
+        return changeLocalPort;
+    }
+
+    public void setChangeLocalPort(boolean changeLocalPort) {
+        this.changeLocalPort = changeLocalPort;
+    }
+
+    /**
+     * Obtain the name of the HTTP header used to override the value returned
+     * by {@link Request#getServerPort()} and (optionally depending on {link
+     * {@link #isChangeLocalPort()} {@link Request#getLocalPort()}.
+     * 
+     * @return  The HTTP header name
+     */
+    public String getPortHeader() {
+        return portHeader;
+    }
+
+    /**
+     * Set the name of the HTTP header used to override the value returned
+     * by {@link Request#getServerPort()} and (optionally depending on {link
+     * {@link #isChangeLocalPort()} {@link Request#getLocalPort()}.
+     * 
+     * @param   portHeader  The HTTP header name
+     */
+    public void setPortHeader(String portHeader) {
+        this.portHeader = portHeader;
+    }
+
     /**
      * Return descriptive information about this Valve implementation.
      */
@@ -611,13 +645,13 @@ public class RemoteIpValve extends ValveBase {
                     // use request.coyoteRequest.scheme instead of request.setScheme() because request.setScheme() is no-op in Tomcat 6.0
                     request.getCoyoteRequest().scheme().setString("https");
                     
-                    request.setServerPort(httpsServerPort);
+                    setPorts(request, httpsServerPort);
                 } else {
                     request.setSecure(false);
                     // use request.coyoteRequest.scheme instead of request.setScheme() because request.setScheme() is no-op in Tomcat 6.0
                     request.getCoyoteRequest().scheme().setString("http");
                     
-                    request.setServerPort(httpServerPort);
+                    setPorts(request, httpServerPort);
                 }
             }
             
@@ -657,6 +691,26 @@ public class RemoteIpValve extends ValveBase {
             request.setServerPort(originalServerPort);
         }
     }
+
+    private void setPorts(Request request, int defaultPort) {
+        int port = defaultPort;
+        if (portHeader != null) {
+            String portHeaderValue = request.getHeader(portHeader);
+            if (portHeaderValue != null) {
+                try {
+                    port = Integer.parseInt(portHeaderValue);
+                } catch (NumberFormatException nfe) {
+                    log.debug(sm.getString(
+                            "remoteIpValve.invalidPortHeader",
+                            portHeaderValue, portHeader), nfe);
+                }
+            }
+        }
+        request.setServerPort(port);
+        if (changeLocalPort) {
+            request.getCoyoteRequest().setLocalPort(port);
+        }
+    }
     
     /**
      * <p>
index d52d667..7c62d24 100644 (file)
         Use correct class loader when loading Servlet classes in
         StandardWrapper. (markt)
       </fix>
+      <add>
+        Provide additional configuration options for the RemoteIpValve to allow
+        greater control over the values returned by
+        ServletRequest#getServerPort() and ServletRequest#getLocalPort() when
+        using this valve. (markt)
+      </add>
     </changelog>
   </subsection>
 </section>
index 4fe4ad4..06f945d 100644 (file)
         default of <code>null</code> is used.</p>
       </attribute>
 
+      <attribute name="portHeader" required="false">
+        <p>Name of the HTTP Header read by this valve that holds the port
+        used by the client to connect to the proxy. If not specified, the
+        default of <code>null</code> is used.</p>
+      </attribute>
+
       <attribute name="protocolHeaderHttpsValue" required="false">
         <p>Value of the <strong>protocolHeader</strong> to indicate that it is
         an HTTPS request. If not specified, the default of <code>https</code> is
       <attribute name="httpServerPort" required="false">
          <p>Value returned by <code>ServletRequest.getServerPort()</code> 
          when the <strong>protocolHeader</strong> indicates <code>http</code> 
-         protocol. If not specified, the default of <code>80</code> is
-        used.</p>
+         protocol and no <strong>portHeader</strong> is present. If not
+         specified, the default of <code>80</code> is used.</p>
       </attribute>
 
       <attribute name="httpsServerPort" required="false">
          <p>Value returned by <code>ServletRequest.getServerPort()</code> 
          when the <strong>protocolHeader</strong> indicates <code>https</code> 
-         protocol. If not specified, the default of <code>443</code> is
-        used.</p>
+         protocol and no <strong>portHeader</strong> is present. If not
+         specified, the default of <code>443</code> is used.</p>
       </attribute>
       
+      <attribute name="changeLocalPort" required="false">
+        <p>If <code>true</code>, the value returned by
+        <code>ServletRequest.getLocalPort()</code> and
+        <code>ServletRequest.getServerPort()</code> is modified by the this
+        valve. If not specified, the default of <code>false</code> is used.</p>
+      </attribute>
+
     </attributes>
 
   </subsection>