Repository: quarkusio/quarkus
Issue: Mime mappings in web.xml are ignored by undertow extension

I need to serve my wasm file with 'Content-Type' header `application/wasm` instead of `application/octet-stream`. I explicitly use the quarkus-undertow extension.

I tried to add a web.xml under src/main/resources/META-INF with a mime mapping for wasm files like this:
```
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         id="WebApp_ID" version="3.1">

    <mime-mapping>
        <extension>wasm</extension>
        <mime-type>application/wasm</mime-type>
    </mime-mapping>
</web-app>
```
The web.xml mime mapping seems to be ignored by the undertow extension.

**Expected behavior**
The Content-Type header for wasm files should be `application/wasm`.

**Actual behavior**
The Content-Type header for wasm files is still the original `application/octet-stream`.

**To Reproduce**
Steps to reproduce the behavior:
1. Add the quarkus-undertow extension
2. Add the web.xml from above under `src/main/resources/META-INF`
3. Add an empty file 'test.wasm' to `src/main/resources/META-INF/resources`
4. HTTP GET request to url `<quarkus-root>/test.wasm`
--> Content-Type header of response should be `application/wasm` like defined in the web.xml instead of `application/octet-stream`

**Environment (please complete the following information):**
 - Output of `uname -a` or `ver`: 
`Linux 5.3.16-300.fc31.x86_64 #1 SMP Fri Dec 13 17:59:04 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux`
 - Output of `java -version`: 
```
openjdk version "1.8.0_232"
OpenJDK Runtime Environment (build 1.8.0_232-b09)
OpenJDK 64-Bit Server VM (build 25.232-b09, mixed mode)
```
 - GraalVM version (if different from Java): CE 19.2.1
 - Quarkus version or git rev: 1.1.0.Final

**Additional context**
My original SO post: https://stackoverflow.com/q/59520915/3952202

Changed files:
extensions/undertow/deployment/src/main/java/io/quarkus/undertow/deployment/UndertowBuildStep.java
extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java
extensions/undertow/deployment/src/test/java/io/quarkus/undertow/test/ServletWebXmlTestCase.java

diff --git a/extensions/undertow/deployment/src/main/java/io/quarkus/undertow/deployment/UndertowBuildStep.java b/extensions/undertow/deployment/src/main/java/io/quarkus/undertow/deployment/UndertowBuildStep.java
index 015f199cf40..e16605c3b0b 100644
--- a/extensions/undertow/deployment/src/main/java/io/quarkus/undertow/deployment/UndertowBuildStep.java
+++ b/extensions/undertow/deployment/src/main/java/io/quarkus/undertow/deployment/UndertowBuildStep.java
@@ -66,6 +66,7 @@
 import org.jboss.metadata.web.spec.FiltersMetaData;
 import org.jboss.metadata.web.spec.HttpMethodConstraintMetaData;
 import org.jboss.metadata.web.spec.ListenerMetaData;
+import org.jboss.metadata.web.spec.MimeMappingMetaData;
 import org.jboss.metadata.web.spec.MultipartConfigMetaData;
 import org.jboss.metadata.web.spec.SecurityConstraintMetaData;
 import org.jboss.metadata.web.spec.ServletMappingMetaData;
@@ -463,6 +464,13 @@ public ServletDeploymentManagerBuildItem build(List<ServletBuildItem> servlets,
             }
         }
 
+        // MIME mappings
+        if (webMetaData.getMimeMappings() != null) {
+            for (MimeMappingMetaData mimeMapping : webMetaData.getMimeMappings()) {
+                recorder.addMimeMapping(deployment, mimeMapping.getExtension(), mimeMapping.getMimeType());
+            }
+        }
+
         for (ServletBuildItem servlet : servlets) {
             String servletClass = servlet.getServletClass();
             if (servlet.getLoadOnStartup() == 0) {
diff --git a/extensions/undertow/deployment/src/test/java/io/quarkus/undertow/test/ServletWebXmlTestCase.java b/extensions/undertow/deployment/src/test/java/io/quarkus/undertow/test/ServletWebXmlTestCase.java
index 66824b42d28..a960bf964f3 100644
--- a/extensions/undertow/deployment/src/test/java/io/quarkus/undertow/test/ServletWebXmlTestCase.java
+++ b/extensions/undertow/deployment/src/test/java/io/quarkus/undertow/test/ServletWebXmlTestCase.java
@@ -3,6 +3,7 @@
 import static org.hamcrest.Matchers.is;
 
 import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
 import org.jboss.shrinkwrap.api.asset.StringAsset;
 import org.jboss.shrinkwrap.api.spec.JavaArchive;
 import org.junit.jupiter.api.Test;
@@ -29,14 +30,20 @@ public class ServletWebXmlTestCase {
             "  <servlet-mapping>\\n" +
             "    <servlet-name>mapped</servlet-name>\\n" +
             "    <url-pattern>/mapped</url-pattern>\\n" +
-            "  </servlet-mapping>" +
+            "  </servlet-mapping>\\n" +
+            "\\n" +
+            "  <mime-mapping>\\n" +
+            "    <extension>wasm</extension>\\n" +
+            "    <mime-type>application/wasm</mime-type>\\n" +
+            "  </mime-mapping>" +
             "</web-app>";
 
     @RegisterExtension
     static QuarkusUnitTest runner = new QuarkusUnitTest()
             .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
                     .addClasses(WebXmlServlet.class)
-                    .addAsManifestResource(new StringAsset(WEB_XML), "web.xml"));
+                    .addAsManifestResource(new StringAsset(WEB_XML), "web.xml")
+                    .addAsManifestResource(EmptyAsset.INSTANCE, "resources/test.wasm"));
 
     @Test
     public void testWebXmlServlet() {
@@ -45,4 +52,10 @@ public void testWebXmlServlet() {
                 .body(is("web xml servlet"));
     }
 
+    @Test
+    public void testMimeMapping() {
+        RestAssured.when().get("/test.wasm").then()
+                .statusCode(200)
+                .contentType(is("application/wasm"));
+    }
 }
diff --git a/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java b/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java
index d66f8d71f3e..a1fdf23dd37 100644
--- a/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java
+++ b/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java
@@ -65,6 +65,7 @@
 import io.undertow.servlet.api.InstanceHandle;
 import io.undertow.servlet.api.ListenerInfo;
 import io.undertow.servlet.api.LoginConfig;
+import io.undertow.servlet.api.MimeMapping;
 import io.undertow.servlet.api.SecurityConstraint;
 import io.undertow.servlet.api.SecurityInfo;
 import io.undertow.servlet.api.ServletContainer;
@@ -310,6 +311,11 @@ public void registerListener(RuntimeValue<DeploymentInfo> info, Class<?> listene
                                 factory.instanceFactory(listenerClass))));
     }
 
+    public void addMimeMapping(RuntimeValue<DeploymentInfo> info, String extension,
+            String mimeType) throws Exception {
+        info.getValue().addMimeMapping(new MimeMapping(extension, mimeType));
+    }
+
     public void addServletInitParameter(RuntimeValue<DeploymentInfo> info, String name, String value) {
         info.getValue().addInitParameter(name, value);
     }