Change-Id: I6891827a1fb99216d4e286c761d1384a88000604tags/8.0.0.alpha6
@@ -31,7 +31,6 @@ import java.net.MalformedURLException; | |||
import java.net.URISyntaxException; | |||
import java.net.URL; | |||
import java.net.URLConnection; | |||
import java.net.URLDecoder; | |||
import java.nio.charset.Charset; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
@@ -720,25 +719,9 @@ public class VaadinServlet extends HttpServlet implements Constants { | |||
private boolean serveStaticResources(HttpServletRequest request, | |||
HttpServletResponse response) throws IOException, ServletException { | |||
String pathInfo = request.getPathInfo(); | |||
if (pathInfo == null) { | |||
return false; | |||
} | |||
String decodedRequestURI = URLDecoder.decode(request.getRequestURI(), | |||
"UTF-8"); | |||
if ((request.getContextPath() != null) | |||
&& (decodedRequestURI.startsWith("/VAADIN/"))) { | |||
serveStaticResourcesInVAADIN(decodedRequestURI, request, response); | |||
return true; | |||
} | |||
String decodedContextPath = URLDecoder.decode(request.getContextPath(), | |||
"UTF-8"); | |||
if (decodedRequestURI.startsWith(decodedContextPath + "/VAADIN/")) { | |||
serveStaticResourcesInVAADIN( | |||
decodedRequestURI.substring(decodedContextPath.length()), | |||
request, response); | |||
String filePath = getStaticFilePath(request); | |||
if (filePath != null) { | |||
serveStaticResourcesInVAADIN(filePath, request, response); | |||
return true; | |||
} | |||
@@ -1284,8 +1267,25 @@ public class VaadinServlet extends HttpServlet implements Constants { | |||
} | |||
protected boolean isStaticResourceRequest(HttpServletRequest request) { | |||
return request.getRequestURI() | |||
.startsWith(request.getContextPath() + "/VAADIN/"); | |||
return getStaticFilePath(request) != null; | |||
} | |||
protected String getStaticFilePath(HttpServletRequest request) { | |||
String pathInfo = request.getPathInfo(); | |||
if (pathInfo == null) { | |||
return null; | |||
} | |||
// Servlet mapped as /* serves at /VAADIN | |||
// Servlet mapped as /foo/bar/* serves at /foo/bar/VAADIN | |||
if (pathInfo.startsWith("/VAADIN/")) { | |||
return pathInfo; | |||
} | |||
String servletPrefixedPath = request.getServletPath() + pathInfo; | |||
// Servlet mapped as /VAADIN/* | |||
if (servletPrefixedPath.startsWith("/VAADIN/")) { | |||
return servletPrefixedPath; | |||
} | |||
return null; | |||
} | |||
/** |
@@ -15,8 +15,11 @@ | |||
*/ | |||
package com.vaadin.server; | |||
import javax.servlet.http.HttpServletRequest; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
import org.mockito.Mockito; | |||
public class VaadinServletTest { | |||
@@ -57,4 +60,77 @@ public class VaadinServletTest { | |||
Assert.assertEquals("", VaadinServlet | |||
.getLastPathParameter("http://myhost.com/a;hello/;b=1,c=2/")); | |||
} | |||
@Test | |||
public void getStaticFilePath() { | |||
VaadinServlet servlet = new VaadinServlet(); | |||
// Mapping: /VAADIN/* | |||
// /VAADIN | |||
Assert.assertNull(servlet | |||
.getStaticFilePath(createServletRequest("/VAADIN", null))); | |||
// /VAADIN/ - not really sensible but still interpreted as a resource | |||
// request | |||
Assert.assertEquals("/VAADIN/", servlet | |||
.getStaticFilePath(createServletRequest("/VAADIN", "/"))); | |||
// /VAADIN/vaadinBootstrap.js | |||
Assert.assertEquals("/VAADIN/vaadinBootstrap.js", | |||
servlet.getStaticFilePath(createServletRequest("/VAADIN", | |||
"/vaadinBootstrap.js"))); | |||
// /VAADIN/foo bar.js | |||
Assert.assertEquals("/VAADIN/foo bar.js", servlet.getStaticFilePath( | |||
createServletRequest("/VAADIN", "/foo bar.js"))); | |||
// /VAADIN/.. - not normalized and disallowed in this method | |||
Assert.assertEquals("/VAADIN/..", servlet | |||
.getStaticFilePath(createServletRequest("/VAADIN", "/.."))); | |||
// Mapping: /* | |||
// / | |||
Assert.assertNull( | |||
servlet.getStaticFilePath(createServletRequest("", null))); | |||
// /VAADIN | |||
Assert.assertNull( | |||
servlet.getStaticFilePath(createServletRequest("", "/VAADIN"))); | |||
// /VAADIN/ | |||
Assert.assertEquals("/VAADIN/", servlet | |||
.getStaticFilePath(createServletRequest("", "/VAADIN/"))); | |||
// /VAADIN/foo bar.js | |||
Assert.assertEquals("/VAADIN/foo bar.js", servlet.getStaticFilePath( | |||
createServletRequest("", "/VAADIN/foo bar.js"))); | |||
// /VAADIN/.. - not normalized and disallowed in this method | |||
Assert.assertEquals("/VAADIN/..", servlet | |||
.getStaticFilePath(createServletRequest("", "/VAADIN/.."))); | |||
// /BAADIN/foo.js | |||
Assert.assertNull(servlet | |||
.getStaticFilePath(createServletRequest("", "/BAADIN/foo.js"))); | |||
// Mapping: /myservlet/* | |||
// /myservlet | |||
Assert.assertNull(servlet | |||
.getStaticFilePath(createServletRequest("/myservlet", null))); | |||
// /myservlet/VAADIN | |||
Assert.assertNull(servlet.getStaticFilePath( | |||
createServletRequest("/myservlet", "/VAADIN"))); | |||
// /myservlet/VAADIN/ | |||
Assert.assertEquals("/VAADIN/", servlet.getStaticFilePath( | |||
createServletRequest("/myservlet", "/VAADIN/"))); | |||
// /myservlet/VAADIN/foo bar.js | |||
Assert.assertEquals("/VAADIN/foo bar.js", servlet.getStaticFilePath( | |||
createServletRequest("/myservlet", "/VAADIN/foo bar.js"))); | |||
// /myservlet/VAADIN/.. - not normalized and disallowed in this method | |||
Assert.assertEquals("/VAADIN/..", servlet.getStaticFilePath( | |||
createServletRequest("/myservlet", "/VAADIN/.."))); | |||
// /myservlet/BAADIN/foo.js | |||
Assert.assertNull(servlet.getStaticFilePath( | |||
createServletRequest("/myservlet", "/BAADIN/foo.js"))); | |||
} | |||
private HttpServletRequest createServletRequest(String servletPath, | |||
String pathInfo) { | |||
HttpServletRequest request = Mockito.mock(HttpServletRequest.class); | |||
Mockito.when(request.getServletPath()).thenReturn(servletPath); | |||
Mockito.when(request.getPathInfo()).thenReturn(pathInfo); | |||
return request; | |||
} | |||
} |
@@ -146,6 +146,15 @@ | |||
</init-param> | |||
<async-supported>true</async-supported> | |||
</servlet> | |||
<servlet> | |||
<servlet-name>ResourcesFromServlet</servlet-name> | |||
<servlet-class>com.vaadin.launcher.ApplicationRunnerServlet</servlet-class> | |||
<init-param> | |||
<param-name>resources</param-name> | |||
<param-value>/servlet-with-resources</param-value> | |||
</init-param> | |||
<async-supported>true</async-supported> | |||
</servlet> | |||
<!-- For testing GAE - the deployment script changes this to use GAEVaadinServlet --> | |||
<servlet> | |||
@@ -221,6 +230,11 @@ | |||
<url-pattern>/VAADIN/*</url-pattern> | |||
</servlet-mapping> | |||
<servlet-mapping> | |||
<servlet-name>ResourcesFromServlet</servlet-name> | |||
<url-pattern>/servlet-with-resources/*</url-pattern> | |||
</servlet-mapping> | |||
<welcome-file-list> | |||
<welcome-file>index.html</welcome-file> | |||
</welcome-file-list> |
@@ -0,0 +1,68 @@ | |||
/* | |||
* Copyright 2000-2016 Vaadin Ltd. | |||
* | |||
* Licensed 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 com.vaadin.tests.applicationservlet; | |||
import java.util.List; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
import org.openqa.selenium.By; | |||
import org.openqa.selenium.WebElement; | |||
import com.vaadin.testbench.elements.CheckBoxElement; | |||
import com.vaadin.tests.components.label.LabelModes; | |||
import com.vaadin.tests.tb3.SingleBrowserTest; | |||
public class ServletWithResourcesTest extends SingleBrowserTest { | |||
@Override | |||
protected Class<?> getUIClass() { | |||
return LabelModes.class; | |||
} | |||
@Override | |||
protected String getDeploymentPath(Class<?> uiClass) { | |||
return super.getDeploymentPath(uiClass).replaceAll("/run/", | |||
"/servlet-with-resources/"); | |||
} | |||
@Test | |||
public void servletServesResources() { | |||
openTestURL(); | |||
Assert.assertEquals("Enabled", | |||
$(CheckBoxElement.class).first().getCaption()); | |||
List<WebElement> links = findElements(By.xpath("//head/link")); | |||
for (WebElement link : links) { | |||
String href = link.getAttribute("href"); | |||
Assert.assertTrue( | |||
"href '" + href | |||
+ "' should contain '/servlet-with-resources/VAADIN'", | |||
href.contains("/servlet-with-resources/VAADIN")); | |||
} | |||
List<WebElement> scripts = findElements(By.xpath("//head/script")); | |||
for (WebElement script : scripts) { | |||
String src = script.getAttribute("src"); | |||
Assert.assertTrue( | |||
"src '" + src | |||
+ "' should contain '/servlet-with-resources/VAADIN'", | |||
src.contains("/servlet-with-resources/VAADIN")); | |||
} | |||
} | |||
} |