GROOVY-8294: Return 404 for non-existing paths in TemplateServlet when running 
from .war (closes #588)

- When TemplateServlet was used in application servers that don't unpack
  a war (i.e. when the real path of resources could not be retrieved),
  an internal server error was returned upon trying to retrieve a
  non-existing template file. Now, a 404 is returned.
- When running from a unpacked war, this had already worked before.


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/49ff8b20
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/49ff8b20
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/49ff8b20

Branch: refs/heads/GROOVY_2_5_X
Commit: 49ff8b203a44f8052b32874820e36f6973f46f62
Parents: 3ffaf66
Author: Thomas Reifenberger <[email protected]>
Authored: Thu Aug 17 23:11:30 2017 +0200
Committer: John Wagenleitner <[email protected]>
Committed: Thu Aug 24 18:33:10 2017 -0700

----------------------------------------------------------------------
 .../java/groovy/servlet/TemplateServlet.java    |  4 +
 .../groovy/servlet/TemplateServletTest.groovy   | 97 ++++++++++++++++++++
 2 files changed, 101 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/49ff8b20/subprojects/groovy-servlet/src/main/java/groovy/servlet/TemplateServlet.java
----------------------------------------------------------------------
diff --git 
a/subprojects/groovy-servlet/src/main/java/groovy/servlet/TemplateServlet.java 
b/subprojects/groovy-servlet/src/main/java/groovy/servlet/TemplateServlet.java
index 4c3e8be..553ed3c 100644
--- 
a/subprojects/groovy-servlet/src/main/java/groovy/servlet/TemplateServlet.java
+++ 
b/subprojects/groovy-servlet/src/main/java/groovy/servlet/TemplateServlet.java
@@ -441,6 +441,10 @@ public class TemplateServlet extends AbstractHttpServlet {
         } else {
             name = getScriptUri(request);
             URL url = servletContext.getResource(name);
+            if (url == null) {
+                response.sendError(HttpServletResponse.SC_NOT_FOUND);
+                return;
+            }
             getMillis = System.currentTimeMillis();
             template = getTemplate(url);
             getMillis = System.currentTimeMillis() - getMillis;

http://git-wip-us.apache.org/repos/asf/groovy/blob/49ff8b20/subprojects/groovy-servlet/src/test/groovy/groovy/servlet/TemplateServletTest.groovy
----------------------------------------------------------------------
diff --git 
a/subprojects/groovy-servlet/src/test/groovy/groovy/servlet/TemplateServletTest.groovy
 
b/subprojects/groovy-servlet/src/test/groovy/groovy/servlet/TemplateServletTest.groovy
new file mode 100644
index 0000000..ae05e6d
--- /dev/null
+++ 
b/subprojects/groovy-servlet/src/test/groovy/groovy/servlet/TemplateServletTest.groovy
@@ -0,0 +1,97 @@
+package groovy.servlet
+
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+
+import javax.servlet.ServletConfig
+import javax.servlet.ServletContext
+import javax.servlet.http.HttpServletRequest
+import javax.servlet.http.HttpServletResponse
+
+class TemplateServletTest {
+
+    TemplateServlet servlet
+
+    @Rule
+    public TemporaryFolder temporaryFolder = new TemporaryFolder()
+
+    @Before
+    void setUp() {
+        servlet = new TemplateServlet()
+    }
+
+    @Test
+    void test_service_for_existing_resource() {
+        def templateFile = temporaryFolder.newFile('template.gsp')
+        def url = templateFile.toURI().toURL()
+        def servletConfig = mockServletConfigForUrlResource(url)
+        HttpServletRequest request = mockRequest()
+        def (HttpServletResponse response, responseData) = mockResponse()
+        servlet.init(servletConfig)
+
+        servlet.service(request, response)
+
+        assert responseData.error == null
+        assert responseData.writer.toString() != ''
+        assert responseData.status == HttpServletResponse.SC_OK
+    }
+
+    @Test
+    void test_service_for_missing_resource() {
+        def url = null
+        def servletConfig = mockServletConfigForUrlResource(url)
+        HttpServletRequest request = mockRequest()
+        def (HttpServletResponse response, responseData) = mockResponse()
+        servlet.init(servletConfig)
+
+        servlet.service(request, response)
+
+        assert responseData.error == HttpServletResponse.SC_NOT_FOUND
+        assert responseData.writer.toString() == ''
+        assert responseData.status == null
+    }
+
+    private mockRequest() {
+        return [
+                getAttribute     : { null },
+                getPathInfo      : { 'pathInfo' },
+                getScriptUri     : 'scriptUri',
+                getServletPath   : { 'servletPath' },
+                getSession       : { null },
+                getParameterNames: { new Vector().elements() },
+                getHeaderNames   : { new Vector().elements() },
+        ] as HttpServletRequest
+    }
+
+    private mockResponse() {
+        def data = [
+                writer: new StringWriter(),
+                status: null,
+                error : null,
+        ]
+        def mock = [
+                getWriter     : { new PrintWriter(data.writer) },
+                sendError     : { error -> data.error = error },
+                setContentType: { contentType -> },
+                setStatus     : { status -> data.status = status },
+                flushBuffer   : { -> },
+        ] as HttpServletResponse
+        return [mock, data]
+    }
+
+    private mockServletConfigForUrlResource(URL mockedResourceUrl) {
+        def servletContext = [
+                getRealPath: { arg -> null },
+                getResource: { arg -> mockedResourceUrl },
+                log        : { msg -> },
+        ] as ServletContext
+        [
+                getServletName   : { 'name' },
+                getServletContext: { servletContext },
+                getInitParameter : { null },
+        ] as ServletConfig
+    }
+
+}

Reply via email to