From e11700a70ad08d04ab5e9dc716372eb13bbace5e Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Fri, 3 Feb 2023 16:00:43 +0200 Subject: [PATCH 1/4] fix: Provide correct mime type for javascript and css The correct mimetype for javascript is a requirement when loading javascript modules# --- .../proxy/internal/servlet/AwsServletContext.java | 7 ++++++- .../proxy/internal/servlet/AwsServletContextTest.java | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java index 1531315e9..3ffca36bf 100644 --- a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java +++ b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java @@ -167,7 +167,12 @@ public String getMimeType(String s) { if (mimeTypes == null) { mimeTypes = new MimetypesFileTypeMap(); } - + if (s.endsWith(".css")) { + return "text/css"; + } + if (s.endsWith(".js")) { + return "application/javascript"; + } // TODO: The getContentType method of the MimetypesFileTypeMap returns application/octet-stream // instead of null when the type cannot be found. We should replace with an implementation that // loads the System mime types ($JAVA_HOME/lib/mime.types diff --git a/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContextTest.java b/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContextTest.java index ed84462a5..4d61f428e 100644 --- a/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContextTest.java +++ b/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContextTest.java @@ -65,6 +65,13 @@ void getMimeType_mimeTypeOfCorrectFile_expectMime() { mimeType = ctx.getMimeType("file://" + tmpFilePath); assertEquals("text/plain", mimeType); } + @Test + void getMimeType_mimeTypeOfJavascript_expectApplicationJavascript() { + String tmpFilePath = TMP_DIR + "some.js"; + AwsServletContext ctx = new AwsServletContext(null); + String mimeType = ctx.getMimeType(tmpFilePath); + assertEquals("application/javascript", mimeType); + } @Test void getMimeType_unknownExtension_expectAppOctetStream() { From 7d2a74c405eb89a390bfdad2c1f4b49c4987b9f2 Mon Sep 17 00:00:00 2001 From: Dennis Kieselhorst Date: Mon, 6 Feb 2023 11:24:21 +0100 Subject: [PATCH 2/4] fix: provide more accurate result for content type --- .../internal/servlet/AwsServletContext.java | 36 +++++++++++++------ .../servlet/AwsServletContextTest.java | 2 +- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java index 3ffca36bf..0374c7a08 100644 --- a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java +++ b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java @@ -27,10 +27,14 @@ import jakarta.activation.MimetypesFileTypeMap; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Paths; import java.util.*; import java.util.stream.Collectors; @@ -160,23 +164,33 @@ public int getEffectiveMinorVersion() { @Override @SuppressFBWarnings("PATH_TRAVERSAL_IN") // suppressing because we are using the getValidFilePath - public String getMimeType(String s) { - if (s == null || !s.contains(".")) { + public String getMimeType(String file) { + if (file == null || !file.contains(".")) { return null; } + String mimeType = null; + try { + mimeType = Files.probeContentType(Paths.get(file)); + } catch (IOException | InvalidPathException e) { + log("unable to probe for content type, will use fallback", e); + } + + // MimetypesFileTypeMap is kept for backwards compatibility, remove in 2.0 if (mimeTypes == null) { mimeTypes = new MimetypesFileTypeMap(); } - if (s.endsWith(".css")) { - return "text/css"; + String backwardsCompatibleMimeType = mimeTypes.getContentType(file); + // The getContentType method of the MimetypesFileTypeMap + // returns MimetypesFileTypeMap.defaultType = application/octet-stream + // instead of null when the type cannot be found. + if (mimeType == null || (backwardsCompatibleMimeType != null && !backwardsCompatibleMimeType.equals(mimeType) + && !MediaType.APPLICATION_OCTET_STREAM.equals(backwardsCompatibleMimeType))) { + log("using type " + backwardsCompatibleMimeType + " from MimetypesFileTypeMap for " + file + + " instead of " + mimeType + " for backwards compatibility"); + mimeType = backwardsCompatibleMimeType; } - if (s.endsWith(".js")) { - return "application/javascript"; - } - // TODO: The getContentType method of the MimetypesFileTypeMap returns application/octet-stream - // instead of null when the type cannot be found. We should replace with an implementation that - // loads the System mime types ($JAVA_HOME/lib/mime.types - return mimeTypes.getContentType(s); + + return mimeType; } diff --git a/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContextTest.java b/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContextTest.java index 4d61f428e..04209e402 100644 --- a/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContextTest.java +++ b/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContextTest.java @@ -70,7 +70,7 @@ void getMimeType_mimeTypeOfJavascript_expectApplicationJavascript() { String tmpFilePath = TMP_DIR + "some.js"; AwsServletContext ctx = new AwsServletContext(null); String mimeType = ctx.getMimeType(tmpFilePath); - assertEquals("application/javascript", mimeType); + assertEquals("text/javascript", mimeType); } @Test From 332a8c5f1e98727ce00c3275bd7c5c200bf23577 Mon Sep 17 00:00:00 2001 From: Dennis Kieselhorst Date: Wed, 8 Feb 2023 16:38:41 +0100 Subject: [PATCH 3/4] fix: provide more accurate result for content type (another try as Files.probeContentType returns null on Lambda) --- .../internal/servlet/AwsServletContext.java | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java index 0374c7a08..46328ee70 100644 --- a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java +++ b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java @@ -27,14 +27,11 @@ import jakarta.activation.MimetypesFileTypeMap; import java.io.File; -import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; -import java.nio.file.Files; -import java.nio.file.InvalidPathException; -import java.nio.file.Paths; +import java.net.URLConnection; import java.util.*; import java.util.stream.Collectors; @@ -168,26 +165,31 @@ public String getMimeType(String file) { if (file == null || !file.contains(".")) { return null; } - String mimeType = null; - try { - mimeType = Files.probeContentType(Paths.get(file)); - } catch (IOException | InvalidPathException e) { - log("unable to probe for content type, will use fallback", e); - } - // MimetypesFileTypeMap is kept for backwards compatibility, remove in 2.0 + // this implementation would be nice but returns null on Lambda +// try { +// mimeType = Files.probeContentType(Paths.get(file)); +// } catch (IOException | InvalidPathException e) { +// log("unable to probe for content type, will use fallback", e); +// } + if (mimeTypes == null) { mimeTypes = new MimetypesFileTypeMap(); } - String backwardsCompatibleMimeType = mimeTypes.getContentType(file); + String mimeType = mimeTypes.getContentType(file); + // The getContentType method of the MimetypesFileTypeMap // returns MimetypesFileTypeMap.defaultType = application/octet-stream - // instead of null when the type cannot be found. - if (mimeType == null || (backwardsCompatibleMimeType != null && !backwardsCompatibleMimeType.equals(mimeType) - && !MediaType.APPLICATION_OCTET_STREAM.equals(backwardsCompatibleMimeType))) { - log("using type " + backwardsCompatibleMimeType + " from MimetypesFileTypeMap for " + file - + " instead of " + mimeType + " for backwards compatibility"); - mimeType = backwardsCompatibleMimeType; + // instead of null when the type cannot be found. trying to improve the result... + if (mimeType == null || MediaType.APPLICATION_OCTET_STREAM.equals(mimeType)) { + try { + String mimeTypeGuess = URLConnection.guessContentTypeFromName(new File(file).getName()); + if (mimeTypeGuess !=null) { + mimeType = mimeTypeGuess; + } + } catch (Exception e) { + log("couldn't find a better contentType than " + mimeType + " for file " + file, e); + } } return mimeType; From 0c0650edcdf2486868b91d473c7f0434daeccb0f Mon Sep 17 00:00:00 2001 From: Dennis Kieselhorst Date: Fri, 19 May 2023 11:14:24 +0200 Subject: [PATCH 4/4] fix: for 2.0 we return null instead of application/octet-stream if content type cannot be resolved (as per servlet-api docs), a fix to make probeContentType work in Lambda execution environment is being worked on by the Lambda service team --- aws-serverless-java-container-core/pom.xml | 5 ---- .../internal/servlet/AwsServletContext.java | 29 ++++++++----------- .../servlet/AwsServletContextTest.java | 4 +-- 3 files changed, 14 insertions(+), 24 deletions(-) diff --git a/aws-serverless-java-container-core/pom.xml b/aws-serverless-java-container-core/pom.xml index ff6e4b710..21f73ae99 100644 --- a/aws-serverless-java-container-core/pom.xml +++ b/aws-serverless-java-container-core/pom.xml @@ -71,11 +71,6 @@ commons-fileupload2 2.0-SNAPSHOT - - org.eclipse.angus - angus-mail - 2.0.1 - org.apache.httpcomponents diff --git a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java index 46328ee70..5211e68df 100644 --- a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java +++ b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContext.java @@ -17,23 +17,25 @@ import com.amazonaws.serverless.proxy.internal.SecurityUtils; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import jakarta.activation.spi.MimeTypeRegistryProvider; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jakarta.servlet.*; import jakarta.servlet.ServletContext; import jakarta.servlet.descriptor.JspConfigDescriptor; -import jakarta.activation.MimetypesFileTypeMap; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Paths; import java.util.*; -import java.util.stream.Collectors; /** @@ -61,7 +63,6 @@ public class AwsServletContext private Map initParameters; private AwsLambdaServletContainerHandler containerHandler; private Logger log = LoggerFactory.getLogger(AwsServletContext.class); - private MimetypesFileTypeMap mimeTypes; // lazily loaded in the getMimeType method //------------------------------------------------------------- @@ -166,22 +167,16 @@ public String getMimeType(String file) { return null; } - // this implementation would be nice but returns null on Lambda -// try { -// mimeType = Files.probeContentType(Paths.get(file)); -// } catch (IOException | InvalidPathException e) { -// log("unable to probe for content type, will use fallback", e); -// } + String mimeType = null; - if (mimeTypes == null) { - mimeTypes = new MimetypesFileTypeMap(); + // may not work on Lambda until mailcap package is present https://github.com/awslabs/aws-serverless-java-container/pull/504 + try { + mimeType = Files.probeContentType(Paths.get(file)); + } catch (IOException | InvalidPathException e) { + log("unable to probe for content type, will use fallback", e); } - String mimeType = mimeTypes.getContentType(file); - // The getContentType method of the MimetypesFileTypeMap - // returns MimetypesFileTypeMap.defaultType = application/octet-stream - // instead of null when the type cannot be found. trying to improve the result... - if (mimeType == null || MediaType.APPLICATION_OCTET_STREAM.equals(mimeType)) { + if (mimeType == null) { try { String mimeTypeGuess = URLConnection.guessContentTypeFromName(new File(file).getName()); if (mimeTypeGuess !=null) { diff --git a/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContextTest.java b/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContextTest.java index 04209e402..58d0b0542 100644 --- a/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContextTest.java +++ b/aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsServletContextTest.java @@ -74,10 +74,10 @@ void getMimeType_mimeTypeOfJavascript_expectApplicationJavascript() { } @Test - void getMimeType_unknownExtension_expectAppOctetStream() { + void getMimeType_unknownExtension_expectNull() { AwsServletContext ctx = new AwsServletContext(null); String mimeType = ctx.getMimeType("myfile.unkext"); - assertEquals("application/octet-stream", mimeType); + assertNull(mimeType); }