Repository: incubator-freemarker Updated Branches: refs/heads/2.3-gae 3bf80f67f -> 2531f51e7
Continued FREEMARKER-1 "Option to not to overwrite response ContentType in FreemarkerServlet": The output_format setting of the Template also sets the response contentType, similarly to the content_type custom attribute. Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/2531f51e Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/2531f51e Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/2531f51e Branch: refs/heads/2.3-gae Commit: 2531f51e7bc019480abdb35671b7c94bf75fc4b0 Parents: 3bf80f6 Author: ddekany <[email protected]> Authored: Sun Oct 18 12:27:50 2015 +0200 Committer: ddekany <[email protected]> Committed: Sun Oct 18 12:27:50 2015 +0200 ---------------------------------------------------------------------- .../ext/servlet/FreemarkerServlet.java | 49 ++++++++++++++++---- .../ext/servlet/FreemarkerServletTest.java | 29 ++++++++++++ .../ext/servlet/outputFormatHeader.ftl | 20 ++++++++ 3 files changed, 88 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2531f51e/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java b/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java index 291df35..b4aa296 100644 --- a/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java +++ b/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java @@ -38,6 +38,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import com.sun.org.apache.xml.internal.serialize.OutputFormat; + import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import freemarker.cache.ClassTemplateLoader; import freemarker.cache.FileTemplateLoader; @@ -45,6 +47,7 @@ import freemarker.cache.MultiTemplateLoader; import freemarker.cache.TemplateLoader; import freemarker.cache.WebappTemplateLoader; import freemarker.core.Configurable; +import freemarker.core.UndefinedOutputFormat; import freemarker.ext.jsp.TaglibFactory; import freemarker.ext.jsp.TaglibFactory.ClasspathMetaInfTldSource; import freemarker.ext.jsp.TaglibFactory.ClearMetaInfTldSource; @@ -135,13 +138,24 @@ import freemarker.template.utility.StringUtil; * HTTP client not to cache the returned page. The default is <tt>false</tt>.</li> * * <li><strong>{@value #INIT_PARAM_CONTENT_TYPE}</strong>: The Content-type HTTP header value used in the HTTP responses - * (unless {@value #INIT_PARAM_OVERRIDE_RESPONSE_CONTENT_TYPE} is set to {@code false} and the response - * {@code contentType} is already set by the time {@link FreemarkerServlet} is invoked). Defaults to - * <tt>"text/html"</tt>. The value may include the charset (e.g. <tt>"text/html; charset=utf-8"</tt>). If the charset is - * not specified in this init-param, then the charset (encoding) of the actual template file will be used (both in the - * response HTTP header and for encoding the output stream). Note that this setting can be overridden on a per-template - * basis by specifying a custom attribute named <tt>content_type</tt> in the <tt>attributes</tt> parameter of the - * <tt><#ftl></tt> directive.</li> + * when nothing else specifies the MIME type. The things that may specify the MIME type (and hence this init-param is + * ignored), starting with the highest precedence, are: + * <ol> + * <li>The template's custom attribute name <tt>content_type</tt> in the <tt>attributes</tt> parameter of the + * <tt><#ftl></tt> directive. This is a legacy feature, deprecated by the {@link OutputFormat} mechanism. + * <li>The {@linkplain Template#getOutputFormat() output format of the template}, if that has non-{@code null} MIME-type + * ({@link OutputFormat#getMediaType()}). When a template has no output format specified, {@link UndefinedOutputFormat} + * is used, which has {@code null} MIME-type. (The output format of a template is deduced from {@link Configuration} + * settings, or can be specified directly in the template, like {@code <#ftl outputFormat="HTML">}. See the FreeMarker + * Manual for more about the output format mechanism. Note that setting an output format may turns on auto-escaping, + * so it's not just about MIME types.) + * <li>If the {@value #INIT_PARAM_OVERRIDE_RESPONSE_CONTENT_TYPE} init-param is {@code false} (the default is + * {@code true}), then the value of {@link HttpServletResponse#getContentType()} is used if that's non-{@code null}. + * </ol> + * If none of the above gives a MIME type, then this init-param does. Defaults to <tt>"text/html"</tt>. The + * value may include the charset (e.g. <tt>"text/html; charset=utf-8"</tt>). If the charset is not specified in this + * init-param, then the charset (encoding) of the actual template file will appended after it, which, as per the + * Servlet specification, also sets the actual encoding used to write the response body.</li> * * <li><strong>{@value #INIT_PARAM_OVERRIDE_RESPONSE_CONTENT_TYPE}</strong> (since 2.3.24): Specifies if we should * always set the {@code contentType} in the {@link HttpServletResponse} to the value of the @@ -725,9 +739,9 @@ public class FreemarkerServlet extends HttpServlet { "Unexpected error when loading template " + StringUtil.jQuoteNoXSS(templatePath) + ".", e); } - Object attrContentType = template.getCustomAttribute("content_type"); - if (attrContentType != null) { - response.setContentType(attrContentType.toString()); + String templateSpecificContentType = getTemplateSpecificContentType(template); + if (templateSpecificContentType != null) { + response.setContentType(templateSpecificContentType); } else { if (overrideResponseContentType || response.getContentType() == null) { if (noCharsetInContentType) { @@ -767,6 +781,21 @@ public class FreemarkerServlet extends HttpServlet { } } + private String getTemplateSpecificContentType(final Template template) { + Object contentTypeAttr = template.getCustomAttribute("content_type"); + if (contentTypeAttr != null) { + // Convert with toString() for backward compatibility + return contentTypeAttr.toString(); + } + + String outputFormatMimeType = template.getOutputFormat().getMimeType(); + if (outputFormatMimeType != null) { + return outputFormatMimeType; + } + + return null; + } + private ServletException newServletExceptionWithFreeMarkerLogging(String message, Throwable cause) throws ServletException { if (cause instanceof TemplateException) { // For backward compatibility, we log into the same category as Environment did when http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2531f51e/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java b/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java index 9239ee0..5bb8dc9 100644 --- a/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java +++ b/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java @@ -198,6 +198,35 @@ public class FreemarkerServletTest { assertEquals(HttpServletResponse.SC_OK, response.getStatus()); assertEquals("text/plain", response.getContentType()); } + + @Test + public void testContentTypeInitParams_outputFormatAlwaysWins_DefaultOverriding() throws ServletException, IOException { + MockHttpServletRequest request = createMockHttpServletRequest(servletContext, "/outputFormatHeader.ftl"); + MockHttpServletResponse response = new MockHttpServletResponse(); + response.setContentType("application/json"); + assertEquals("application/json", response.getContentType()); + + createFreemarkerServlet().doGet(request, response); + LOG.debug("response content: " + response.getContentAsString()); + + assertEquals(HttpServletResponse.SC_OK, response.getStatus()); + assertEquals("text/plain", response.getContentType()); + } + + @Test + public void testContentTypeInitParams_outputFormatAlwaysWins_NoOverriding() throws ServletException, IOException { + MockHttpServletRequest request = createMockHttpServletRequest(servletContext, "/outputFormatHeader.ftl"); + MockHttpServletResponse response = new MockHttpServletResponse(); + response.setContentType("application/json"); + assertEquals("application/json", response.getContentType()); + + createFreemarkerServlet(FreemarkerServlet.INIT_PARAM_OVERRIDE_RESPONSE_CONTENT_TYPE, "false") + .doGet(request, response); + LOG.debug("response content: " + response.getContentAsString()); + + assertEquals(HttpServletResponse.SC_OK, response.getStatus()); + assertEquals("text/plain", response.getContentType()); + } private FreemarkerServlet createFreemarkerServlet(String... initParams) throws ServletException { MockServletConfig servletConfig = new MockServletConfig(servletContext); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2531f51e/src/test/resources/freemarker/ext/servlet/outputFormatHeader.ftl ---------------------------------------------------------------------- diff --git a/src/test/resources/freemarker/ext/servlet/outputFormatHeader.ftl b/src/test/resources/freemarker/ext/servlet/outputFormatHeader.ftl new file mode 100644 index 0000000..27d7b2e --- /dev/null +++ b/src/test/resources/freemarker/ext/servlet/outputFormatHeader.ftl @@ -0,0 +1,20 @@ +<#ftl outputFormat="plainText"> +<#-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +--> +foo \ No newline at end of file
