From 31b2f687eff5a77ea83c2279cc94c4c7158160dc Mon Sep 17 00:00:00 2001 From: Inigo Goiri Date: Wed, 29 Apr 2020 13:41:36 -0700 Subject: [PATCH] HDFS-15265. HttpFS: validate content-type in HttpFSUtils. Contributed by hemanthboyina. --- .../hadoop/fs/http/client/HttpFSUtils.java | 13 +++++++- .../fs/http/server/TestHttpFSServer.java | 31 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/fs/http/client/HttpFSUtils.java b/hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/fs/http/client/HttpFSUtils.java index fcc7bab15e..bd9baaa93f 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/fs/http/client/HttpFSUtils.java +++ b/hadoop-hdfs-project/hadoop-hdfs-httpfs/src/main/java/org/apache/hadoop/fs/http/client/HttpFSUtils.java @@ -33,6 +33,8 @@ import java.util.List; import java.util.Map; +import javax.ws.rs.core.MediaType; + /** * Utility methods used by HttpFS classes. */ @@ -127,8 +129,17 @@ static URL createURL(Path path, Map params, MapInputStream could not be * JSON parsed. */ - static Object jsonParse(HttpURLConnection conn) throws IOException { + public static Object jsonParse(HttpURLConnection conn) throws IOException { try { + String contentType = conn.getContentType(); + if (contentType != null) { + final MediaType parsed = MediaType.valueOf(contentType); + if (!MediaType.APPLICATION_JSON_TYPE.isCompatible(parsed)) { + throw new IOException("Content-Type \"" + contentType + + "\" is incompatible with \"" + MediaType.APPLICATION_JSON + + "\" (parsed=\"" + parsed + "\")"); + } + } JSONParser parser = new JSONParser(); return parser.parse( new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); diff --git a/hadoop-hdfs-project/hadoop-hdfs-httpfs/src/test/java/org/apache/hadoop/fs/http/server/TestHttpFSServer.java b/hadoop-hdfs-project/hadoop-hdfs-httpfs/src/test/java/org/apache/hadoop/fs/http/server/TestHttpFSServer.java index ae7e2c42ae..a5bbb92f21 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-httpfs/src/test/java/org/apache/hadoop/fs/http/server/TestHttpFSServer.java +++ b/hadoop-hdfs-project/hadoop-hdfs-httpfs/src/test/java/org/apache/hadoop/fs/http/server/TestHttpFSServer.java @@ -70,6 +70,8 @@ import org.apache.hadoop.fs.FsServerDefaults; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.XAttrCodec; +import org.apache.hadoop.fs.http.client.HttpFSUtils; +import org.apache.hadoop.fs.http.client.HttpFSFileSystem.Operation; import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.DataParam; import org.apache.hadoop.fs.http.server.HttpFSParametersProvider.NoRedirectParam; import org.apache.hadoop.fs.permission.AclEntry; @@ -88,6 +90,7 @@ import org.apache.hadoop.security.token.Token; import org.apache.hadoop.test.HFSTestCase; import org.apache.hadoop.test.HadoopUsersConfTestHelper; +import org.apache.hadoop.test.LambdaTestUtils; import org.apache.hadoop.test.TestDir; import org.apache.hadoop.test.TestDirHelper; import org.apache.hadoop.test.TestHdfs; @@ -1880,4 +1883,32 @@ public void testNoRedirectWithData() throws Exception { Assert.assertEquals(TestJettyHelper.getJettyURL() + "/webhdfs/v1" + path, location); } + + @Test + @TestDir + @TestJetty + @TestHdfs + public void testContentType() throws Exception { + createHttpFSServer(false, false); + FileSystem fs = FileSystem.get(TestHdfsHelper.getHdfsConf()); + Path dir = new Path("/tmp"); + Path file = new Path(dir, "foo"); + fs.mkdirs(dir); + fs.create(file); + + String user = HadoopUsersConfTestHelper.getHadoopUsers()[0]; + URL url = new URL(TestJettyHelper.getJettyURL(), MessageFormat.format( + "/webhdfs/v1/tmp/foo?user.name={0}&op=open&offset=1&length=2", user)); + + // test jsonParse with non-json type. + final HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod(Operation.OPEN.getMethod()); + conn.connect(); + + LambdaTestUtils.intercept(IOException.class, + "Content-Type \"text/html;charset=iso-8859-1\" " + + "is incompatible with \"application/json\"", + () -> HttpFSUtils.jsonParse(conn)); + conn.disconnect(); + } }