2

I want Undertow to serve static files like .jpg, .png, .js, .css, .txt etc...

I edited the undertow subsystem in standalone.xml:

<subsystem xmlns="urn:jboss:domain:undertow:4.0">
        <buffer-cache name="default"/>
        <server name="default-server">
            <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
            <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
            <host name="default-host" alias="localhost">
                <location name="/images" handler="sh-resources"/>
                <filter-ref name="server-header"/>
                <filter-ref name="x-powered-by-header"/>
                <filter-ref name="content-png" predicate="path-suffix['.png']"/>
                <http-invoker security-realm="ApplicationRealm"/>
            </host>
        </server>
        <servlet-container name="default">
            <jsp-config/>
            <websockets/>
        </servlet-container>
        <handlers>
            <file name="sh-resources" path="/resource" directory-listing="true"/>
        </handlers>
        <filters>
            <response-header name="server-header" header-name="Server" header-value="WildFly/11"/>
            <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
            <response-header name="content-png" header-name="Content-Type" header-value="image/png"/>
        </filters>
    </subsystem>

I hav some files in my "/resource" folder "1.jpg", "2.png", "js.js", "c.css" in:

http://localhost:8080/resource/1.jpg --> shows nothing in browser

http://localhost:8080/resource/2.png --> shows nothing in browser

http://localhost:8080/resource/js.js --> shows nothing in browser

http://localhost:8080/resource/c.css --> shows file content in browser

http://localhost:8080/resource/test.html --> shows file content in browser

Why cant I see the images but can see the css & html content ? I think its because of incorrect mimetype setting ?

PS: I tried serving the static files via a Servlet and setting the correct Mimetypes -> everything works perfectly in browser (chrome) I can see the images and .js content (and all other file endings).

My Servlet Code (app is running at "/" of server):

@WebFilter("/*")  //get all requests
public class MasterFilter implements javax.servlet.Filter {
        //...
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {

    HttpServletRequest req = (HttpServletRequest) request;
    String path = req.getRequestURI();

    if (path.startsWith("/resource")) {         
        String mimetype = "text/html;charset=UTF-8";

        mimetype = path.contains(".png") ? "image/png" : mimetype;
        mimetype = path.contains(".jpg") || path.contains(".jpeg") ? "image/jpeg" : mimetype;
        mimetype = path.contains(".js") ? "text/javascript" : mimetype;
        mimetype = path.contains(".css") ? "text/css" : mimetype;
        response.setContentType(mimetype);
        chain.doFilter(request, response); // Goes to static resource in local folder "webapp/resource/"

    }
}

Any suggestions ? Thanks in advance.

EDIT:

The above solution with the Servlet Filter works fine. But thanks to @JGlass's answer I also found another solution. (keep in mind that I absolutely need my Servlet Filter):

  1. "MasterFilter" class forwards to "ServeResource" servlet:

    @WebFilter("/*") public class MasterFilter implements javax.servlet.Filter { /*...*/ public void doFilter(..){ /*...*/ if (path.startsWith("/resource")) {//forward to "ServeResource" servlet } } }

2."ServeResource" servlet serves static file:

@WebServlet("/resource/*")
public class ServeResource extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
 * @see HttpServlet#HttpServlet()
 */
public ServeResource() {
    super();
}

/**
 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse 
   response)
 */
protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException {

  ServletContext cntx= req.getServletContext();
  String fileUri = req.getRequestURI();
  System.out.println("fileUri: "+fileUri);
  // Get the absolute path of the image (or any file)
  String filename = cntx.getRealPath(fileUri);
  System.out.println("file realPath: "+filename);
  // retrieve mimeType dynamically
  String mime = cntx.getMimeType(filename);
  System.out.println("mime type: "+mime);
  if (mime == null) {
    resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    return;
  }

  resp.setContentType(mime);
  File file = new File(filename);
  resp.setContentLength((int)file.length());

  FileInputStream in = new FileInputStream(file);
  OutputStream out = resp.getOutputStream();

  // Copy the contents of the file to the output stream
   byte[] buf = new byte[1024];
   int count = 0;
   while ((count = in.read(buf)) >= 0) {
     out.write(buf, 0, count);
  } 
    out.close();
    in.close();
}

/**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
 */
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
}

}

3.web.xml contains extension mappings:

    <mime-mapping>
    <extension>html</extension>
    <mime-type>text/html</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>txt</extension>
    <mime-type>text/plain</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>js</extension>
    <mime-type>text/javascript</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>jpg</extension>
    <mime-type>image/jpeg</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>jpeg</extension>
    <mime-type>image/jpeg</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>png</extension>
    <mime-type>image/png</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>css</extension>
    <mime-type>text/css</mime-type>
</mime-mapping>
<mime-mapping>
    <extension>zip</extension>
    <mime-type>application/zip</mime-type>
</mime-mapping>
Blackpanther0001
  • 258
  • 1
  • 3
  • 14
  • 1
    *"I think its because of incorrect mimetype setting ?"* In other words, you haven't even checked the actual response headers..?? Why not? – BalusC Feb 07 '18 at 08:29
  • Any reason you're using the servlet filter to handle the mime types instead of just allowing the final servlet in the chain handle them in which case you don't need a servlet filter? My answer below is sort of two fold - I'd imagine you'd need the mime type mappings in the web.xml for static pages then the SO link for having a servlet handle mime types – JGlass Feb 07 '18 at 14:14
  • @JGlass I need the servlet filter for my routing setup. If I get a request for "/resource" -> serve static file -> else forward request to some other servlets – Blackpanther0001 Feb 07 '18 at 17:49
  • Oh, I understand now. Did you try BalusC's comment, you know how to do that in FF or IE correct? And stupid questions, but try sys out'ing path to make sure it contains what you expect it to contains - you dont have an else.. so *possibly* the IF statements not even getting hit Another thought, if it's a static resource... well I dunno, but maybe try adding the web.xml entries, see if they help? – JGlass Feb 07 '18 at 18:00
  • And as per this [Javax servlet filterchain setting contenttype as text plain in firefox](https://stackoverflow.com/questions/28610752/javax-servlet-filterchain-setting-contenttype-as-text-plain-in-firefox) i'd try the mime types in the web.xml as it was the correct answer – JGlass Feb 07 '18 at 18:04

1 Answers1

2

You can put your mime-types mapping in your web.xml. Here's an example:

<?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">
    <display-name>TestDynamicWAR</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>

    <servlet>
        <servlet-name>testServlet</servlet-name>
        <servlet-class>com.mycompany.test.TestServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>testServlet</servlet-name>
        <url-pattern>/test</url-pattern>
    </servlet-mapping>

    <mime-mapping>
        <extension>html</extension>
        <mime-type>text/html</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>txt</extension>
        <mime-type>text/plain</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>jpg</extension>
        <mime-type>image/jpeg</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>png</extension>
        <mime-type>image/png</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>js</extension>
        <mime-type>text/plain</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>css</extension>
        <mime-type>text/css</mime-type>
    </mime-mapping> 

</web-app>

Note: you likely don't need the css and js as they're already working. html and txt mime types are just an example as well

And I dont believe you need to deal with the servlet filter if you just want to handle the mime-types. This SO post has the servlet dealing with the mime types Output an image file from a servlet

JGlass
  • 1,427
  • 2
  • 12
  • 26