Browse Source

Add support for excess slashes within static file request path. (#11827)

tags/8.10.0.alpha1
Anna Koskinen 4 years ago
parent
commit
32aba81d1d
No account linked to committer's email address

+ 26
- 7
server/src/main/java/com/vaadin/server/VaadinServlet.java View File

import java.util.Properties; import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Pattern;


import javax.servlet.ServletConfig; import javax.servlet.ServletConfig;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
*/ */
private static boolean scssCompileWarWarningEmitted = false; private static boolean scssCompileWarWarningEmitted = false;


/**
* Pattern for matching request paths that start with /VAADIN/, multiple
* slashes allowed on either side.
*/
private static Pattern staticFileRequestPathPatternVaadin = Pattern
.compile("^/+VAADIN/.*");

/** /**
* Returns the default theme. Must never return null. * Returns the default theme. Must never return null.
* *
String decodedPath = null; String decodedPath = null;
String contextPath = null; String contextPath = null;
try { try {
// pathInfo should be already decoded, but some containers do not decode it,
// hence we use getRequestURI instead.
decodedPath = URLDecoder.decode(request.getRequestURI(), StandardCharsets.UTF_8.name());
contextPath = URLDecoder.decode(request.getContextPath(), StandardCharsets.UTF_8.name());
// pathInfo should be already decoded, but some containers do not
// decode it, hence we use getRequestURI instead.
decodedPath = URLDecoder.decode(request.getRequestURI(),
StandardCharsets.UTF_8.name());
contextPath = URLDecoder.decode(request.getContextPath(),
StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new RuntimeException("An error occurred during decoding URL.",e);
throw new RuntimeException("An error occurred during decoding URL.",
e);
} }
// Possible context path needs to be removed // Possible context path needs to be removed
String filePath = decodedPath.substring(contextPath.length()); String filePath = decodedPath.substring(contextPath.length());
String servletPath = request.getServletPath(); String servletPath = request.getServletPath();
// Possible servlet path needs to be removed // Possible servlet path needs to be removed
if (!servletPath.isEmpty() && !servletPath.equals("/VAADIN")
if (!servletPath.isEmpty() && !servletPath.equals("/VAADIN")
&& filePath.startsWith(servletPath)) { && filePath.startsWith(servletPath)) {
filePath = filePath.substring(servletPath.length()); filePath = filePath.substring(servletPath.length());
} }
// Servlet mapped as /* serves at /VAADIN // Servlet mapped as /* serves at /VAADIN
// Servlet mapped as /foo/bar/* serves at /foo/bar/VAADIN // Servlet mapped as /foo/bar/* serves at /foo/bar/VAADIN
if (filePath.startsWith("/VAADIN/")) {

// Matches request paths /VAADIN/*, //VAADIN/* etc.
if (staticFileRequestPathPatternVaadin.matcher(filePath).matches()) {
// Remove any extra slashes from the beginning,
// later occurrences don't interfere
while (filePath.startsWith("//")) {
filePath = filePath.substring(1);
}
return filePath; return filePath;
} }

String servletPrefixedPath = servletPath + filePath; String servletPrefixedPath = servletPath + filePath;
// Servlet mapped as /VAADIN/* // Servlet mapped as /VAADIN/*
if (servletPrefixedPath.startsWith("/VAADIN/")) { if (servletPrefixedPath.startsWith("/VAADIN/")) {

+ 14
- 0
test/spring-boot-subcontext/src/test/java/com/example/VaadinSpringBootSmokeIT.java View File



@Test @Test
public void testPageLoadsAndButtonWorks() { public void testPageLoadsAndButtonWorks() {
getDriver().navigate()
.to("http://localhost:" + port + DemoApplication.CONTEXT);
runSmokeTest();
}

@Test
public void testPageLoadsAndButtonWorksWithExtraSlash() {
getDriver().navigate() getDriver().navigate()
.to("http://localhost:" + port + "/" + DemoApplication.CONTEXT); .to("http://localhost:" + port + "/" + DemoApplication.CONTEXT);
runSmokeTest(); runSmokeTest();


@Test @Test
public void testSubPathPageLoadsAndButtonWorks() { public void testSubPathPageLoadsAndButtonWorks() {
getDriver().navigate().to("http://localhost:" + port
+ DemoApplication.CONTEXT + "/" + SubPathUI.SUBPATH);
runSmokeTest();
}

@Test
public void testSubPathPageLoadsAndButtonWorksWithExtraSlash() {
getDriver().navigate().to("http://localhost:" + port + "/" getDriver().navigate().to("http://localhost:" + port + "/"
+ DemoApplication.CONTEXT + "/" + SubPathUI.SUBPATH); + DemoApplication.CONTEXT + "/" + SubPathUI.SUBPATH);
runSmokeTest(); runSmokeTest();

Loading…
Cancel
Save