Improve IE 6 bug detection logic.

This commit is contained in:
Ben Alex 2004-04-29 02:14:20 +00:00
parent 136c27aff3
commit 2421268baa
2 changed files with 55 additions and 120 deletions

View File

@ -25,14 +25,14 @@ import javax.servlet.ServletRequest;
* <code>ServletRequest.getServerPort()</code>. * <code>ServletRequest.getServerPort()</code>.
* *
* <P> * <P>
* If either the <code>alwaysHttpPort</code> or <code>alwaysHttpsPort</code> * This class is capable of handling the IE bug which results in an incorrect
* properties are set, these ports will be used <B>instead of</B> those * URL being presented in the header subsequent to a redirect to a different
* obtained from the <code>ServletRequest.getServerPort()</code> method. * scheme and port where the port is not a well-known number (ie 80 or 443).
* Setting these properties will cause the * Handling involves detecting an incorrect response from
* <code>ServletRequest.getScheme()</code> method to be used to determine * <code>ServletRequest.getServerPort()</code> for the scheme (eg a HTTP
* whether a request was HTTP or HTTPS, and then return the port defined by * request on 8443) and then determining the real server port (eg HTTP request
* the <code>always[Scheme]Port</code> property. You can configure zero, one * is really on 8080). The map of valid ports is obtained from the configured
* or both of these properties. * {@link PortMapper}.
* </p> * </p>
* *
* @author Ben Alex * @author Ben Alex
@ -41,52 +41,45 @@ import javax.servlet.ServletRequest;
public class PortResolverImpl implements InitializingBean, PortResolver { public class PortResolverImpl implements InitializingBean, PortResolver {
//~ Instance fields ======================================================== //~ Instance fields ========================================================
private int alwaysHttpPort = 0; private PortMapper portMapper = new PortMapperImpl();
private int alwaysHttpsPort = 0;
//~ Methods ================================================================ //~ Methods ================================================================
public void setAlwaysHttpPort(int alwaysHttpPort) { public void setPortMapper(PortMapper portMapper) {
this.alwaysHttpPort = alwaysHttpPort; this.portMapper = portMapper;
} }
public int getAlwaysHttpPort() { public PortMapper getPortMapper() {
return alwaysHttpPort; return portMapper;
}
public void setAlwaysHttpsPort(int alwaysHttpsPort) {
this.alwaysHttpsPort = alwaysHttpsPort;
}
public int getAlwaysHttpsPort() {
return alwaysHttpsPort;
} }
public int getServerPort(ServletRequest request) { public int getServerPort(ServletRequest request) {
if ("http".equals(request.getScheme().toLowerCase()) int result = request.getServerPort();
&& (alwaysHttpPort != 0)) {
return alwaysHttpPort; if ("http".equals(request.getScheme().toLowerCase())) {
Integer http = portMapper.lookupHttpPort(new Integer(result));
if (http != null) {
// IE 6 bug
result = http.intValue();
}
} }
if ("https".equals(request.getScheme().toLowerCase()) if ("https".equals(request.getScheme().toLowerCase())) {
&& (alwaysHttpsPort != 0)) { Integer https = portMapper.lookupHttpsPort(new Integer(result));
return alwaysHttpsPort;
if (https != null) {
// IE 6 bug
result = https.intValue();
}
} }
return request.getServerPort(); return result;
} }
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
if ((alwaysHttpPort != 0) if (portMapper == null) {
&& ((alwaysHttpPort > 65535) || (alwaysHttpPort < 0))) { throw new IllegalArgumentException("portMapper required");
throw new IllegalArgumentException(
"alwaysHttpPort must be between 1 and 65535");
}
if ((alwaysHttpsPort != 0)
&& ((alwaysHttpsPort > 65535) || (alwaysHttpsPort < 0))) {
throw new IllegalArgumentException(
"alwaysHttpsPort must be between 1 and 65535");
} }
} }
} }

View File

@ -47,15 +47,31 @@ public class PortResolverImplTests extends TestCase {
junit.textui.TestRunner.run(PortResolverImplTests.class); junit.textui.TestRunner.run(PortResolverImplTests.class);
} }
public void testDetectsBuggyIeHttpRequest() throws Exception {
PortResolverImpl pr = new PortResolverImpl();
pr.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest("X");
request.setServerPort(8443);
request.setScheme("HTtP"); // proves case insensitive handling
assertEquals(8080, pr.getServerPort(request));
}
public void testDetectsBuggyIeHttpsRequest() throws Exception {
PortResolverImpl pr = new PortResolverImpl();
pr.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest("X");
request.setServerPort(8080);
request.setScheme("HTtPs"); // proves case insensitive handling
assertEquals(8443, pr.getServerPort(request));
}
public void testGettersSetters() throws Exception { public void testGettersSetters() throws Exception {
PortResolverImpl pr = new PortResolverImpl(); PortResolverImpl pr = new PortResolverImpl();
assertEquals(0, pr.getAlwaysHttpPort()); assertTrue(pr.getPortMapper() != null);
assertEquals(0, pr.getAlwaysHttpsPort()); pr.setPortMapper(new PortMapperImpl());
assertTrue(pr.getPortMapper() != null);
pr.setAlwaysHttpPort(80);
pr.setAlwaysHttpsPort(443);
assertEquals(80, pr.getAlwaysHttpPort());
assertEquals(443, pr.getAlwaysHttpsPort());
} }
public void testNormalOperation() throws Exception { public void testNormalOperation() throws Exception {
@ -67,78 +83,4 @@ public class PortResolverImplTests extends TestCase {
request.setServerPort(1021); request.setServerPort(1021);
assertEquals(1021, pr.getServerPort(request)); assertEquals(1021, pr.getServerPort(request));
} }
public void testOverridesHttp() throws Exception {
PortResolverImpl pr = new PortResolverImpl();
pr.setAlwaysHttpPort(495);
pr.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest("X");
request.setServerPort(7676);
request.setScheme("HTtP"); // proves case insensitive handling
assertEquals(495, pr.getServerPort(request));
request.setScheme("https");
assertEquals(7676, pr.getServerPort(request));
}
public void testOverridesHttps() throws Exception {
PortResolverImpl pr = new PortResolverImpl();
pr.setAlwaysHttpsPort(987);
pr.afterPropertiesSet();
MockHttpServletRequest request = new MockHttpServletRequest("X");
request.setServerPort(6949);
request.setScheme("HTtPs"); // proves case insensitive handling
assertEquals(987, pr.getServerPort(request));
request.setScheme("http");
assertEquals(6949, pr.getServerPort(request));
}
public void testRejectsOutOfRangeHttp() throws Exception {
PortResolverImpl pr = new PortResolverImpl();
pr.setAlwaysHttpPort(9999999);
try {
pr.afterPropertiesSet();
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertEquals("alwaysHttpPort must be between 1 and 65535",
expected.getMessage());
}
pr.setAlwaysHttpPort(-49);
try {
pr.afterPropertiesSet();
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertEquals("alwaysHttpPort must be between 1 and 65535",
expected.getMessage());
}
}
public void testRejectsOutOfRangeHttps() throws Exception {
PortResolverImpl pr = new PortResolverImpl();
pr.setAlwaysHttpsPort(9999999);
try {
pr.afterPropertiesSet();
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertEquals("alwaysHttpsPort must be between 1 and 65535",
expected.getMessage());
}
pr.setAlwaysHttpsPort(-49);
try {
pr.afterPropertiesSet();
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertEquals("alwaysHttpsPort must be between 1 and 65535",
expected.getMessage());
}
}
} }