diff --git a/CHANGES.txt b/CHANGES.txt index 0950f2dba40..9eac876d6cb 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -438,6 +438,8 @@ Release 0.22.0 - Unreleased HADOOP-7097. JAVA_LIBRARY_PATH missing base directory. (Noah Watkins via todd) + HADOOP-7093. Servlets should default to text/plain (todd) + Release 0.21.1 - Unreleased IMPROVEMENTS diff --git a/src/java/org/apache/hadoop/conf/ConfServlet.java b/src/java/org/apache/hadoop/conf/ConfServlet.java index 48473036812..5ca8537135f 100644 --- a/src/java/org/apache/hadoop/conf/ConfServlet.java +++ b/src/java/org/apache/hadoop/conf/ConfServlet.java @@ -69,12 +69,12 @@ public class ConfServlet extends HttpServlet { } if (FORMAT_XML.equals(format)) { - response.setContentType("text/xml"); + response.setContentType("text/xml; charset=utf-8"); } else if (FORMAT_JSON.equals(format)) { - response.setContentType("text/javascript"); + response.setContentType("application/json; charset=utf-8"); } - OutputStreamWriter out = new OutputStreamWriter(response.getOutputStream()); + Writer out = response.getWriter(); try { writeResponse(getConfFromContext(), out, format); } catch (BadFormatException bfe) { diff --git a/src/java/org/apache/hadoop/http/HttpServer.java b/src/java/org/apache/hadoop/http/HttpServer.java index ddab4552c84..890ecb82af2 100644 --- a/src/java/org/apache/hadoop/http/HttpServer.java +++ b/src/java/org/apache/hadoop/http/HttpServer.java @@ -739,8 +739,7 @@ public class HttpServer implements FilterContainer { return; } - PrintWriter out = new PrintWriter - (HtmlQuoting.quoteOutputStream(response.getOutputStream())); + PrintWriter out = response.getWriter(); ReflectionUtils.printThreadInfo(out, ""); out.close(); ReflectionUtils.logThreadInfo(LOG, "jsp requested", 1); @@ -858,12 +857,16 @@ public class HttpServer implements FilterContainer { HttpServletResponse httpResponse = (HttpServletResponse) response; String mime = inferMimeType(request); - if (mime == null || mime.equals("text/html")) { - // no extension or HTML with unspecified encoding, we want to + if (mime == null) { + httpResponse.setContentType("text/plain; charset=utf-8"); + } else if (mime.startsWith("text/html")) { + // HTML with unspecified encoding, we want to // force HTML with utf-8 encoding // This is to avoid the following security issue: // http://openmya.hacker.jp/hasegawa/security/utf7cs.html httpResponse.setContentType("text/html; charset=utf-8"); + } else if (mime.startsWith("application/xml")) { + httpResponse.setContentType("text/xml; charset=utf-8"); } chain.doFilter(quoted, httpResponse); } diff --git a/src/java/org/apache/hadoop/metrics/MetricsServlet.java b/src/java/org/apache/hadoop/metrics/MetricsServlet.java index c1a58a1d2c6..92c342108d1 100644 --- a/src/java/org/apache/hadoop/metrics/MetricsServlet.java +++ b/src/java/org/apache/hadoop/metrics/MetricsServlet.java @@ -112,17 +112,26 @@ public class MetricsServlet extends HttpServlet { return; } - PrintWriter out = new PrintWriter(response.getOutputStream()); String format = request.getParameter("format"); Collection allContexts = ContextFactory.getFactory().getAllContexts(); if ("json".equals(format)) { - // Uses Jetty's built-in JSON support to convert the map into JSON. - out.print(new JSON().toJSON(makeMap(allContexts))); + response.setContentType("application/json; charset=utf-8"); + PrintWriter out = response.getWriter(); + try { + // Uses Jetty's built-in JSON support to convert the map into JSON. + out.print(new JSON().toJSON(makeMap(allContexts))); + } finally { + out.close(); + } } else { - printMap(out, makeMap(allContexts)); + PrintWriter out = response.getWriter(); + try { + printMap(out, makeMap(allContexts)); + } finally { + out.close(); + } } - out.close(); } /** diff --git a/src/test/core/org/apache/hadoop/http/TestHttpServer.java b/src/test/core/org/apache/hadoop/http/TestHttpServer.java index 71ceebcc85a..95c5d0aef7d 100644 --- a/src/test/core/org/apache/hadoop/http/TestHttpServer.java +++ b/src/test/core/org/apache/hadoop/http/TestHttpServer.java @@ -19,6 +19,7 @@ package org.apache.hadoop.http; import java.io.IOException; import java.io.PrintStream; +import java.io.PrintWriter; import java.net.URLConnection; import java.net.HttpURLConnection; import java.net.URL; @@ -67,7 +68,7 @@ public class TestHttpServer extends HttpServerFunctionalTest { public void doGet(HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { - PrintStream out = new PrintStream(response.getOutputStream()); + PrintWriter out = response.getWriter(); Map params = request.getParameterMap(); SortedSet keys = new TreeSet(params.keySet()); for(String key: keys) { @@ -94,7 +95,7 @@ public class TestHttpServer extends HttpServerFunctionalTest { public void doGet(HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { - PrintStream out = new PrintStream(response.getOutputStream()); + PrintWriter out = response.getWriter(); SortedSet sortedKeys = new TreeSet(); Enumeration keys = request.getParameterNames(); while(keys.hasMoreElements()) { @@ -110,10 +111,25 @@ public class TestHttpServer extends HttpServerFunctionalTest { } } + @SuppressWarnings("serial") + public static class HtmlContentServlet extends HttpServlet { + @SuppressWarnings("unchecked") + @Override + public void doGet(HttpServletRequest request, + HttpServletResponse response + ) throws ServletException, IOException { + response.setContentType("text/html"); + PrintWriter out = response.getWriter(); + out.print("hello world"); + out.close(); + } + } + @BeforeClass public static void setup() throws Exception { server = createTestServer(); server.addServlet("echo", "/echo", EchoServlet.class); server.addServlet("echomap", "/echomap", EchoMapServlet.class); + server.addServlet("htmlcontent", "/htmlcontent", HtmlContentServlet.class); server.start(); baseUrl = getServerURL(server); } @@ -176,16 +192,30 @@ public class TestHttpServer extends HttpServerFunctionalTest { assertEquals(200, conn.getResponseCode()); assertEquals("text/css", conn.getContentType()); - // Servlets should have text/html with proper encoding + // Servlets should have text/plain with proper encoding by default URL servletUrl = new URL(baseUrl, "/echo?a=b"); conn = (HttpURLConnection)servletUrl.openConnection(); conn.connect(); assertEquals(200, conn.getResponseCode()); + assertEquals("text/plain; charset=utf-8", conn.getContentType()); + + // We should ignore parameters for mime types - ie a parameter + // ending in .css should not change mime type + servletUrl = new URL(baseUrl, "/echo?a=b.css"); + conn = (HttpURLConnection)servletUrl.openConnection(); + conn.connect(); + assertEquals(200, conn.getResponseCode()); + assertEquals("text/plain; charset=utf-8", conn.getContentType()); + + // Servlets that specify text/html should get that content type + servletUrl = new URL(baseUrl, "/htmlcontent"); + conn = (HttpURLConnection)servletUrl.openConnection(); + conn.connect(); + assertEquals(200, conn.getResponseCode()); assertEquals("text/html; charset=utf-8", conn.getContentType()); - // We should ignore parameters for mime types - ie a parameter - // ending in .css should not change mime type - servletUrl = new URL(baseUrl, "/echo?a=b.css"); + // JSPs should default to text/html with utf8 + servletUrl = new URL(baseUrl, "/testjsp.jsp"); conn = (HttpURLConnection)servletUrl.openConnection(); conn.connect(); assertEquals(200, conn.getResponseCode()); diff --git a/src/test/test-webapps/test/testjsp.jsp b/src/test/test-webapps/test/testjsp.jsp new file mode 100644 index 00000000000..23465da2959 --- /dev/null +++ b/src/test/test-webapps/test/testjsp.jsp @@ -0,0 +1,21 @@ +<%! +/* + * 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. + */ +%> +<%@ page contentType="text/html; charset=UTF-8" %> +Hello world!